Compare commits

...

105 Commits

Author SHA1 Message Date
Alejandro
5621c2c394 Merge pull request #3942 from penpot/niwinz-staging-svg-parse-fill-fix
🐛 Fix several issues on svg path parsing
2023-12-28 10:41:52 +01:00
Alejandro
a506be2897 Merge pull request #3940 from penpot/eva-bugfixing-ui-1
💄 Fix some frontend bugs
2023-12-28 10:37:07 +01:00
Andrey Antukh
74447442b8 Add several improvements to svg path parser tests
And properly reorganize legacy implementations
2023-12-28 10:30:56 +01:00
Andrey Antukh
62b1dc2a4b 🐛 Fix incorrect arc to curve conversion in some cases 2023-12-28 10:30:56 +01:00
Andrey Antukh
88779dd50b 📎 Fix naming of fills react component 2023-12-28 10:30:56 +01:00
Andrey Antukh
ae4f14ece2 Reduce allocation on custom-shape-strokes react component 2023-12-28 10:30:56 +01:00
Andrey Antukh
ad185c4215 🐛 Assign correct fill to match standard svg behavior when no fils found
On parsing svg
2023-12-28 10:30:56 +01:00
Eva
1a1e9b4ecd 💄 Fix some frontend bugs 2023-12-28 09:49:47 +01:00
Andrey Antukh
63b264b494 🐛 Fix incorrect last command tracing on svg path parser 2023-12-27 15:38:14 +01:00
Andrey Antukh
fca33f8451 📎 Fix incorrect version 2023-12-27 12:15:02 +01:00
Hosted Weblate
d7fded19aa Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2023-12-27 12:00:17 +01:00
Hosted Weblate
7f47131499 Merge branch 'origin/develop' into Weblate. 2023-12-27 12:00:13 +01:00
Andrey Antukh
85829e53af Merge branch 'staging' into develop 2023-12-27 11:59:31 +01:00
Andrey Antukh
16b37230cc Merge branch 'translations' into staging 2023-12-27 11:59:15 +01:00
Stephan Paternotte
c2f48e4075 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-27 11:58:25 +01:00
Stephan Paternotte
6e5d5cfc50 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-27 11:58:25 +01:00
Stephan Paternotte
32439a52db 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-27 11:58:24 +01:00
Stas Haas
ce8c17e589 🌐 Add translations for: German.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-12-27 11:58:24 +01:00
Stas Haas
407e7186a4 🌐 Add translations for: German.
Currently translated at 99.6% (1316 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-12-27 11:58:24 +01:00
Swapnil C
a589d79043 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Aimee
5ce362df8e 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Locness
2120b40abe 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Louis Chance
705a1c8b10 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Oğuz Ersen
a9cafdfc9d 🌐 Add translations for: Turkish.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2023-12-27 11:58:24 +01:00
Luigi
0cb80febf0 🌐 Add translations for: French.
Currently translated at 88.2% (1165 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Luigi
804fe018ef 🌐 Add translations for: French.
Currently translated at 87.8% (1159 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-12-27 11:58:24 +01:00
Yaron Shahrabani
026c32fe00 🌐 Add translations for: Hebrew.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2023-12-27 11:58:24 +01:00
Hugo Vermaak
96d9786f83 🌐 Add translations for: Afrikaans.
Currently translated at 7.6% (101 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/af/
2023-12-27 11:58:24 +01:00
Madalena Melo
9a5c220c87 🌐 Added translation for: Afrikaans. 2023-12-27 11:58:24 +01:00
TheScientistPT
4a2fb6facd 🌐 Add translations for: Portuguese (Portugal).
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2023-12-27 11:58:24 +01:00
AlexTECPlayz
eb575e9daf 🌐 Add translations for: Romanian.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2023-12-27 11:58:24 +01:00
AlexTECPlayz
a7fc53f325 🌐 Add translations for: Romanian.
Currently translated at 99.3% (1311 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2023-12-27 11:58:24 +01:00
TheScientistPT
24bb49d0bf 🌐 Add translations for: Portuguese (Portugal).
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2023-12-27 11:58:24 +01:00
Yaron Shahrabani
67d3a7f9c5 🌐 Add translations for: Hebrew.
Currently translated at 98.3% (1298 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2023-12-27 11:58:24 +01:00
Linerly
1efc40b6c4 🌐 Add translations for: Indonesian.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2023-12-27 11:58:24 +01:00
Stas Haas
304f6ea96e 🌐 Add translations for: German.
Currently translated at 99.3% (1312 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-12-27 11:58:24 +01:00
Merih Güz
2509ab3a5d 🌐 Add translations for: Turkish.
Currently translated at 98.4% (1299 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2023-12-27 11:58:24 +01:00
Stephan Paternotte
163ce9f3b7 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-27 11:56:54 +01:00
Andrey Antukh
0643ba03a1 Merge branch 'staging' into develop 2023-12-27 11:55:38 +01:00
Andrey Antukh
49d719fb45 🐛 Fix incorrect stream handling on shape move
Bug introduced in the beicon2 upgrade part2 commit
2023-12-27 11:53:05 +01:00
Aitor
4fc892a856 🐛 Fix Update main component thumbnail 2023-12-26 14:51:42 +01:00
Andrey Antukh
88c7ac379b 🐛 Fix unexpected rx scheduler saturation on mouse movement burst
Fixed with custom trailing-edge throttling mechanism
2023-12-26 14:14:20 +01:00
Andrey Antukh
ccf063b8ef ⬆️ Upgrade to beicon2 (part2) 2023-12-26 14:14:20 +01:00
Andrey Antukh
96f5a33f5f ⬆️ Upgrade to beicon2 (part1) 2023-12-26 14:14:20 +01:00
Andrey Antukh
ecee15af5b Improve logging on websocket related code (backend) 2023-12-26 14:14:20 +01:00
Stephan Paternotte
607c3c4517 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-26 14:11:56 +01:00
Alejandro
7648836725 Merge pull request #3931 from penpot/alotor-fix-layout
🐛 Fix problem with absolutes inside grid
2023-12-26 11:41:44 +01:00
Stephan Paternotte
6b12645bfb 🌐 Add translations for: Dutch.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2023-12-22 16:12:30 +00:00
Andrés Moya
92934c6cdd 🔧 Add data-test to ease selection in e2e tests 2023-12-18 18:17:27 +01:00
alonso.torres
52c849ce4b 🐛 Fix problem with absolutes inside grid 2023-12-15 22:18:23 +01:00
Eva
f8dd86da34 💄 Add new UI to viewer area 2023-12-15 22:15:22 +01:00
Andrey Antukh
15f81e557c 🐛 Fix unexpected exception on importing some binary files 2023-12-15 17:54:26 +01:00
Andrey Antukh
60fc1a48a5 🔥 Remove obsolete entry on devenv log config 2023-12-15 17:54:26 +01:00
Eva Marco
51b3556b45 Merge pull request #3920 from penpot/ladybenko-fix-ui-modal-shared-library
🐛 fix modal text color + remove lines in shared library modal
2023-12-15 17:09:02 +01:00
Eva Marco
89c14b25ab Merge pull request #3915 from penpot/alotor-fixes-ui
Fixes new UI
2023-12-15 16:28:51 +01:00
Alejandro
051c0dce78 Merge pull request #3926 from penpot/niwinz-staging-bugfixes-2
🐛 More features related bugfixes
2023-12-15 16:16:39 +01:00
Andrey Antukh
a9dd55b8d2 🐛 Fix incorrect feature detection on frontend code 2023-12-15 16:09:57 +01:00
Andrey Antukh
ca50486639 Simplify feature handling on duplicate-file 2023-12-15 15:18:04 +01:00
Andrey Antukh
0ad2e8a0f2 Make retrieving fdata for thumbnail to no modify the file
This prevents that file to be considered opened just for creating
the thumbnail for it.
2023-12-15 15:18:04 +01:00
Andrey Antukh
ac20451ae7 Simplify feature handling on get-file 2023-12-15 15:18:04 +01:00
Andrey Antukh
47baa21d53 🐛 Fix some edge cases on feature handling on binfile import process 2023-12-15 15:18:04 +01:00
Andrey Antukh
eee28a5793 Simplify feature handling on components-v2 migration functions 2023-12-15 15:18:04 +01:00
Andrey Antukh
da15924de0 🔥 Remove empty lines on ui.dashboard ns file 2023-12-15 15:18:04 +01:00
Andrey Antukh
eabed4325a Integrate feature handling on file data migration
Make it less error prone
2023-12-15 15:18:04 +01:00
Andrey Antukh
f01cad9ce7 🐛 Fix incorrect error reporting on clone template error 2023-12-15 15:18:04 +01:00
Andrey Antukh
78260fbc42 🐛 Fix no migration are applied on accessing to a file 2023-12-15 15:18:04 +01:00
Belén Albeza
7b36a7df8b 🐛 fix line-height and color of the message text in all modals 2023-12-15 13:15:11 +01:00
Belén Albeza
05614a345d 🐛 fix modal text color + remove lines in shared library modal 2023-12-13 16:32:26 +01:00
alonso.torres
4832b718da 🐛 Fix problem with menu colors 2023-12-13 16:12:41 +01:00
alonso.torres
625f99c933 🐛 Fix tutorial button style 2023-12-13 16:12:41 +01:00
alonso.torres
6ed1d223bf 🐛 Add scroll to login 2023-12-13 16:12:41 +01:00
alonso.torres
39856c8f6a 🐛 Improve inspect tab 2023-12-13 16:12:41 +01:00
alonso.torres
e2446fcc62 🐛 Fix problems in inspect tab 2023-12-13 16:12:41 +01:00
alonso.torres
9834195f0e 🐛 Fix scroll so it's not hidden against palette 2023-12-13 16:12:41 +01:00
alonso.torres
ffa37d26fc 🐛 Add padding to inspect help 2023-12-13 16:12:41 +01:00
alonso.torres
db3d7af0b8 🐛 Hide guides parameters when hiding guides 2023-12-13 16:12:41 +01:00
alonso.torres
85c301c26b 🐛 Change order to create layout panel 2023-12-13 16:12:41 +01:00
alonso.torres
18d954faba 🐛 Fix overflow library name 2023-12-13 16:12:41 +01:00
alonso.torres
7d98833e4e 🐛 Reorder buttons for layout menu 2023-12-13 16:12:41 +01:00
alonso.torres
aa3fe1cd2b 🐛 Fix problems with assets 2023-12-13 16:12:41 +01:00
alonso.torres
e884cba002 🐛 Fix visual problems 2023-12-13 16:12:41 +01:00
alonso.torres
030ff398ed Improved dashboard thumbnails 2023-12-13 16:12:41 +01:00
alonso.torres
5522430afe 🐛 Fix hover style in dashboard 2023-12-13 16:12:41 +01:00
alonso.torres
6969f8be03 🐛 Fix presence widget 2023-12-13 16:12:41 +01:00
alonso.torres
9ac8e72b23 🐛 Fix strange visual in assets 2023-12-13 16:12:41 +01:00
Stas Haas
527d7afb00 🌐 Add translations for: German.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-11-28 10:04:03 +01:00
Stas Haas
d9fa8bbb06 🌐 Add translations for: German.
Currently translated at 99.6% (1316 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-11-23 11:04:30 +00:00
Swapnil C
780edaac3b 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-16 19:03:41 +01:00
Aimee
0b6633dc44 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-11 14:34:11 +01:00
Locness
ed2461c3ec 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-11 14:34:11 +01:00
Louis Chance
ae535b8ea1 🌐 Add translations for: French.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-11 14:34:11 +01:00
Oğuz Ersen
7c2fa2392f 🌐 Add translations for: Turkish.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2023-11-06 19:34:48 +01:00
Luigi
736a26a46a 🌐 Add translations for: French.
Currently translated at 88.2% (1165 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-06 19:34:47 +01:00
Luigi
23853345cc 🌐 Add translations for: French.
Currently translated at 87.8% (1159 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2023-11-05 18:33:20 +01:00
Yaron Shahrabani
69cffe43f3 🌐 Add translations for: Hebrew.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2023-10-16 06:09:42 +02:00
Hugo Vermaak
93df5354e5 🌐 Add translations for: Afrikaans.
Currently translated at 7.6% (101 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/af/
2023-10-13 20:01:12 +02:00
Madalena Melo
161e8b01a5 🌐 Added translation for: Afrikaans. 2023-10-12 11:45:43 +02:00
TheScientistPT
958b442b2e 🌐 Add translations for: Portuguese (Portugal).
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2023-10-11 14:01:31 +02:00
AlexTECPlayz
d3404bd359 🌐 Add translations for: Romanian.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2023-10-10 10:01:12 +00:00
AlexTECPlayz
b49ba9572e 🌐 Add translations for: Romanian.
Currently translated at 99.3% (1311 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2023-10-09 09:00:29 +00:00
TheScientistPT
6a397eb262 🌐 Add translations for: Portuguese (Portugal).
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2023-10-07 12:12:03 +00:00
Yaron Shahrabani
c09ca021e9 🌐 Add translations for: Hebrew.
Currently translated at 98.3% (1298 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2023-10-07 12:12:02 +00:00
Linerly
85fbc0352c 🌐 Add translations for: Indonesian.
Currently translated at 100.0% (1320 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2023-10-07 12:12:02 +00:00
Stas Haas
271384718d 🌐 Add translations for: German.
Currently translated at 99.3% (1312 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2023-10-07 12:12:01 +00:00
Merih Güz
ff8b6fbd8c 🌐 Add translations for: Turkish.
Currently translated at 98.4% (1299 of 1320 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2023-10-07 12:12:00 +00:00
321 changed files with 8806 additions and 3390 deletions

View File

@@ -15,7 +15,7 @@
:hooks
{:analyze-call
{app.common.data.macros/export hooks.export/export
potok.core/reify hooks.export/potok-reify
potok.v2.core/reify hooks.export/potok-reify
app.util.services/defmethod hooks.export/service-defmethod
app.common.record/defrecord hooks.export/penpot-defrecord
app.db/with-atomic hooks.export/penpot-with-atomic

View File

@@ -30,7 +30,6 @@
<Logger name="app.redis" level="info" />
<Logger name="app.rpc.rlimit" level="info" />
<Logger name="app.rpc.climit" level="info" />
<Logger name="app.rpc.mutations.files" level="info" />
<Logger name="app.common.files.migrations" level="info" />
<Logger name="app.loggers" level="debug" additivity="false">

View File

@@ -9,7 +9,6 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.features :as cfeat]
[app.common.files.changes :as cp]
[app.common.files.changes-builder :as fcb]
[app.common.files.helpers :as cfh]
@@ -769,12 +768,13 @@
fdata (migrate-graphics fdata)]
(update fdata :options assoc :components-v2 true)))))
(defn- prepare-fdata
[fdata id]
(-> fdata
(assoc :id id)
(fdata/process-pointers deref)
(fmg/migrate-data)))
(defn- get-file
[system id]
(binding [pmap/*load-fn* (partial fdata/load-pointer system id)]
(-> (files/get-file system id :migrate? false)
(update :data assoc :id id)
(update :data fdata/process-pointers deref)
(fmg/migrate-file))))
(defn- validate-file!
[file libs throw-on-validate?]
@@ -788,18 +788,10 @@
(defn- process-file
[{:keys [::db/conn] :as system} id & {:keys [validate? throw-on-validate?]}]
(let [file (binding [cfeat/*new* (atom #{})
pmap/*load-fn* (partial fdata/load-pointer system id)]
(-> (files/get-file system id :migrate? false)
(update :data prepare-fdata id)
(update :features into (deref cfeat/*new*))
(update :features cfeat/migrate-legacy-features)))
(let [file (get-file system id)
libs (->> (files/get-file-libraries conn id)
(into [file] (map (fn [{:keys [id]}]
(binding [pmap/*load-fn* (partial fdata/load-pointer system id)]
(-> (files/get-file system id :migrate? false)
(update :data prepare-fdata id))))))
(into [file] (comp (map :id) (map (partial get-file system))))
(d/index-by :id))
file (-> file

View File

@@ -81,6 +81,7 @@
(cond
(or (= code :spec-validation)
(= code :params-validation)
(= code :schema-validation)
(= code :data-validation))
(let [explain (ex/explain data)]
{::rres/status 400

View File

@@ -11,7 +11,7 @@
[app.common.exceptions :as ex]
[app.common.features :as cfeat]
[app.common.files.defaults :as cfd]
[app.common.files.migrations :as pmg]
[app.common.files.migrations :as fmg]
[app.common.files.validate :as fval]
[app.common.fressian :as fres]
[app.common.logging :as l]
@@ -701,23 +701,29 @@
(update :object-id #(str/replace-first % #"^(.*?)/" (str file-id "/")))))
thumbnails))
(defn- process-fdata
[fdata id]
(-> fdata
(dissoc :recent-colors)
(assoc :id id)
(cond-> (> (:version fdata) cfd/version)
(assoc :version cfd/version))
;; FIXME: We're temporarily activating all
;; migrations because a problem in the
;; environments messed up with the version
;; numbers When this problem is fixed delete
;; the following line
(assoc :version 22)
(pmg/migrate-data)
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)))
(defn- process-file
[{:keys [id] :as file}]
(-> file
(update :data (fn [fdata]
(-> fdata
(assoc :id id)
(dissoc :recent-colors)
(cond-> (> (:version fdata) cfd/version)
(assoc :version cfd/version))
;; FIXME: We're temporarily activating all
;; migrations because a problem in the
;; environments messed up with the version
;; numbers When this problem is fixed delete
;; the following line
(cond-> (> (:version fdata) 22)
(assoc :version 22)))))
(fmg/migrate-file)
(update :data (fn [fdata]
(-> fdata
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
(d/without-nils))))))
(defmethod read-section :v1/files
@@ -730,19 +736,7 @@
file-id (:id file)
file-id' (lookup-index file-id)
thumbnails (:thumbnails file)
file (update file :features cfeat/migrate-legacy-features)
features (-> enabled-features
(set/difference cfeat/frontend-only-features)
(set/union (cfeat/check-supported-features! (:features file))))]
;; All features that are enabled and requires explicit migration
;; are added to the state for a posterior migration step
(doseq [feature (-> enabled-features
(set/difference cfeat/no-migration-features)
(set/difference (:features file)))]
(vswap! *state* update :pending-to-migrate (fnil conj []) [feature file-id']))
thumbnails (:thumbnails file)]
(when (not= file-id expected-file-id)
(ex/raise :type :validation
@@ -773,16 +767,28 @@
(l/dbg :hint "update media references" ::l/sync? true)
(vswap! *state* update :media into (map #(update % :id lookup-index)) media))
(let [file (binding [cfeat/*new* (atom #{})]
(-> file
(assoc :id file-id')
(assoc :features features)
(assoc :project-id project-id)
(assoc :created-at timestamp)
(assoc :modified-at timestamp)
(dissoc :thumbnails)
(update :data process-fdata file-id')
(update :features into (deref cfeat/*new*))))
(let [file (-> file
(assoc :id file-id')
(process-file))
;; All features that are enabled and requires explicit migration are
;; added to the state for a posterior migration step.
_ (doseq [feature (-> enabled-features
(set/difference cfeat/no-migration-features)
(set/difference (:features file)))]
(vswap! *state* update :pending-to-migrate (fnil conj []) [feature file-id']))
file (-> file
(assoc :project-id project-id)
(assoc :created-at timestamp)
(assoc :modified-at timestamp)
(dissoc :thumbnails)
(update :features
(fn [features]
(let [features (cfeat/check-supported-features! features)]
(-> enabled-features
(set/difference cfeat/frontend-only-features)
(set/union features))))))
_ (when (contains? cf/flags :file-schema-validation)
(fval/validate-file-schema! file))
@@ -803,7 +809,6 @@
file))
file)
file (-> file
(update :features #(db/create-array conn "text" %))
(update :data blob/encode))]

View File

@@ -224,11 +224,8 @@
(defn- migrate-file
[{:keys [::db/conn] :as cfg} {:keys [id] :as file}]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)
pmap/*tracked* (pmap/create-tracked)
cfeat/*new* (atom #{})]
(let [file (-> (fmg/migrate-file file)
(update :features into (deref cfeat/*new*))
(update :features cfeat/migrate-legacy-features))]
pmap/*tracked* (pmap/create-tracked)]
(let [file (fmg/migrate-file file)]
;; NOTE: when file is migrated, we break the rule of no perform
;; mutations on get operations and update the file with all
@@ -250,11 +247,13 @@
file)))
(defn get-file
[{:keys [::db/conn] :as cfg} id & {:keys [project-id migrate?
[{:keys [::db/conn] :as cfg} id & {:keys [project-id
migrate?
include-deleted?
lock-for-update?]
:or {include-deleted? false
lock-for-update? false}}]
lock-for-update? false
migrate? true}}]
(dm/assert!
"expected cfg with valid connection"
(db/connection-map? cfg))

View File

@@ -10,6 +10,7 @@
[app.common.data.macros :as dm]
[app.common.features :as cfeat]
[app.common.files.helpers :as cfh]
[app.common.files.migrations :as fmg]
[app.common.geom.shapes :as gsh]
[app.common.schema :as sm]
[app.common.thumbnails :as thc]
@@ -105,24 +106,12 @@
(letfn [;; function responsible on finding the frame marked to be
;; used as thumbnail; the returned frame always have
;; the :page-id set to the page that it belongs.
(get-thumbnail-frame [file]
;; NOTE: this is a hack for avoid perform blocking
;; operation inside the for loop, clojure lazy-seq uses
;; synchronized blocks that does not plays well with
;; virtual threads where all rpc methods calls are
;; dispatched, so we need to perform the load operation
;; first. This operation forces all pointer maps load into
;; the memory.
;;
;; FIXME: this is no longer true with clojure>=1.12
(let [{:keys [data]} (update file :data feat.fdata/process-pointers pmap/load!)]
;; Then proceed to find the frame set for thumbnail
(d/seek #(or (:use-for-thumbnail %)
(:use-for-thumbnail? %)) ; NOTE: backward comp (remove on v1.21)
(for [page (-> data :pages-index vals)
frame (-> page :objects ctt/get-frames)]
(assoc frame :page-id (:id page))))))
(get-thumbnail-frame [{:keys [data]}]
(d/seek #(or (:use-for-thumbnail %)
(:use-for-thumbnail? %)) ; NOTE: backward comp (remove on v1.21)
(for [page (-> data :pages-index vals)
frame (-> page :objects ctt/get-frames)]
(assoc frame :page-id (:id page)))))
;; function responsible to filter objects data structure of
;; all unneeded shapes if a concrete frame is provided. If no
@@ -166,30 +155,29 @@
objects)))]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
(let [frame (get-thumbnail-frame file)
frame-id (:id frame)
page-id (or (:page-id frame)
(-> data :pages first))
(let [frame (get-thumbnail-frame file)
frame-id (:id frame)
page-id (or (:page-id frame)
(-> data :pages first))
page (dm/get-in data [:pages-index page-id])
page (cond-> page (pmap/pointer-map? page) deref)
frame-ids (if (some? frame) (list frame-id) (map :id (ctt/get-frames (:objects page))))
page (dm/get-in data [:pages-index page-id])
page (cond-> page (pmap/pointer-map? page) deref)
frame-ids (if (some? frame) (list frame-id) (map :id (ctt/get-frames (:objects page))))
obj-ids (map #(thc/fmt-object-id (:id file) page-id % "frame") frame-ids)
thumbs (get-object-thumbnails conn id obj-ids)]
obj-ids (map #(thc/fmt-object-id (:id file) page-id % "frame") frame-ids)
thumbs (get-object-thumbnails conn id obj-ids)]
(cond-> page
;; If we have frame, we need to specify it on the page level
;; and remove the all other unrelated objects.
(some? frame-id)
(-> (assoc :thumbnail-frame-id frame-id)
(update :objects filter-objects frame-id))
(cond-> page
;; If we have frame, we need to specify it on the page level
;; and remove the all other unrelated objects.
(some? frame-id)
(-> (assoc :thumbnail-frame-id frame-id)
(update :objects filter-objects frame-id))
;; Assoc the available thumbnails and prune not visible shapes
;; for avoid transfer unnecessary data.
:always
(update :objects assoc-thumbnails page-id thumbs))))))
;; Assoc the available thumbnails and prune not visible shapes
;; for avoid transfer unnecessary data.
:always
(update :objects assoc-thumbnails page-id thumbs)))))
(def ^:private
schema:get-file-data-for-thumbnail
@@ -221,7 +209,10 @@
:profile-id profile-id
:file-id file-id)
file (files/get-file cfg file-id)]
file (binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg file-id)]
(-> (files/get-file cfg file-id :migrate? false)
(update :data feat.fdata/process-pointers deref)
(fmg/migrate-file)))]
(-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-client-features! (:features params))

View File

@@ -106,41 +106,34 @@
media
media))
(update-fdata [fdata new-id]
(-> fdata
(assoc :id new-id)
(feat.fdata/process-pointers deref)
(pmg/migrate-data)
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
(d/without-nils)))]
(process-file [{:keys [id] :as file}]
(-> file
(update :data assoc :id id)
(update :data feat.fdata/process-pointers deref)
(pmg/migrate-file)
(update :data (fn [data]
(-> data
(update :pages-index relink-shapes)
(update :components relink-shapes)
(update :media relink-media)
(d/without-nils))))))]
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)
pmap/*tracked* (pmap/create-tracked)
cfeat/*new* (atom #{})]
(let [new-id (get index id)
file (binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)]
(-> (assoc file :id new-id)
(process-file)))
(let [new-id (get index id)
file (binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg id)
cfeat/*new* (atom #{})]
(-> file
(assoc :id new-id)
(update :data update-fdata new-id)
(update :features into (deref cfeat/*new*))
(update :features cfeat/migrate-legacy-features)))
file (if (contains? (:features file) "fdata/objects-map")
(feat.fdata/enable-objects-map file)
file)
file (if (contains? (:features file) "fdata/objects-map")
(feat.fdata/enable-objects-map file)
file)
file (if (contains? (:features file) "fdata/pointer-map")
(binding [pmap/*tracked* (pmap/create-tracked)]
(let [file (feat.fdata/enable-pointer-map file)]
(feat.fdata/persist-pointers! cfg (:id file))
file))
file)]
file))))
file (if (contains? (:features file) "fdata/pointer-map")
(binding [pmap/*tracked* (pmap/create-tracked)]
(let [file (feat.fdata/enable-pointer-map file)]
(feat.fdata/persist-pointers! cfg (:id file))
file))
file)]
file)))
(def sql:get-used-libraries
"select flr.*

View File

@@ -9,6 +9,7 @@
[app.common.spec :as us]
[app.db :as db]
[app.rpc :as-alias rpc]
[app.rpc.commands.files :refer [resolve-public-uri]]
[app.rpc.doc :as-alias doc]
[app.util.services :as sv]
[clojure.spec.alpha :as s]))
@@ -37,12 +38,15 @@
)
select distinct
f.id,
f.revn,
f.project_id,
f.created_at,
f.modified_at,
f.name,
f.is_shared
f.is_shared,
ft.media_id
from file as f
left join file_thumbnail as ft on (ft.file_id = f.id and ft.revn = f.revn)
inner join projects as pr on (f.project_id = pr.id)
where f.name ilike ('%' || ? || '%')
and (f.deleted_at is null or f.deleted_at > now())
@@ -50,10 +54,16 @@
(defn search-files
[conn profile-id team-id search-term]
(db/exec! conn [sql:search-files
profile-id team-id
profile-id team-id
search-term]))
(->> (db/exec! conn [sql:search-files
profile-id team-id
profile-id team-id
search-term])
(mapv (fn [row]
(if-let [media-id (:media-id row)]
(-> row
(dissoc :media-id)
(assoc :thumbnail-uri (resolve-public-uri media-id)))
(dissoc row :media-id))))))
(s/def ::team-id ::us/uuid)
(s/def ::search-files ::us/string)

View File

@@ -103,7 +103,7 @@
{:on-open
(fn on-open [channel]
(l/trace :fn "on-open" :conn-id id :channel channel)
(l/dbg :fn "on-open" :conn-id (str id))
(let [options (-> options
(assoc ::channel channel)
(on-connect))
@@ -114,10 +114,10 @@
:on-close
(fn on-close [_channel code reason]
(l/info :fn "on-ws-terminate"
:conn-id id
:code code
:reason reason)
(l/dbg :fn "on-close"
:conn-id (str id)
:code code
:reason reason)
(sp/close! close-ch))
:on-error
@@ -132,18 +132,19 @@
:on-pong
(fn on-pong [_channel data]
(l/trace :fn "on-pong" :data data)
(sp/put! hbeat-ch data))}))
(defn- handle-ping!
[{:keys [::id ::beats ::channel] :as wsp} beat-id]
(l/trace :hint "send ping" :beat beat-id :conn-id id)
(l/trc :hint "send ping" :beat beat-id :conn-id (str id))
(rws/ping channel (encode-beat beat-id))
(let [issued (swap! beats conj (long beat-id))]
(not (>= (count issued) max-missed-heartbeats))))
(defn- start-io-loop!
[{:keys [::id ::close-ch ::input-ch ::output-ch ::heartbeat-ch ::channel ::handler ::beats ::on-rcv-message ::on-snd-message] :as wsp}]
[{:keys [::id ::close-ch ::input-ch ::output-ch ::heartbeat-ch
::channel ::handler ::beats ::on-rcv-message ::on-snd-message]
:as wsp}]
(try
(handler wsp {:type :open})
(loop [i 0]
@@ -154,14 +155,16 @@
(identical? p ping-ch)
(if (handle-ping! wsp i)
(recur (inc i))
(rws/close channel 8802 "missing to many pings"))
(do
(l/trc :hint "closing" :reason "missing to many pings")
(rws/close channel 8802 "missing to many pings")))
(or (identical? p close-ch) (nil? msg))
(do :nothing)
(identical? p heartbeat-ch)
(let [beat (decode-beat msg)]
;; (l/trace :hint "pong" :beat beat :conn-id id)
(l/trc :hint "pong received" :beat beat :conn-id (str id))
(swap! beats disj beat)
(recur i))
@@ -179,7 +182,6 @@
(identical? p output-ch)
(let [message (on-snd-message msg)
message (t/encode-str message {:type :json-verbose})]
;; (l/trace :hint "writing message to output" :message msg)
(rws/send channel message)
(recur i))))))
@@ -188,12 +190,12 @@
(catch java.io.IOException _)
(catch InterruptedException _cause
(l/debug :hint "websocket thread interrumpted" :conn-id id))
(l/dbg :hint "websocket thread interrumpted" :conn-id id))
(catch Throwable cause
(l/error :hint "unhandled exception on websocket thread"
:conn-id id
:cause cause))
(l/err :hint "unhandled exception on websocket thread"
:conn-id id
:cause cause))
(finally
(try
(handler wsp {:type :close})
@@ -212,4 +214,4 @@
(catch Throwable cause
(throw cause)))
(l/trace :hint "websocket thread terminated" :conn-id id))))
(l/trc :hint "websocket thread terminated" :conn-id id))))

View File

@@ -358,13 +358,13 @@
(defn changed-attrs
"Returns the list of attributes that will change when `update-fn` is applied"
[object update-fn {:keys [attrs]}]
[object objects update-fn {:keys [attrs]}]
(let [changed?
(fn [old new attr]
(let [old-val (get old attr)
new-val (get new attr)]
(not= old-val new-val)))
new-obj (update-fn object)]
new-obj (update-fn object objects)]
(when-not (= object new-obj)
(let [attrs (or attrs (d/concat-set (keys object) (keys new-obj)))]
(filter (partial changed? object new-obj) attrs)))))
@@ -412,7 +412,7 @@
update-shape
(fn [changes id]
(let [old-obj (get objects id)
new-obj (update-fn old-obj)]
new-obj (update-fn old-obj objects)]
(if (= old-obj new-obj)
changes
(let [[rops uops] (-> (or attrs (d/concat-set (keys old-obj) (keys new-obj)))

View File

@@ -42,18 +42,21 @@
(reduce migrate-fn data (range (:version data 0) to-version))))))
(defn migrate-file
[{:keys [id data] :as file}]
(let [data (assoc data :id id)]
(-> file
(assoc ::orig-version (:version data))
(assoc :data (migrate-data data)))))
[{:keys [id data features] :as file}]
(binding [cfeat/*new* (atom #{})]
(let [file (-> file
(update :data assoc :id id)
(update :data migrate-data)
(update :features (fnil into #{}) (deref cfeat/*new*))
(update :features cfeat/migrate-legacy-features))]
(if (or (not= (:version data) (:version (:data file)))
(not= features (:features file)))
(vary-meta file assoc ::migrated true)
file))))
(defn migrated?
[{:keys [data] :as file}]
(or (::migrated file)
(let [version (:version data)]
(> version
(::orig-version file version)))))
[file]
(true? (-> file meta ::migrated)))
;; Default handler, noop
(defmethod migrate :default [data] data)

View File

@@ -353,3 +353,19 @@
(mth/max by1 y1)
(mth/min bx2 x2)
(mth/min by2 y2)))))
(defn fix-aspect-ratio
[bounds aspect-ratio]
(if aspect-ratio
(let [width (dm/get-prop bounds :width)
height (dm/get-prop bounds :height)
target-height (* width aspect-ratio)
target-width (* height (/ 1 aspect-ratio))]
(cond-> bounds
(> target-height height)
(-> (assoc :height target-height)
(update :y - (/ (- target-height height ) 2)))
(< target-height height)
(-> (assoc :width target-width)
(update :x - (/ (- target-width width ) 2)))))
bounds))

View File

@@ -1,3 +1,11 @@
/**
* Performance focused pure java implementation of the
* SVG path parser.
*
* @author KALEIDOS INC
* @license MPL-2.0 <https://www.mozilla.org/en-US/MPL/2.0/>
*/
package app.common.svg.path;
import java.util.Arrays;
@@ -61,9 +69,11 @@ public class Parser {
command = MOVE_TO;
params = new Object[] {K_X, this.params[0], K_Y, this.params[1]};
break;
case 'Z':
command = CLOSE_PATH;
break;
case 'L':
command = LINE_TO;
params = new Object[] {K_X, this.params[0], K_Y, this.params[1]};
@@ -636,8 +646,9 @@ public class Parser {
for (int i=0; i<pdata.size(); i++) {
Segment segment = pdata.get(i);
var currentCommand = segment.command;
switch(segment.command) {
switch(currentCommand) {
case 'M':
x = segment.params[0];
y = segment.params[1];
@@ -780,16 +791,6 @@ public class Parser {
var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi);
result.addAll(segments);
// if (rx == 0 || ry == 0) {
// segment.command = 'C';
// segment.params = new double[] {currentX, currentY, x, y, x, y};
// result.add(segment);
// } else if (currentX != x || currentY != y) {
// var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi);
// result.addAll(segments);
// }
currentX = x;
currentY = y;
@@ -803,7 +804,7 @@ public class Parser {
break;
}
lastCommand = segment.command;
lastCommand = currentCommand;
}
return result;
@@ -870,7 +871,6 @@ public class Parser {
}
private static void processCurve(double[] curve, double cx, double cy, double rx, double ry, double sinPhi, double cosPhi) {
double x0 = curve[0] * rx;
double y0 = curve[1] * ry;
double x1 = curve[2] * rx;
@@ -910,7 +910,13 @@ public class Parser {
double x1p = ((cosPhi * (x1 - x2)) / 2) + ((sinPhi * (y1 - y2)) / 2);
double y1p = ((-sinPhi * (x1 - x2)) / 2) + ((cosPhi * (y1 - y2)) / 2);
if (x1p == 0 || y1p == 0 || rx == 0 || ry == 0) {
if (x1p == 0 && y1p == 0) {
// we're asked to draw line to itself
return new ArrayList<>();
}
if (rx == 0 || ry == 0) {
// one of the radii is zero
return new ArrayList<>();
}

View File

@@ -2,7 +2,8 @@
* Arc to Bezier curves transformer
*
* Is a modified and google closure compatible version of the a2c
* functions by https://github.com/fontello/svgpath
* functions by https://github.com/fontello/svgpath used as reference
* implementation for tests
*
* @author KALEIDOS INC
* @license MIT License <https://opensource.org/licenses/MIT>
@@ -10,11 +11,11 @@
"use strict";
goog.provide("common_tests.arc_to_bezier");
goog.provide("app.common.svg.path.arc_to_bezier");
// https://raw.githubusercontent.com/fontello/svgpath/master/lib/a2c.js
goog.scope(function() {
const self = common_tests.arc_to_bezier;
const self = app.common.svg.path.arc_to_bezier;
var TAU = Math.PI * 2;
@@ -123,7 +124,7 @@ goog.scope(function() {
return [ x1, y1, x1 - y1*alpha, y1 + x1*alpha, x2 + y2*alpha, y2 - x2*alpha, x2, y2 ];
}
function a2c(x1, y1, x2, y2, fa, fs, rx, ry, phi) {
function calculate_beziers(x1, y1, x2, y2, fa, fs, rx, ry, phi) {
var sin_phi = Math.sin(phi * TAU / 360);
var cos_phi = Math.cos(phi * TAU / 360);
@@ -132,6 +133,8 @@ goog.scope(function() {
var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2;
var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2;
// console.log("L", x1p, y1p)
if (x1p === 0 && y1p === 0) {
// we're asked to draw line to itself
return [];
@@ -204,5 +207,5 @@ goog.scope(function() {
});
}
self.a2c = a2c;
self.calculateBeziers = calculate_beziers;
});

View File

@@ -0,0 +1,325 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.common.svg.path.legacy-parser1
"The first SVG Path parser implementation.
Written in a mix of CLJS and JS code and used in production until
1.19, used mainly for tests."
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.geom.shapes.path :as upg]
[app.common.svg :as csvg]
[app.common.svg.path.arc-to-bezier :as a2b]
[app.common.svg.path.command :as upc]
[cuerdas.core :as str]))
(def commands-regex #"(?i)[mzlhvcsqta][^mzlhvcsqta]*")
;; Matches numbers for path values allows values like... -.01, 10, +12.22
;; 0 and 1 are special because can refer to flags
(def num-regex #"[+-]?(\d+(\.\d+)?|\.\d+)(e[+-]?\d+)?")
(def flag-regex #"[01]")
(defn extract-params [cmd-str extract-commands]
(loop [result []
extract-idx 0
current {}
remain (-> cmd-str (subs 1) (str/trim))]
(let [[param type] (nth extract-commands extract-idx)
regex (case type
:flag flag-regex
#_:number num-regex)
match (re-find regex remain)]
(if match
(let [value (-> match first csvg/fix-dot-number d/read-string)
remain (str/replace-first remain regex "")
current (assoc current param value)
extract-idx (inc extract-idx)
[result current extract-idx]
(if (>= extract-idx (count extract-commands))
[(conj result current) {} 0]
[result current extract-idx])]
(recur result
extract-idx
current
remain))
(cond-> result
(seq current) (conj current))))))
;; Path specification
;; https://www.w3.org/TR/SVG11/paths.html
(defmulti parse-command (comp str/upper first))
(defmethod parse-command "M" [cmd]
(let [relative (str/starts-with? cmd "m")
param-list (extract-params cmd [[:x :number]
[:y :number]])]
(into [{:command :move-to
:relative relative
:params (first param-list)}]
(for [params (rest param-list)]
{:command :line-to
:relative relative
:params params}))))
(defmethod parse-command "Z" [_]
[{:command :close-path}])
(defmethod parse-command "L" [cmd]
(let [relative (str/starts-with? cmd "l")
param-list (extract-params cmd [[:x :number]
[:y :number]])]
(for [params param-list]
{:command :line-to
:relative relative
:params params})))
(defmethod parse-command "H" [cmd]
(let [relative (str/starts-with? cmd "h")
param-list (extract-params cmd [[:value :number]])]
(for [params param-list]
{:command :line-to-horizontal
:relative relative
:params params})))
(defmethod parse-command "V" [cmd]
(let [relative (str/starts-with? cmd "v")
param-list (extract-params cmd [[:value :number]])]
(for [params param-list]
{:command :line-to-vertical
:relative relative
:params params})))
(defmethod parse-command "C" [cmd]
(let [relative (str/starts-with? cmd "c")
param-list (extract-params cmd [[:c1x :number]
[:c1y :number]
[:c2x :number]
[:c2y :number]
[:x :number]
[:y :number]])
]
(for [params param-list]
{:command :curve-to
:relative relative
:params params})))
(defmethod parse-command "S" [cmd]
(let [relative (str/starts-with? cmd "s")
param-list (extract-params cmd [[:cx :number]
[:cy :number]
[:x :number]
[:y :number]])]
(for [params param-list]
{:command :smooth-curve-to
:relative relative
:params params})))
(defmethod parse-command "Q" [cmd]
(let [relative (str/starts-with? cmd "q")
param-list (extract-params cmd [[:cx :number]
[:cy :number]
[:x :number]
[:y :number]])]
(for [params param-list]
{:command :quadratic-bezier-curve-to
:relative relative
:params params})))
(defmethod parse-command "T" [cmd]
(let [relative (str/starts-with? cmd "t")
param-list (extract-params cmd [[:x :number]
[:y :number]])]
(for [params param-list]
{:command :smooth-quadratic-bezier-curve-to
:relative relative
:params params})))
(defmethod parse-command "A" [cmd]
(let [relative (str/starts-with? cmd "a")
param-list (extract-params cmd [[:rx :number]
[:ry :number]
[:x-axis-rotation :number]
[:large-arc-flag :flag]
[:sweep-flag :flag]
[:x :number]
[:y :number]])]
(for [params param-list]
{:command :elliptical-arc
:relative relative
:params params})))
(defn smooth->curve
[{:keys [params]} pos handler]
(let [{c1x :x c1y :y} (upg/calculate-opposite-handler pos handler)]
{:c1x c1x
:c1y c1y
:c2x (:cx params)
:c2y (:cy params)}))
(defn quadratic->curve
[sp ep cp]
(let [cp1 (-> (gpt/to-vec sp cp)
(gpt/scale (/ 2 3))
(gpt/add sp))
cp2 (-> (gpt/to-vec ep cp)
(gpt/scale (/ 2 3))
(gpt/add ep))]
{:c1x (:x cp1)
:c1y (:y cp1)
:c2x (:x cp2)
:c2y (:y cp2)}))
(defn arc->beziers*
[from-x from-y x y large-arc-flag sweep-flag rx ry x-axis-rotation]
(a2b/calculateBeziers from-x from-y x y large-arc-flag sweep-flag rx ry x-axis-rotation))
(defn arc->beziers [from-p command]
(let [to-command
(fn [[_ _ c1x c1y c2x c2y x y]]
{:command :curve-to
:relative (:relative command)
:params {:c1x c1x :c1y c1y
:c2x c2x :c2y c2y
:x x :y y}})
{from-x :x from-y :y} from-p
{:keys [rx ry x-axis-rotation large-arc-flag sweep-flag x y]} (:params command)
result (arc->beziers* from-x from-y x y large-arc-flag sweep-flag rx ry x-axis-rotation)]
(mapv to-command result)))
(defn simplify-commands
"Removes some commands and convert relative to absolute coordinates"
[commands]
(let [simplify-command
;; prev-pos : previous position for the current path. Necessary for relative commands
;; prev-start : previous move-to necessary for Z commands
;; prev-cc : previous command control point for cubic beziers
;; prev-qc : previous command control point for quadratic curves
(fn [[result prev-pos prev-start prev-cc prev-qc] [command _prev]]
(let [command (assoc command :prev-pos prev-pos)
command
(cond-> command
(:relative command)
(-> (assoc :relative false)
(d/update-in-when [:params :c1x] + (:x prev-pos))
(d/update-in-when [:params :c1y] + (:y prev-pos))
(d/update-in-when [:params :c2x] + (:x prev-pos))
(d/update-in-when [:params :c2y] + (:y prev-pos))
(d/update-in-when [:params :cx] + (:x prev-pos))
(d/update-in-when [:params :cy] + (:y prev-pos))
(d/update-in-when [:params :x] + (:x prev-pos))
(d/update-in-when [:params :y] + (:y prev-pos))
(cond->
(= :line-to-horizontal (:command command))
(d/update-in-when [:params :value] + (:x prev-pos))
(= :line-to-vertical (:command command))
(d/update-in-when [:params :value] + (:y prev-pos)))))
params (:params command)
orig-command command
command
(cond-> command
(= :line-to-horizontal (:command command))
(-> (assoc :command :line-to)
(update :params dissoc :value)
(assoc-in [:params :x] (:value params))
(assoc-in [:params :y] (:y prev-pos)))
(= :line-to-vertical (:command command))
(-> (assoc :command :line-to)
(update :params dissoc :value)
(assoc-in [:params :y] (:value params))
(assoc-in [:params :x] (:x prev-pos)))
(= :smooth-curve-to (:command command))
(-> (assoc :command :curve-to)
(update :params dissoc :cx :cy)
(update :params merge (smooth->curve command prev-pos prev-cc)))
(= :quadratic-bezier-curve-to (:command command))
(-> (assoc :command :curve-to)
(update :params dissoc :cx :cy)
(update :params merge (quadratic->curve prev-pos (gpt/point params) (gpt/point (:cx params) (:cy params)))))
(= :smooth-quadratic-bezier-curve-to (:command command))
(-> (assoc :command :curve-to)
(update :params merge (quadratic->curve prev-pos (gpt/point params) (upg/calculate-opposite-handler prev-pos prev-qc)))))
result (if (= :elliptical-arc (:command command))
(into result (arc->beziers prev-pos command))
(conj result command))
next-cc (case (:command orig-command)
:smooth-curve-to
(gpt/point (get-in orig-command [:params :cx]) (get-in orig-command [:params :cy]))
:curve-to
(gpt/point (get-in orig-command [:params :c2x]) (get-in orig-command [:params :c2y]))
(:line-to-horizontal :line-to-vertical)
(gpt/point (get-in command [:params :x]) (get-in command [:params :y]))
(gpt/point (get-in orig-command [:params :x]) (get-in orig-command [:params :y])))
next-qc (case (:command orig-command)
:quadratic-bezier-curve-to
(gpt/point (get-in orig-command [:params :cx]) (get-in orig-command [:params :cy]))
:smooth-quadratic-bezier-curve-to
(upg/calculate-opposite-handler prev-pos prev-qc)
(gpt/point (get-in orig-command [:params :x]) (get-in orig-command [:params :y])))
next-pos (if (= :close-path (:command command))
prev-start
(upc/command->point prev-pos command))
next-start (if (= :move-to (:command command)) next-pos prev-start)]
[result next-pos next-start next-cc next-qc]))
start (first commands)
start (cond-> start
(:relative start)
(assoc :relative false))
start-pos (gpt/point (:params start))]
(->> (map vector (rest commands) commands)
(reduce simplify-command [[start] start-pos start-pos start-pos start-pos])
(first))))
(defn parse [path-str]
(if (empty? path-str)
path-str
(let [clean-path-str
(-> path-str
(str/trim)
;; Change "commas" for spaces
(str/replace #"," " ")
;; Remove all consecutive spaces
(str/replace #"\s+" " "))
commands (re-seq commands-regex clean-path-str)]
(-> (mapcat parse-command commands)
(simplify-commands)))))

View File

@@ -4,9 +4,11 @@
;;
;; Copyright (c) KALEIDOS INC
(ns app.common.svg.path.legacy
"The first svg path parser implementation in pure clojure, used as reference impl
and for tests."
(ns app.common.svg.path.legacy-parser2
"The second SVG Path parser implementation.
Written in crossplatform CLJC code. Used meanwhile a hight
performance parser is developed in the 1.20 version."
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
@@ -16,7 +18,6 @@
[app.common.svg.path.command :as upc]
[cuerdas.core :as str]))
(def commands-regex #"(?i)[mzlhvcsqta][^mzlhvcsqta]*")
(def regex #"[+-]?(\d+(\.\d+)?|\.\d+)(e[+-]?\d+)?")
@@ -296,10 +297,10 @@
y1p (+ (/ (* (- sin-phi) (- x1 x2)) 2)
(/ (* cos-phi (- y1 y2)) 2))]
(if (or (zero? x1p)
(zero? y1p)
(zero? rx)
(zero? ry))
(if (or (and (zero? x1p)
(zero? y1p))
(and (zero? rx)
(zero? ry)))
[]
(let [
rx (mth/abs rx)
@@ -462,19 +463,10 @@
(reduce simplify-command [[start] start-pos start-pos start-pos start-pos])
(first))))
(defn parse
[path-str]
(if (empty? path-str)
path-str
(let [commands (re-seq commands-regex path-str)]
(->> (mapcat parse-command commands)
(simplify-commands)
(map (fn [segment]
;; (prn "LEGACY:" segment)
segment))))))
(simplify-commands)))))

View File

@@ -1,3 +1,11 @@
/**
* Performance focused pure javascript implementation of the
* SVG path parser.
*
* @author KALEIDOS INC
* @license MPL-2.0 <https://www.mozilla.org/en-US/MPL/2.0/>
*/
import cljs from "goog:cljs.core";
const MOVE_TO = cljs.keyword("move-to");
@@ -674,7 +682,13 @@ export function arcToBeziers(x1, y1, x2, y2, fa, fs, rx, ry, phi) {
let x1p = (cosPhi * (x1 - x2)) / 2 + (sinPhi * (y1 - y2)) / 2;
let y1p = (-sinPhi * (x1 - x2)) / 2 + (cosPhi * (y1 - y2)) / 2;
if (x1p === 0 || y1p === 0 || rx === 0 || ry === 0) {
if (x1p === 0 && y1p === 0) {
// we're asked to draw line to itself
return [];
}
if (rx === 0 || ry === 0) {
// one of the radii is zero
return [];
}
@@ -711,7 +725,7 @@ export function arcToBeziers(x1, y1, x2, y2, fa, fs, rx, ry, phi) {
// commands.
function simplifyPathData(pdata) {
var result = [];
var lastType = null;
var lastCommand = null;
var lastControlX = null;
var lastControlY = null;
@@ -724,8 +738,9 @@ function simplifyPathData(pdata) {
for (let i=0; i<pdata.length; i++) {
const segment = pdata[i];
const currentCommand = segment.command;
switch(segment.command) {
switch(currentCommand) {
case "M":
var x = segment.params[0];
var y = segment.params[1];
@@ -787,7 +802,7 @@ function simplifyPathData(pdata) {
var cx1, cy1;
if (lastType === "C" || lastType === "S") {
if (lastCommand === "C" || lastCommand === "S") {
cx1 = currentX + (currentX - lastControlX);
cy1 = currentY + (currentY - lastControlY);
} else {
@@ -813,7 +828,7 @@ function simplifyPathData(pdata) {
var x1, y1;
if (lastType === "Q" || lastType === "T") {
if (lastCommand === "Q" || lastCommand === "T") {
x1 = currentX + (currentX - lastControlX);
y1 = currentY + (currentY - lastControlY);
} else {
@@ -876,6 +891,7 @@ function simplifyPathData(pdata) {
currentX = x;
currentY = y;
} else if (currentX !== x || currentY !== y) {
var segments = arcToBeziers(currentX, currentY, x, y, fa, fs, rx, ry, phi);
result.push(...segments);
@@ -891,7 +907,7 @@ function simplifyPathData(pdata) {
break;
}
lastCommand = segment.command;
lastCommand = currentCommand;
}
return result;

View File

@@ -229,6 +229,7 @@
:svg-viewbox selrect
:svg-attrs attrs
:svg-transform transform
:strokes []
:fills []})
(gsh/translate-to-frame origin)))))
@@ -355,9 +356,9 @@
(assoc :svg-attrs props))))))
(defn setup-fill
[shape]
(let [color-attr (str/trim (dm/get-in shape [:svg-attrs :fill]))
color-attr (if (= color-attr "currentColor") clr/black color-attr)
[shape]
(let [color-attr (str/trim (dm/get-in shape [:svg-attrs :fill]))
color-attr (if (= color-attr "currentColor") clr/black color-attr)
color-style (str/trim (dm/get-in shape [:svg-attrs :style :fill]))
color-style (if (= color-style "currentColor") clr/black color-style)]
(cond-> shape
@@ -384,6 +385,7 @@
(update :svg-attrs dissoc :fillOpacity)
(assoc-in [:fills 0 :fill-opacity] (-> (dm/get-in shape [:svg-attrs :style :fillOpacity])
(d/parse-double 1)))))))
(defn- setup-stroke
[shape]
(let [attrs (get shape :svg-attrs)
@@ -422,7 +424,8 @@
(dissoc :stroke)
(dissoc :strokeLinecap)
(dissoc :strokeWidth)
(dissoc :strokeOpacity)))))]
(dissoc :strokeOpacity))))
(d/without-nils))]
(cond-> (assoc shape :svg-attrs attrs)
(some? color)
@@ -434,7 +437,7 @@
(and (some? color) (some? width))
(assoc-in [:strokes 0 :stroke-width] width)
(and (some? linecap) (= (:type shape) :path)
(and (some? linecap) (cfh/path-shape? shape)
(or (= linecap :round) (= linecap :square)))
(assoc :stroke-cap-start linecap
:stroke-cap-end linecap)
@@ -464,9 +467,6 @@
(-> (update-in [:svg-attrs :style] dissoc :mixBlendMode)
(assoc :blend-mode (-> (dm/get-in shape [:svg-attrs :style :mixBlendMode]) assert-valid-blend-mode)))))
(defn tag->name
"Given a tag returns its layer name"
[tag]

View File

@@ -1,7 +1,18 @@
(ns app.common.thumbnails
(:require [cuerdas.core :as str]))
(:require
[app.common.uuid :as uuid]
[cuerdas.core :as str]))
(defn fmt-object-id
"Returns ids formatted as a string (object-id)"
[file-id page-id frame-id tag]
(str/ffmt "%/%/%/%" file-id page-id frame-id tag))
(defn file-id?
"Returns ids formatted as a string (file-id)"
[object-id file-id]
(str/starts-with? object-id (str/concat file-id "/")))
(defn get-file-id
[object-id]
(uuid/uuid (str/slice object-id 0 (str/index-of object-id "/"))))

View File

@@ -676,7 +676,7 @@
[id cell])))
(defn remove-grid-column
[parent index]
[parent index objects]
(let [track-num (inc index)
@@ -692,10 +692,10 @@
(-> parent
(update :layout-grid-columns d/remove-at-index index)
(update :layout-grid-cells update-cells)
(assign-cells))))
(assign-cells objects))))
(defn remove-grid-row
[parent index]
[parent index objects]
(let [track-num (inc index)
decrease-track-num (make-decrease-track-num :row :row-span track-num)
@@ -710,7 +710,7 @@
(-> parent
(update :layout-grid-rows d/remove-at-index index)
(update :layout-grid-cells update-cells)
(assign-cells))))
(assign-cells objects))))
(defn- reorder-grid-tracks
"Swap the positions of the tracks info"
@@ -781,6 +781,7 @@
parent
(reorder-grid-tracks parent tracks-props from-index to-index)]
(cond-> parent
move-content?
(swap-track-content prop from-track to-track))))
@@ -828,14 +829,24 @@
(defn check-deassigned-cells
"Clean the cells whith shapes that are no longer in the layout"
[parent]
[parent objects]
(let [child? (set (:shapes parent))
cells (update-vals
(:layout-grid-cells parent)
(fn [cell] (update cell :shapes #(filterv child? %))))]
(let [child-set (set (:shapes parent))
(assoc parent :layout-grid-cells cells)))
assigned?
(fn [id]
(and (contains? child-set id)
(not (position-absolute? objects id))))
cells
(update-vals
(:layout-grid-cells parent)
(fn [cell]
(-> cell
(update :shapes #(filterv assigned? %)))))]
(-> parent
(assoc :layout-grid-cells cells))))
(defn overlapping-cells
"Find overlapping cells"
@@ -902,12 +913,12 @@
;; - Shape duplication
;; - (maybe) create group/frames. This case will assigna a cell that had one of its children
(defn assign-cells
[parent]
[parent objects]
(let [;; TODO: Remove this, shouldn't be happening
;;overlaps (overlapping-cells parent)
;;_ (when (not (empty? overlaps))
;; (.warn js/console "OVERLAPS" overlaps))
parent (cond-> (check-deassigned-cells parent)
parent (cond-> (check-deassigned-cells parent objects)
#_(d/not-empty? overlaps)
#_(fix-overlaps overlaps))
@@ -915,7 +926,9 @@
(into #{} (mapcat (comp :shapes second)) (:layout-grid-cells parent))
no-cell-shapes
(->> (:shapes parent) (remove shape-has-cell?))
(->> (:shapes parent)
(remove shape-has-cell?)
(remove (partial position-absolute? objects)))
parent (position-auto-shapes parent)]
@@ -1174,7 +1187,7 @@
(let [;; Temporary remove the children when moving them
frame (-> frame
(update :shapes #(d/removev children %))
(assign-cells))
(assign-cells objects))
children (->> children (remove #(position-absolute? objects %)))]
@@ -1182,7 +1195,7 @@
(update :shapes d/concat-vec children)
(cond-> (some? cell)
(push-into-cell children row column))
(assign-cells))))
(assign-cells objects))))
(defn add-children-to-index
[parent ids objects to-index]

View File

Binary file not shown.

View File

@@ -10,9 +10,9 @@
[app.common.pprint :as pp]
[app.common.math :as mth]
[app.common.svg.path :as svg.path]
[app.common.svg.path.legacy :as svg.path.legacy]
[app.common.svg.path.legacy-parser2 :as svg.path.legacy2]
[clojure.test :as t]
#?(:cljs [common-tests.arc-to-bezier :as impl])))
#?(:cljs [app.common.svg.path.legacy-parser2 :as svg.path.legacy1])))
(t/deftest parse-test-1
(let [data (str "m -994.563 4564.1423 149.3086 -52.8821 30.1828 "
@@ -23,14 +23,25 @@
result1 (->> (svg.path/parse data)
(mapv (fn [entry]
(update entry :params #(into (sorted-map) %)))))
result2 (->> (svg.path.legacy/parse data)
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]
(update entry :params #(into (sorted-map) %)))))
:clj nil)]
(t/is (= 15
(count result1)
(count result2)))
#?(:cljs
(t/is (= 15
(count result1)
(count result3))))
(dotimes [i (count result1)]
(let [item1 (nth result1 i)
item2 (nth result2 i)]
@@ -40,6 +51,14 @@
(t/is (= (:params item1)
(:params item2)))
#?(:cljs
(let [item3 (nth result3 i)]
(t/is (= (:command item1)
(:command item3)))
(t/is (= (:params item1)
(:params item3)))))
#_(println "------------------------")
#_(pp/pprint (dissoc item1 :relative))
#_(pp/pprint (dissoc item2 :prev-pos :relative))))))
@@ -92,7 +111,7 @@
result1 (->> (svg.path/parse data)
(mapv (fn [entry]
(update entry :params #(into (sorted-map) %)))))
result2 (->> (svg.path.legacy/parse data)
result2 (->> (svg.path.legacy2/parse data)
(mapv (fn [entry]
(update entry :params #(into (sorted-map) %)))))]
@@ -108,7 +127,6 @@
(t/is (= (:command item1)
(:command item2)))
;; (println "================" (:command item1))
;; (pp/pprint (:params item1))
;; (println "---------")
@@ -124,7 +142,7 @@
result1 (->> (svg.path/parse data)
(mapv (fn [entry]
(update entry :params #(into (sorted-map) %)))))
result2 (->> (svg.path.legacy/parse data)
result2 (->> (svg.path.legacy2/parse data)
(mapv (fn [entry]
(update entry :params #(into (sorted-map) %)))))]
@@ -142,6 +160,198 @@
(doseq [[k v] (:params item1)]
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001)))))))
(t/deftest parse-test-4
(let [data (str "m480 839-41-37c-70.512-64.747-128.807-120.601-174.884-167.561C218.039 587.48 181.333 "
"545.5 154 508.5S107.5 438 96.5 408 80 347.667 80 317c0-60.103 20.167-110.296 "
"60.5-150.577C180.833 126.141 230.667 106 290 106c38 0 73.167 9 105.5 27s60.5 44 84.5 "
"78c28-36 57.667-62.5 89-79.5S634 106 670 106c59.333 0 109.167 20.141 149.5 60.423C859.833 "
"206.704 880 256.897 880 317c0 30.667-5.5 61-16.5 91s-30.167 63.5-57.5 100.5-64.039 "
"78.98-110.116 125.939C649.807 681.399 591.512 737.253 521 802l-41 37Zm0-79c67.491-61.997 "
"123.03-115.163 166.618-159.498C690.206 556.167 724.833 517.333 750.5 484s43.667-63.045 "
"54-89.135c10.333-26.091 15.5-51.997 15.5-77.72 0-44.097-14-80.312-42-108.645S714.075 166 "
"670.225 166c-34.349 0-66.141 10.5-95.375 31.5C545.617 218.5 522 248 504 286h-49c-17.333"
"-37.333-40.617-66.667-69.85-88-29.234-21.333-61.026-32-95.375-32C245.925 166 210 180.167 "
"182 208.5s-42 64.605-42 108.816c0 25.789 5.167 51.851 15.5 78.184s28.333 56.333 54 90S270 "
"558 314 602s99.333 96.667 166 158Zm0-297Z")
expect [{:command :move-to, :params {:x 480.0, :y 839.0}}
{:command :line-to, :params {:x 439.0, :y 802.0}}
{:command :curve-to, :params {:c1x 368.488, :c1y 737.253, :c2x 310.193, :c2y 681.399, :x 264.116, :y 634.439}}
{:command :curve-to, :params {:c1x 218.039, :c1y 587.48, :c2x 181.333, :c2y 545.5, :x 154.0, :y 508.5}}
{:command :curve-to, :params {:c1x 126.667, :c1y 471.5, :c2x 107.5, :c2y 438.0, :x 96.5, :y 408.0}}
{:command :curve-to, :params {:c1x 85.5, :c1y 378.0, :c2x 80.0, :c2y 347.667, :x 80.0, :y 317.0}}
{:command :curve-to, :params {:c1x 80.0, :c1y 256.897, :c2x 100.167, :c2y 206.704, :x 140.5, :y 166.423}}
{:command :curve-to, :params {:c1x 180.833, :c1y 126.141, :c2x 230.667, :c2y 106.0, :x 290.0, :y 106.0}}
{:command :curve-to, :params {:c1x 328.0, :c1y 106.0, :c2x 363.16700000000003, :c2y 115.0, :x 395.5, :y 133.0}}
{:command :curve-to, :params {:c1x 427.83299999999997, :c1y 151.0, :c2x 456.0, :c2y 177.0, :x 480.0, :y 211.0}}
{:command :curve-to, :params {:c1x 508.0, :c1y 175.0, :c2x 537.667, :c2y 148.5, :x 569.0, :y 131.5}}
{:command :curve-to, :params {:c1x 600.333, :c1y 114.5, :c2x 634.0, :c2y 106.0, :x 670.0, :y 106.0}}
{:command :curve-to, :params {:c1x 729.333, :c1y 106.0, :c2x 779.167, :c2y 126.14099999999999, :x 819.5, :y 166.423}}
{:command :curve-to, :params {:c1x 859.833, :c1y 206.704, :c2x 880.0, :c2y 256.897, :x 880.0, :y 317.0}}
{:command :curve-to, :params {:c1x 880.0, :c1y 347.66700000000003, :c2x 874.5, :c2y 378.0, :x 863.5, :y 408.0}}
{:command :curve-to, :params {:c1x 852.5, :c1y 438.0, :c2x 833.333, :c2y 471.5, :x 806.0, :y 508.5}}
{:command :curve-to, :params {:c1x 778.667, :c1y 545.5, :c2x 741.961, :c2y 587.48, :x 695.884, :y 634.439}}
{:command :curve-to, :params {:c1x 649.807, :c1y 681.399, :c2x 591.512, :c2y 737.253, :x 521.0, :y 802.0}}
{:command :line-to, :params {:x 480.0, :y 839.0}}
{:command :close-path, :params {}}
{:command :move-to, :params {:x 480.0, :y 760.0}}
{:command :curve-to, :params {:c1x 547.491, :c1y 698.003, :c2x 603.03, :c2y 644.837, :x 646.6179999999999, :y 600.502}}
{:command :curve-to, :params {:c1x 690.206, :c1y 556.167, :c2x 724.833, :c2y 517.333, :x 750.5, :y 484.0}}
{:command :curve-to, :params {:c1x 776.167, :c1y 450.66700000000003, :c2x 794.167, :c2y 420.955, :x 804.5, :y 394.865}}
{:command :curve-to, :params {:c1x 814.833, :c1y 368.774, :c2x 820.0, :c2y 342.868, :x 820.0, :y 317.145}}
{:command :curve-to, :params {:c1x 820.0, :c1y 273.048, :c2x 806.0, :c2y 236.83299999999997, :x 778.0, :y 208.5}}
{:command :curve-to, :params {:c1x 750.0, :c1y 180.16700000000003, :c2x 714.075, :c2y 166.0, :x 670.225, :y 166.0}}
{:command :curve-to, :params {:c1x 635.876, :c1y 166.0, :c2x 604.0840000000001, :c2y 176.5, :x 574.85, :y 197.5}}
{:command :curve-to, :params {:c1x 545.617, :c1y 218.5, :c2x 522.0, :c2y 248.0, :x 504.0, :y 286.0}}
{:command :line-to, :params {:x 455.0, :y 286.0}}
{:command :curve-to, :params {:c1x 437.66700000000003, :c1y 248.667, :c2x 414.383, :c2y 219.333, :x 385.15, :y 198.0}}
{:command :curve-to, :params {:c1x 355.916, :c1y 176.667, :c2x 324.12399999999997, :c2y 166.0, :x 289.775, :y 166.0}}
{:command :curve-to, :params {:c1x 245.925, :c1y 166.0, :c2x 210.0, :c2y 180.167, :x 182.0, :y 208.5}}
{:command :curve-to, :params {:c1x 154.0, :c1y 236.833, :c2x 140.0, :c2y 273.105, :x 140.0, :y 317.31600000000003}}
{:command :curve-to, :params {:c1x 140.0, :c1y 343.105, :c2x 145.167, :c2y 369.16700000000003, :x 155.5, :y 395.5}}
{:command :curve-to,
:params {:c1x 165.833, :c1y 421.83299999999997, :c2x 183.833, :c2y 451.83299999999997, :x 209.5, :y 485.5}}
{:command :curve-to, :params {:c1x 235.167, :c1y 519.167, :c2x 270.0, :c2y 558.0, :x 314.0, :y 602.0}}
{:command :curve-to, :params {:c1x 358.0, :c1y 646.0, :c2x 413.33299999999997, :c2y 698.667, :x 480.0, :y 760.0}}
{:command :close-path, :params {}}
{:command :move-to, :params {:x 480.0, :y 463.0}}
{:command :close-path, :params {}}]
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) %)))))]
(t/is (= 41
(count result1)
(count result2)))
;; (pp/pprint result1 {:length 50})
(dotimes [i (count result1)]
(let [item1 (nth result1 i)
item2 (nth result2 i)
item3 (nth expect i)]
(t/is (= (:command item1)
(:command item2)
(:command item3)))
(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/deftest parse-test-5
(let [data (str "M363 826"
"q11-56 54-93"
"t101-37"
"h176"
"q22-35 34-75.179 12-40.178 12-84.821 0-125.357-87.321-212.679"
"Q565.357 236 440 236"
"t-212.679 87.321"
"Q140 410.643 140 536"
"q0 105 63 184.5T363 826Zm157 190"
"q-58 0-102"
"-36.5T363 888q-122-26-202.5-124T80 536q0-150 105-255t255-105"
"q150 0 255 105t105 "
"255q0 43-9.5 83.5T763 696q66 0 111.5 47T920 856q0 66-47 113t-113 47H520Zm-80"
"-485Zm200 325ZM520 956h240q42 0 71-29t29-71q0-42-29-71t-71-29H520q-42 0-71 29t"
"-29 71q0 42 29 71t71 29Zm-.175-70Q507 886 498.5 877.325"
"q-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.5Zm120 0Q627 886 618.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.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"
)
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) %)))))]
(t/is (= 76
(count result1)
(count result2)))
;; (pp/pprint result1 {:length 100})
;; (pp/pprint result2 {:length 50})
(dotimes [i (count result1)]
(let [item1 (nth result1 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/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"
"H7.582a2.5 2.5 0 0 1-2.5-2.5V6.565a2.5 2.5 0 0 1 2.5-2.5"
"h10.84a2.5 2.5 0 0 1 2.5 2.5V9a2.5 2.5 0 0 1-2.5 2.5Z"
"M7.582 5.065a1.5 1.5 0 0 0-1.5 1.5V9a1.5 1.5 0 0 0 1.5 1.5"
"h10.84a1.5 1.5 0 0 0 1.5-1.5V6.565a1.5 1.5 0 0 0-1.5-1.5Z"
"M13.451 19.938H7.582a2.5 2.5 0 0 1-2.5-2.5V15"
"a2.5 2.5 0 0 1 2.5-2.5h5.869a2.5 2.5 0 0 1 2.5 2.5v2.436"
"a2.5 2.5 0 0 1-2.5 2.502ZM7.582 13.5a1.5 1.5 0 0 0-1.5 1.5v2.436"
"a1.5 1.5 0 0 0 1.5 1.5h5.869a1.5 1.5 0 0 0 1.5-1.5V15"
"a1.5 1.5 0 0 0-1.5-1.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) %)))))]
(t/is (= 47
(count result1)
(count result2)))
;; (pp/pprint result1 {:length 100})
;; (pp/pprint result2 {:length 50})
(dotimes [i (count result1)]
(let [item1 (nth result1 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))
)))
#?(:cljs
(let [result3 (svg.path.legacy1/parse data)]
(t/is (= 47
(count result1)
(count result3)))
(dotimes [i (count result1)]
(let [item1 (nth result1 i)
item3 (nth result2 i)]
(t/is (= (:command item1)
(:command item3)))
(t/is (= (:params item1)
(:params item3)))))))))
(t/deftest arc-to-bezier-1
(let [expected1 [-1.6697754290362354e-13
-5.258016244624741e-13
@@ -179,7 +389,7 @@
(nth expected2 (+ i 2))
0.0000000001))))
(let [[result1 result2 :as total] (svg.path.legacy/arc->beziers* 0 0 30 50 0 0 1 162.55 162.45)]
(let [[result1 result2 :as total] (svg.path.legacy2/arc->beziers* 0 0 30 50 0 0 1 162.55 162.45)]
(t/is (= (count total) 2))
(dotimes [i (count result1)]
@@ -190,7 +400,96 @@
(dotimes [i (count result2)]
(t/is (mth/close? (nth result2 i)
(nth expected2 i)
0.000000000001))))))
0.000000000001))))
#?(:cljs
(let [[result1 result2 :as total] (svg.path.legacy1/arc->beziers* 0 0 30 50 0 0 1 162.55 162.45)]
(t/is (= (count total) 2))
(dotimes [i (count result1)]
(t/is (mth/close? (nth result1 i)
(nth expected1 i)
0.000000000001)))
(dotimes [i (count result2)]
(t/is (mth/close? (nth result2 i)
(nth expected2 i)
0.000000000001)))))
))
(t/deftest arc-to-bezier-2
(let [expected1 [3.0779999999999994,
20.448,
3.0780000082296834,
20.724142369096132,
3.3018576309038683,
20.94799998509884,
3.5779999999999994,
20.94799998509884]
expected2 [3.5779999999999994,
20.94799998509884,
3.854142369096131,
20.94799998509884,
4.077999991770315,
20.724142369096132,
4.077999999999999,
20.448]]
(let [[result1 result2 :as total] (->> (svg.path/arc->beziers 3.078 20.448 4.077999999999999 20.448 0 0 0.5 0.5 0)
(mapv (fn [segment]
(vec (.-params segment)))))]
(t/is (= (count total) 2))
;; (println "================" 11111111)
;; (pp/pprint expected1 {:width 50})
;; (println "------------")
;; (pp/pprint result1 {:width 50})
(dotimes [i (count result1)]
(t/is (mth/close? (nth result1 i)
(nth expected1 (+ i 2))
0.0000000001)))
(dotimes [i (count result2)]
(t/is (mth/close? (nth result2 i)
(nth expected2 (+ i 2))
0.0000000001))))
(let [[result1 result2 :as total] (svg.path.legacy2/arc->beziers* 3.078 20.448 4.077999999999999 20.448 0 0 0.5 0.5 0)]
(t/is (= (count total) 2))
;; (println "================" 11111111)
;; (pp/pprint expected1 {:width 50})
;; (println "------------")
;; (pp/pprint (vec result1) {:width 50})
(dotimes [i (count result1)]
(t/is (mth/close? (nth result1 i)
(nth expected1 i)
0.000000000001)))
(dotimes [i (count result2)]
(t/is (mth/close? (nth result2 i)
(nth expected2 i)
0.000000000001))))
#?(:cljs
(let [[result1 result2 :as total] (svg.path.legacy1/arc->beziers* 3.078 20.448 4.077999999999999 20.448 0 0 0.5 0.5 0)]
(t/is (= (count total) 2))
(dotimes [i (count result1)]
(t/is (mth/close? (nth result1 i)
(nth expected1 i)
0.000000000001)))
(dotimes [i (count result2)]
(t/is (mth/close? (nth result2 i)
(nth expected2 i)
0.000000000001)))))
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -220,14 +519,14 @@
"59.9137 -301.293 -1.0595 -51.375 25.7186 -261.0492 -7.706 ")
pattern [[:x :number] [:y :number]]]
(t/is (= expected (svg.path.legacy/extract-params cmdstr pattern)))))
(t/is (= expected (svg.path.legacy2/extract-params cmdstr pattern)))))
(t/deftest extract-params-legacy-2
(let [expected [{:x -994.563, :y 4564.1423 :r 0}]
cmdstr (str "m -994.563 4564.1423 0")
pattern [[:x :number] [:y :number] [:r :flag]]]
(t/is (= expected (svg.path.legacy/extract-params cmdstr pattern)))))
(t/is (= expected (svg.path.legacy2/extract-params cmdstr pattern)))))
(t/deftest extract-params-legacy-3
(let [cmdstr (str "a1.42 1.42 0 00-1.415-1.416 1.42 1.42 0 00-1.416 1.416 "
@@ -245,7 +544,7 @@
[:sweep-flag :flag]
[:x :number]
[:y :number]]
result (svg.path.legacy/extract-params cmdstr pattern)]
result (svg.path.legacy2/extract-params cmdstr pattern)]
(t/is (= (nth result 0)
(nth expected 0)))

View File

@@ -6,10 +6,17 @@
org.clojure/clojure {:mvn/version "1.11.1"}
binaryage/devtools {:mvn/version "RELEASE"}
metosin/reitit-core {:mvn/version "0.5.18"}
funcool/beicon {:mvn/version "2021.07.05-1"}
funcool/okulary {:mvn/version "2022.04.11-16"}
funcool/potok {:mvn/version "2022.12.16-71"}
funcool/potok2
{:git/tag "v2.0"
:git/sha "2bb377b"
:git/url "https://github.com/funcool/potok.git"}
funcool/beicon2
{:git/tag "v2.0"
:git/sha "e7135e0"
:git/url "https://github.com/funcool/beicon.git"}
funcool/rumext
{:git/tag "v2.7"

View File

@@ -46,6 +46,7 @@
"@storybook/react": "^7.5.3",
"@storybook/react-vite": "^7.5.3",
"@storybook/testing-library": "^0.2.2",
"@types/node": "^20.10.5",
"animate.css": "^4.1.1",
"autoprefixer": "^10.4.15",
"concurrently": "^8.2.2",
@@ -73,6 +74,7 @@
"sass": "^1.66.1",
"shadow-cljs": "2.26.2",
"storybook": "^7.5.3",
"typescript": "^5.3.3",
"vite": "^5.0.2"
},
"dependencies": {
@@ -90,7 +92,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-virtualized": "^9.22.3",
"rxjs": "~7.8.1",
"rxjs": "8.0.0-alpha.13",
"sax": "^1.2.4",
"source-map-support": "^0.5.21",
"tdigest": "^0.1.2",

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M10.357 2.813h2.828v2.829m-10.37 4.713v2.829h2.828m7.071-9.9l-9.428 9.429z"/>
</svg>

After

Width:  |  Height:  |  Size: 206 B

View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 273 KiB

After

Width:  |  Height:  |  Size: 279 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M2.4 8a6 6 0 111.758 4.242M2.4 8l2.1-2zm0 0L1 5.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 182 B

View File

@@ -148,6 +148,7 @@
stroke: var(--button-tertiary-foreground-color-active);
}
}
&:global(.disabled),
&[disabled],
&:disabled {

View File

@@ -4,7 +4,7 @@
//
// Copyright (c) KALEIDOS INC
@use "sass:color" as color;
@use "sass:color";
:root {
// DARK
@@ -25,16 +25,19 @@
--dark-ok-color: var(--strong-green);
--dark-warning-color: #ff6432;
--dark-pending-color: var(--lilac);
--dark-error-color: #ec1f1f;
--dark-error-color: #ff3277;
--default-presence-color: #dee563;
// LIGHT
--light-gray-1: #fff;
--light-gray-2: #e8eaee;
--light-gray-2-30: rgba(232, 234, 238, 0.3);
--light-gray-2-80: rgba(232, 234, 238, 0.8);
--light-gray-3: #f3f4f6;
--light-gray-4: #eef0f2;
--black: #000;
--off-black: #495e74;
--off-black-30: #{color.change(#495e74, $alpha: 0.3)};
--purple: #6911d4;
--purple-30: rgba(105, 17, 212, 0.2);
--blue: #1345aa;

View File

@@ -157,6 +157,8 @@
.btn-primary {
@extend .button-primary;
text-transform: uppercase;
font-size: $fs-14;
font-weight: $fw400;
}
.btn-secondary {

View File

@@ -14,6 +14,7 @@
--scrollbar-background-color: var(--color-foreground-secondary);
--panel-background-color: var(--color-background-primary);
--panel-title-background-color: var(--color-background-secondary);
--presence-color: var(--default-presence-color);
// BUTTONS
--button-foreground-hover: var(--color-accent-primary);
@@ -179,7 +180,7 @@
--menu-shortcut-foreground-color: var(--color-foreground-secondary);
--menu-shortcut-foreground-color-selected: var(--color-foreground-primary);
--menu-shortcut-foreground-color-hover: var(--color-foreground-primary);
--menu-shadow-color: var(--color-background-subtle);
--menu-shadow-color: var(--shadow-color);
--menu-background-color-disabled: var(--color-background-primary);
--menu-foreground-color-disabled: var(--color-foreground-secondary);
--menu-border-color-disabled: var(--color-background-quaternary);
@@ -297,4 +298,16 @@
--tag-background-color: var(--color-accent-primary);
--link-foreground-color: var(--color-accent-primary);
--resize-area-background-color: var(--color-background-primary);
--resize-area-border-color: var(--color-background-quaternary);
// VIEWER
--viewer-background-color: var(--color-background-secondary);
--viewer-paginator-background-color: var(--color-background-tertiary);
--viewer-controls-background-color: var(--color-background-primary);
--viewer-inspect-border-color: var(--color-background-tertiary);
--viewer-thumbnails-control-foreground-color: var(--color-foreground-secondary);
--viewer-thumbnail-border-color: var(--color-accent-primary);
--viewer-thumbnail-background-color-selected: var(--color-accent-primary-muted);
}

View File

@@ -63,6 +63,13 @@
line-height: 1.2;
}
@mixin codeTypography {
font-family: "robotomono", monospace;
font-size: $fs-12;
font-weight: $fw400;
line-height: 1.2;
}
@mixin textEllipsis {
max-width: 99%;
overflow: hidden;

View File

@@ -21,6 +21,7 @@
--color-accent-primary-muted: var(--green-30);
--color-accent-secondary: var(--lilac);
--color-accent-tertiary: var(--strong-green);
--overlay-color: rgba(0, 0, 0, 0.4);
--ok-color: var(--dark-ok-color);
--warning-color: var(--dark-warning-color);
@@ -28,5 +29,8 @@
--error-color: var(--dark-error-color);
--canvas-color: var(--color-canvas);
--shadow-color: var(--dark-gray-2-30);
--radio-button-box-shadow: 0 0 0 1px var(--dark-gray-2-30) inset;
@include meta.load-css("hljs-dark-theme");
}

View File

@@ -1,98 +1,124 @@
/**
* Panda Syntax Theme for Highlight.js
* Based on: https://github.com/tinkertrain/panda-syntax-vscode
* Author: Annmarie Switzer <https://github.com/annmarie-switzer>
*/
/*!
Theme: GitHub Dark Dimmed
Description: Dark dimmed theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Colors taken from GitHub's CSS
*/
.hljs {
color: #e6e6e6;
background: #2a2c2d;
color: #adbac7;
background: #22272e;
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #f47067;
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #dcbdfb;
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #6cb6ff;
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #96d0ff;
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #f69d50;
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #768390;
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #8ddb8c;
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #adbac7;
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #316dca;
font-weight: bold;
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #eac55f;
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #adbac7;
font-style: italic;
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #adbac7;
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #b4f1b4;
background-color: #1b4721;
}
.hljs-comment,
.hljs-quote {
color: #bbbbbb;
font-style: italic;
}
.hljs-params {
color: #bbbbbb;
}
.hljs-punctuation,
.hljs-attr {
color: #e6e6e6;
}
.hljs-selector-tag,
.hljs-name,
.hljs-meta {
color: #ff4b82;
}
.hljs-operator,
.hljs-char.escape_ {
color: #b084eb;
}
.hljs-keyword,
.hljs-deletion {
color: #ff75b5;
/* prettylights-syntax-markup-deleted */
color: #ffd8d3;
background-color: #78191b;
}
.hljs-regexp,
.hljs-selector-pseudo,
.hljs-selector-attr,
.hljs-variable.language_ {
color: #ff9ac1;
}
.hljs-subst,
.hljs-property,
.hljs-code,
.hljs-formula,
.hljs-section,
.hljs-title.function_ {
color: #45a9f9;
}
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition,
.hljs-selector-class,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-meta .hljs-string {
color: #19f9d8;
}
.hljs-variable,
.hljs-template-variable,
.hljs-number,
.hljs-literal,
.hljs-type,
.hljs-char.escape_,
.hljs-link,
.hljs-built_in,
.hljs-title,
.hljs-selector-id,
.hljs-tag,
.hljs-doctag,
.hljs-attribute,
.hljs-template-tag,
.hljs-meta .hljs-keyword,
.hljs-punctuation {
color: #ffb86c;
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}

View File

@@ -1,94 +1,126 @@
/**
* Panda Syntax Theme for Highlight.js
* Based on: https://github.com/tinkertrain/panda-syntax-vscode
* Author: Annmarie Switzer <https://github.com/annmarie-switzer>
*/
/*!
Theme: GitHub
Description: Light theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-light
Current colors taken from GitHub's CSS
*/
.hljs {
color: #2a2c2d;
background: #e6e6e6;
color: #24292e;
background: #ffffff;
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #d73a49;
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #6f42c1;
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #005cc5;
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #032f62;
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #e36209;
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #6a737d;
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #22863a;
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #24292e;
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #005cc5;
font-weight: bold;
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #735c0f;
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #24292e;
font-style: italic;
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #24292e;
font-weight: bold;
}
.hljs-link {
text-decoration: underline;
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #22863a;
background-color: #f0fff4;
}
.hljs-comment,
.hljs-quote {
color: #676b79;
font-style: italic;
}
.hljs-params {
color: #676b79;
}
.hljs-punctuation,
.hljs-attr {
color: #2a2c2d;
}
.hljs-selector-tag,
.hljs-name,
.hljs-meta,
.hljs-operator,
.hljs-char.escape_ {
color: #c56200;
}
.hljs-keyword,
.hljs-deletion {
color: #d92792;
/* prettylights-syntax-markup-deleted */
color: #b31d28;
background-color: #ffeef0;
}
.hljs-regexp,
.hljs-selector-pseudo,
.hljs-selector-attr,
.hljs-variable.language_ {
color: #cc5e91;
}
.hljs-subst,
.hljs-property,
.hljs-code,
.hljs-formula,
.hljs-section,
.hljs-title.function_ {
color: #3787c7;
}
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition,
.hljs-selector-class,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-meta .hljs-string {
color: #0d7d6c;
}
.hljs-variable,
.hljs-template-variable,
.hljs-number,
.hljs-literal,
.hljs-type,
.hljs-char.escape_,
.hljs-link,
.hljs-built_in,
.hljs-title,
.hljs-selector-id,
.hljs-tag,
.hljs-doctag,
.hljs-attribute,
.hljs-template-tag,
.hljs-meta .hljs-keyword {
color: #7641bb;
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
color: #6a737d;
}

View File

@@ -21,11 +21,16 @@
--color-accent-primary-muted: var(--purple-30);
--color-accent-secondary: var(--blue);
--color-accent-tertiary: var(--strong-purple);
--overlay-color: rgba(255, 255, 255, 0.4);
--ok-color: var(--light-ok-color);
--warning-color: var(--light-warning-color);
--pending-color: var(--light-pending-color);
--error-color: var(--light-error-color);
--canvas-color: var(--color-canvas);
--shadow-color: var(--off-black-30);
--radio-button-box-shadow: 0 0 0 1px var(--light-gray-2) inset;
@include meta.load-css("hljs-light-theme");
}

View File

@@ -16,7 +16,7 @@
[app.util.webapi :as wapi]
[app.util.zip :as uz]
[app.worker.export :as e]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]))
(defn parse-data [data]
@@ -55,7 +55,7 @@
(->> (rx/from (vals media))
(rx/map #(assoc % :file-id file-id))
(rx/flat-map
(rx/merge-map
(fn [media]
(let [file-path (str/concat file-id "/media/" (:id media) (cm/mtype->extension (:mtype media)))
blob (data-uri->blob (:uri media))]
@@ -79,38 +79,38 @@
render-stream
(->> files-stream
(rx/flat-map vals)
(rx/flat-map e/process-pages)
(rx/merge-map vals)
(rx/merge-map e/process-pages)
(rx/observe-on :async)
(rx/flat-map e/get-page-data)
(rx/merge-map e/get-page-data)
(rx/share))
colors-stream
(->> files-stream
(rx/flat-map vals)
(rx/merge-map vals)
(rx/map #(vector (:id %) (get-in % [:data :colors])))
(rx/filter #(d/not-empty? (second %)))
(rx/map e/parse-library-color))
typographies-stream
(->> files-stream
(rx/flat-map vals)
(rx/merge-map vals)
(rx/map #(vector (:id %) (get-in % [:data :typographies])))
(rx/filter #(d/not-empty? (second %)))
(rx/map e/parse-library-typographies))
media-stream
(->> files-stream
(rx/flat-map vals)
(rx/merge-map vals)
(rx/map #(vector (:id %) (get-in % [:data :media])))
(rx/filter #(d/not-empty? (second %)))
(rx/flat-map parse-library-media))
(rx/merge-map parse-library-media))
components-stream
(->> files-stream
(rx/flat-map vals)
(rx/merge-map vals)
(rx/filter #(d/not-empty? (ctkl/components-seq (:data %))))
(rx/flat-map e/parse-library-components))
(rx/merge-map e/parse-library-components))
pages-stream
(->> render-stream
@@ -132,7 +132,7 @@
typographies-stream)
(rx/reduce conj [])
(rx/with-latest-from files-stream)
(rx/flat-map (fn [[data _]]
(rx/merge-map (fn [[data _]]
(->> (uz/compress-files data)
(rx/map #(vector file %)))))))))

View File

@@ -8,7 +8,7 @@
(:require
[app.common.uuid :as uuid]
[app.main.render :as r]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[promesa.core :as p]))
(defn render-page-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})

View File

@@ -28,10 +28,10 @@
[app.util.dom :as dom]
[app.util.i18n :as i18n]
[app.util.theme :as theme]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[debug]
[features]
[potok.core :as ptk]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(log/setup! {:app :info})

View File

@@ -9,8 +9,8 @@
(:require
[app.common.exceptions :as ex]
[app.common.transit :as t]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defrecord BroadcastMessage [id type data]
cljs.core/IDeref

View File

@@ -14,8 +14,8 @@
[app.common.uuid :as uuid]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.repo :as rp]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(def ^:private schema:comment-thread
(sm/define

View File

@@ -14,8 +14,8 @@
[app.main.features :as features]
[app.main.repo :as rp]
[app.util.i18n :refer [tr]]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SHARE LINK
@@ -106,9 +106,8 @@
(:typography-count summary))]
(modal/show
{:type :confirm
:message ""
:title (tr "modals.add-shared-confirm.message" (:name summary))
:hint (if (zero? count) (tr "modals.add-shared-confirm-empty.hint") (tr "modals.add-shared-confirm.hint"))
:message (if (zero? count) (tr "modals.add-shared-confirm-empty.hint") (tr "modals.add-shared-confirm.hint"))
:cancel-label (if (zero? count) (tr "labels.cancel") :omit)
:accept-label (tr "modals.add-shared-confirm.accept")
:accept-style :primary

View File

@@ -30,9 +30,9 @@
[app.util.time :as dt]
[app.util.timers :as tm]
[app.util.webapi :as wapi]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[clojure.set :as set]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(log/set-level! :warn)
@@ -419,7 +419,7 @@
(rx/map di/validate-file)
(rx/map prepare)
(rx/mapcat #(rp/cmd! :update-team-photo %))
(rx/do on-success)
(rx/tap on-success)
(rx/map du/fetch-teams)
(rx/catch on-error))))))
@@ -831,9 +831,15 @@
(ptk/reify ::set-file-thumbnail
ptk/UpdateEvent
(update [_ state]
(-> state
(d/update-in-when [:dashboard-files file-id] assoc :thumbnail-uri thumbnail-uri)
(d/update-in-when [:dashboard-recent-files file-id] assoc :thumbnail-uri thumbnail-uri)))))
(letfn [(update-search-files [files]
(->> files
(mapv #(cond-> %
(= file-id (:id %))
(assoc :thumbnail-uri thumbnail-uri)))))]
(-> state
(d/update-in-when [:dashboard-files file-id] assoc :thumbnail-uri thumbnail-uri)
(d/update-in-when [:dashboard-recent-files file-id] assoc :thumbnail-uri thumbnail-uri)
(d/update-when :dashboard-search-result update-search-files))))))
;; --- EVENT: create-file

View File

@@ -17,9 +17,10 @@
[app.util.object :as obj]
[app.util.storage :refer [storage]]
[app.util.time :as dt]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[beicon.v2.operators :as rxo]
[lambdaisland.uri :as u]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(l/set-level! :info)
@@ -238,7 +239,7 @@
profile (->> (rx/from-atom storage {:emit-current-value? true})
(rx/map :profile)
(rx/map :id)
(rx/dedupe))]
(rx/pipe (rxo/distinct-contiguous)))]
(l/debug :hint "event instrumentation initialized")
@@ -259,12 +260,12 @@
(l/debug :hint "events chunk persisted" :total (count chunk))))
(rx/map (constantly chunk))))))
(rx/take-until stoper)
(rx/subs (fn [chunk]
(swap! buffer remove-from-buffer (count chunk)))
(fn [cause]
(l/error :hint "unexpected error on audit persistence" :cause cause))
(fn []
(l/debug :hint "audit persistence terminated"))))
(rx/subs! (fn [chunk]
(swap! buffer remove-from-buffer (count chunk)))
(fn [cause]
(l/error :hint "unexpected error on audit persistence" :cause cause))
(fn []
(l/debug :hint "audit persistence terminated"))))
(->> stream
(rx/with-latest-from profile)
@@ -290,10 +291,10 @@
(rx/switch-map #(rx/timer (inst-ms session-timeout)))
(rx/take-until stoper)
(rx/subs (fn [_]
(l/debug :hint "session reinitialized")
(reset! session nil))
(fn [cause]
(l/error :hint "error on event batching stream" :cause cause))
(fn []
(l/debug :hitn "events batching stream terminated")))))))))
(rx/subs! (fn [_]
(l/debug :hint "session reinitialized")
(reset! session nil))
(fn [cause]
(l/error :hint "error on event batching stream" :cause cause))
(fn []
(l/debug :hitn "events batching stream terminated")))))))))

View File

@@ -15,8 +15,8 @@
[app.util.dom :as dom]
[app.util.time :as dt]
[app.util.websocket :as ws]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(def default-timeout 5000)

View File

@@ -19,9 +19,9 @@
[app.util.i18n :refer [tr]]
[app.util.storage :refer [storage]]
[app.util.webapi :as wa]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; General purpose events & IMPL

View File

@@ -11,7 +11,7 @@
[app.main.data.messages :as dm]
[app.main.store :as st]
[app.util.i18n :refer [tr]]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]))

View File

@@ -9,8 +9,8 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.schema :as sm]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(declare hide)
(declare show)

View File

@@ -10,7 +10,7 @@
[app.common.uuid :as uuid]
[app.main.store :as st]
[cljs.core :as c]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(defonce components (atom {}))

View File

@@ -16,10 +16,10 @@
[app.main.refs :as refs]
[app.util.code-gen :as cg]
[app.util.timers :as ts]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[clojure.set :as set]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(def style-type "css")
(def markup-type "html")
@@ -80,7 +80,7 @@
(rx/merge-map fonts/fetch-font-css)
(rx/reduce conj [])
(rx/map #(str/join "\n" %))
(rx/subs
(rx/subs!
(fn [fontfaces-css]
(let [style-code
(dm/str

View File

@@ -13,7 +13,7 @@
[app.common.schema :as sm]
[app.config :as cf]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(log/set-level! :warn)

View File

@@ -21,8 +21,8 @@
[app.util.i18n :as i18n]
[app.util.router :as rt]
[app.util.storage :refer [storage]]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; --- SCHEMAS
@@ -434,7 +434,7 @@
(rx/map di/validate-file)
(rx/map prepare)
(rx/mapcat #(rp/cmd! :update-profile-photo %))
(rx/do on-success)
(rx/tap on-success)
(rx/map (constantly (fetch-profile)))
(rx/catch on-error))))))

View File

@@ -21,8 +21,8 @@
[app.main.repo :as rp]
[app.util.globals :as ug]
[app.util.router :as rt]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; --- Local State Initialization

View File

@@ -11,8 +11,8 @@
[app.common.uri :as u]
[app.config :as cf]
[app.util.websocket :as ws]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(l/set-level! :error)
@@ -44,7 +44,7 @@
(ptk/reify ::initialize
ptk/WatchEvent
(watch [_ state stream]
(l/trace :hint "event:initialize" :fn "watch")
(l/trace :hint "initialize" :fn "watch")
(let [sid (:session-id state)
uri (prepare-uri {:session-id sid})
ws (ws/create uri)]

View File

@@ -78,10 +78,10 @@
[app.util.router :as rt]
[app.util.timers :as tm]
[app.util.webapi :as wapi]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(def default-workspace-local {:zoom 1})
@@ -444,7 +444,7 @@
uris (into #{} xform (wsh/lookup-page-objects state page-id))]
(->> (rx/from uris)
(rx/subs #(http/fetch-data-uri % false)))))))
(rx/subs! #(http/fetch-data-uri % false)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Workspace Page CRUD
@@ -872,10 +872,10 @@
(pcb/update-shapes [parent-id] #(ctl/add-children-to-index % ids objects to-index)))
(pcb/update-shapes parents
(fn [parent]
(fn [parent objects]
(cond-> parent
(ctl/grid-layout? parent)
(ctl/assign-cells))))
(ctl/assign-cells objects))))
(pcb/reorder-grid-children parents)

View File

@@ -18,9 +18,9 @@
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(defn selected-shapes-idx
[state]

View File

@@ -20,8 +20,8 @@
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.worker :as uw]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; Change this to :info :debug or :trace to debug this module
(log/set-level! :warn)
@@ -70,7 +70,7 @@
update-layout-ids
(->> ids
(map (d/getf objects))
(filter #(some update-layout-attr? (pcb/changed-attrs % update-fn {:attrs attrs})))
(filter #(some update-layout-attr? (pcb/changed-attrs % objects update-fn {:attrs attrs})))
(map :id))
changes (reduce

View File

@@ -8,7 +8,7 @@
(:require
[app.common.files.helpers :as cfh]
[app.common.uuid :as uuid]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
;; --- Shape attrs (Layers Sidebar)

View File

@@ -23,8 +23,8 @@
[app.main.data.workspace.undo :as dwu]
[app.util.color :as uc]
[app.util.storage :refer [storage]]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; A set of keys that are used for shared state identifiers
(def ^:const colorpicker-selected-broadcast-key ::colorpicker-selected)
@@ -353,7 +353,7 @@
;; Stream that updates the stroke/width and stops if `esc` pressed
(->> sub
(rx/take-until stop?)
(rx/flat-map update-events))
(rx/merge-map update-events))
;; Hide the modal if the stop event is emitted
(->> stop?

View File

@@ -22,8 +22,8 @@
[app.main.streams :as ms]
[app.util.mouse :as mse]
[app.util.router :as rt]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(declare handle-interrupt)
(declare handle-comment-layer-click)

View File

@@ -13,8 +13,8 @@
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.util.router :as rt]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; Change this to :info :debug or :trace to debug this module
(log/set-level! :warn)

View File

@@ -14,8 +14,8 @@
[app.main.data.workspace.drawing.common :as common]
[app.main.data.workspace.drawing.curve :as curve]
[app.main.data.workspace.path :as path]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(declare start-drawing)
(declare handle-drawing)

View File

@@ -24,9 +24,10 @@
[app.main.data.workspace.state-helpers :as wsh]
[app.main.snap :as snap]
[app.main.streams :as ms]
[app.util.array :as array]
[app.util.mouse :as mse]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn adjust-ratio
[point initial]
@@ -128,12 +129,11 @@
(->> ms/mouse-position
(rx/filter #(> (gpt/distance % initial) (/ 2 zoom)))
(rx/with-latest vector ms/mouse-position-shift)
(rx/with-latest conj ms/mouse-position-mod)
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-mod)
(rx/switch-map
(fn [[point :as current]]
(->> (snap/closest-snap-point page-id [shape] objects layout zoom focus point)
(rx/map #(conj current %)))))
(rx/map (partial array/conj current)))))
(rx/map
(fn [[_ shift? mod? point]]
#(update-drawing % initial (cond-> point snap-pixel? (gpt/round-step snap-prec)) shift? mod?)))))

View File

@@ -16,8 +16,8 @@
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.worker :as uw]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn clear-drawing
[]

View File

@@ -23,8 +23,8 @@
[app.main.streams :as ms]
[app.util.mouse :as mse]
[app.util.path.simplify-curve :as ups]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(def simplify-tolerance 0.3)

View File

@@ -10,8 +10,8 @@
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn interrupt? [e] (= e :interrupt))

View File

@@ -10,8 +10,8 @@
[app.common.geom.shapes :as gsh]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; This event will update the file so the boolean data has a pre-generated path data
;; to increase performance.

View File

@@ -7,8 +7,8 @@
(ns app.main.data.workspace.fix-broken-shapes
(:require
[app.main.data.workspace.changes :as dch]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn- generate-broken-link-changes
[attr {:keys [objects id] :as container}]

View File

@@ -12,8 +12,8 @@
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.fonts :as fonts]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; This event will update the file so the texts with non existing custom fonts try to be fixed.
;; This can happen when:

View File

@@ -12,8 +12,8 @@
[app.common.files.changes-builder :as pcb]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Grid

View File

@@ -9,7 +9,7 @@
[app.common.geom.rect :as grc]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.state-helpers :as wsh]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(defn hover-grid-cell
[grid-id cell-id add-to-set]

View File

@@ -10,8 +10,8 @@
[app.main.data.workspace :as dw]
[app.main.data.workspace.common :as dwc]
[app.main.store :as st]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Shortcuts

View File

@@ -19,8 +19,8 @@
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn shapes-for-grouping
[objects selected]

View File

@@ -13,8 +13,8 @@
[app.common.types.page :as ctp]
[app.main.data.workspace.changes :as dwc]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn make-update-guide [guide]
(fn [other]

View File

@@ -8,7 +8,7 @@
(:require
[app.common.data.macros :as dm]
[clojure.set :as set]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
;; --- Manage shape's highlight status

View File

@@ -20,8 +20,8 @@
[app.main.data.workspace.undo :as dwu]
[app.main.streams :as ms]
[app.util.mouse :as mse]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; --- Flows

View File

@@ -11,9 +11,9 @@
[app.common.math :as mth]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
;; -- Opacity ----------------------------------------------------------

View File

@@ -10,7 +10,7 @@
[app.common.data.macros :as dm]
[app.util.storage :refer [storage]]
[clojure.set :as set]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(def valid-flags
#{:sitemap

View File

@@ -45,9 +45,9 @@
[app.util.i18n :refer [tr]]
[app.util.router :as rt]
[app.util.time :as dt]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default
(log/set-level! :warn)
@@ -754,6 +754,18 @@
(dch/commit-changes (assoc nonlocal-changes
:file-id file-id)))))))))))
(defn- update-component-thumbnail-sync
[state component-id file-id tag]
(let [current-file-id (:current-file-id state)
current-file? (= current-file-id file-id)
data (if current-file?
(get state :workspace-data)
(get-in state [:workspace-libraries file-id :data]))
component (ctkl/get-component data component-id)
page-id (:main-instance-page component)
root-id (:main-instance-id component)]
(dwt/request-thumbnail file-id page-id root-id tag)))
(defn update-component-sync
([shape-id file-id] (update-component-sync shape-id file-id nil))
([shape-id file-id undo-group]
@@ -761,14 +773,18 @@
ptk/WatchEvent
(watch [_ state _]
(let [current-file-id (:current-file-id state)
current-file? (= current-file-id file-id)
page (wsh/lookup-page state)
shape (ctn/get-shape page shape-id)
component-id (:component-id shape)
undo-id (js/Symbol)]
(rx/of
(dwu/start-undo-transaction undo-id)
(update-component shape-id undo-group)
(sync-file current-file-id file-id :components (:component-id shape) undo-group)
(when (not= current-file-id file-id)
(update-component-thumbnail-sync state component-id file-id "frame")
(update-component-thumbnail-sync state component-id file-id "component")
(when (not current-file?)
(sync-file file-id file-id :components (:component-id shape) undo-group))
(dwu/commit-undo-transaction undo-id)))))))
@@ -795,7 +811,8 @@
(ptk/reify ::update-component-thumbnail
ptk/WatchEvent
(watch [_ state _]
(let [data (get state :workspace-data)
(rx/of (update-component-thumbnail-sync state component-id file-id "component"))
#_(let [data (get state :workspace-data)
component (ctkl/get-component data component-id)
page-id (:main-instance-page component)
root-id (:main-instance-id component)]

View File

@@ -182,10 +182,10 @@
(-> changes
(pcb/update-shapes
[(:parent-id first-shape)]
(fn [shape]
(fn [shape objects]
(-> shape
(ctl/push-into-cell [(:id first-shape)] row column)
(ctl/assign-cells))))
(ctl/assign-cells objects))))
(pcb/reorder-grid-children [(:parent-id first-shape)])))
changes)

View File

@@ -30,9 +30,9 @@
[app.main.store :as st]
[app.util.http :as http]
[app.util.i18n :refer [tr]]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]
[potok.v2.core :as ptk]
[promesa.core :as p]
[tubax.core :as tubax]))
@@ -122,13 +122,13 @@
(->> (rx/from uris)
(rx/filter (comp not svg-url?))
(rx/mapcat upload)
(rx/do on-image))
(rx/tap on-image))
(->> (rx/from uris)
(rx/filter svg-url?)
(rx/merge-map (partial fetch-svg name))
(rx/merge-map svg->clj)
(rx/do on-svg)))))
(rx/tap on-svg)))))
(defn- process-blobs
[{:keys [file-id local? name blobs force-media on-image on-svg]}]
@@ -154,14 +154,14 @@
(rx/filter (comp not svg-blob?))
(rx/map prepare-blob)
(rx/mapcat #(rp/cmd! :upload-file-media-object %))
(rx/do on-image))
(rx/tap on-image))
(->> (rx/from blobs)
(rx/map dmm/validate-file)
(rx/filter svg-blob?)
(rx/merge-map extract-content)
(rx/merge-map svg->clj)
(rx/do on-svg)))))
(rx/tap on-svg)))))
(defn handle-media-error [error on-error]
(if (ex/ex-info? error)
@@ -278,7 +278,7 @@
(rx/map dmm/validate-file)
(rx/map prepare)
(rx/mapcat #(rp/cmd! :upload-file-media-object %))
(rx/do on-upload-success)
(rx/tap on-upload-success)
(rx/catch handle-media-error))))))
;; --- Upload File Media objects
@@ -423,7 +423,7 @@
:timeout nil
:tag :media-loading}))
(->> (rp/cmd! :clone-file-media-object params)
(rx/do on-success)
(rx/tap on-success)
(rx/catch on-error)
(rx/finalize #(st/emit! (msg/hide-tag :media-loading)))))))))

View File

@@ -27,8 +27,8 @@
[app.main.data.workspace.guides :as-alias dwg]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;; -- temporary modifiers -------------------------------------------
@@ -191,14 +191,14 @@
;; Temporary remove the children when moving them
frame (-> frame
(update :shapes #(d/removev ids %))
(ctl/assign-cells))
(ctl/assign-cells objects))
ids (->> ids (remove #(ctl/position-absolute? objects %)))
frame (-> frame
(update :shapes d/concat-vec ids)
(cond-> (some? cell)
(ctl/push-into-cell ids row column))
(ctl/assign-cells))]
(ctl/assign-cells objects))]
(-> modifiers
(ctm/change-property :layout-grid-rows (:layout-grid-rows frame))

View File

@@ -19,10 +19,11 @@
[app.util.globals :refer [global]]
[app.util.mouse :as mse]
[app.util.object :as obj]
[app.util.rxops :as rxs]
[app.util.time :as dt]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[clojure.set :as set]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(declare process-message)
(declare handle-presence)
@@ -82,7 +83,7 @@
;; position changes.
(->> stream
(rx/filter mse/pointer-event?)
(rx/sample 50)
(rx/pipe (rxs/throttle 100))
(rx/map #(handle-pointer-send file-id (:pt %)))))
(rx/take-until stoper))]
@@ -132,7 +133,7 @@
"#faa6b7" ; salmon
"#f9b489" ; orange
"#fdcd79" ; soft-orange
"#dee563" ; yellow
"#dee563" ; yellow -> default presence color
"#b1e96f" ; yellow-green
})

View File

@@ -13,8 +13,8 @@
[app.main.data.workspace.path.helpers :as helpers]
[app.main.data.workspace.path.state :as st]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn generate-path-changes
"Generates changes to update the new content of the shape"

View File

@@ -8,7 +8,7 @@
(:require
[app.common.schema :as sm]
[app.main.data.workspace.path.state :as st]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(def valid-commands
#{:move-to

View File

@@ -27,8 +27,8 @@
[app.main.data.workspace.path.undo :as undo]
[app.main.data.workspace.state-helpers :as wsh]
[app.util.mouse :as mse]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(declare change-edit-mode)
@@ -46,7 +46,8 @@
command (helpers/next-node shape position last-point prev-handler)]
(assoc-in state [:workspace-local :edit-path id :preview] command)))))
(defn add-node [{:keys [x y shift?]}]
(defn add-node
[{:keys [x y shift?]}]
(ptk/reify ::add-node
ptk/UpdateEvent
(update [_ state]
@@ -135,7 +136,7 @@
(first handlers))
drag-events-stream
(->> (streams/position-stream)
(->> (streams/position-stream state)
(rx/map #(drag-handler position idx prefix %))
(rx/take-until
(rx/merge
@@ -164,7 +165,7 @@
(defn start-path-from-point [position]
(ptk/reify ::start-path-from-point
ptk/WatchEvent
(watch [_ _ stream]
(watch [_ state stream]
(let [stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
@@ -172,7 +173,7 @@
(->> stream
(rx/filter helpers/end-path-event?)))
drag-events (->> (streams/position-stream)
drag-events (->> (streams/position-stream state)
(rx/map #(drag-handler %))
(rx/take-until stoper))]
(rx/concat
@@ -190,7 +191,12 @@
(rx/merge-map #(rx/empty))))
(defn make-drag-stream
[stream down-event]
[state stream down-event]
(dm/assert!
"should be a pointer"
(gpt/point? down-event))
(let [stoper (rx/merge
(->> stream
(rx/filter mse/mouse-event?)
@@ -198,7 +204,7 @@
(->> stream
(rx/filter helpers/end-path-event?)))
drag-events (->> (streams/position-stream)
drag-events (->> (streams/position-stream state)
(rx/map #(drag-handler %))
(rx/take-until stoper))]
(rx/concat
@@ -217,7 +223,7 @@
(assoc-in state [:workspace-local :edit-path id :edit-mode] :draw)))
ptk/WatchEvent
(watch [_ _ stream]
(watch [_ state stream]
(let [mouse-down (->> stream
(rx/filter mse/mouse-event?)
(rx/filter mse/mouse-down-event?))
@@ -226,7 +232,7 @@
;; Mouse move preview
mousemove-events
(->> (streams/position-stream)
(->> (streams/position-stream state)
(rx/take-until end-path-events)
(rx/map #(preview-next-point %)))
@@ -234,12 +240,13 @@
mousedown-events
(->> mouse-down
(rx/take-until end-path-events)
(rx/with-latest merge (streams/position-stream))
;; We just ignore the mouse event and stream down the
;; last position event
(rx/with-latest-from #(-> %2) (streams/position-stream state))
;; We change to the stream that emits the first event
(rx/switch-map
#(rx/race (make-node-events-stream stream)
(make-drag-stream stream %))))]
(make-drag-stream state stream %))))]
(rx/concat
(rx/of (undo/start-path-undo))

View File

@@ -28,8 +28,8 @@
[app.main.streams :as ms]
[app.util.mouse :as mse]
[app.util.path.tools :as upt]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn modify-handler [id index prefix dx dy match-opposite?]
(ptk/reify ::modify-handler

View File

@@ -15,7 +15,7 @@
[app.common.svg.path.subpath :as ups]
[app.main.data.workspace.path.common :as common]
[app.util.mouse :as mse]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(defn end-path-event?
[event]

View File

@@ -14,8 +14,8 @@
[app.main.data.workspace.path.state :as st]
[app.main.streams :as ms]
[app.util.mouse :as mse]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn path-pointer-enter [position]
(ptk/reify ::path-pointer-enter

View File

@@ -12,8 +12,8 @@
[app.common.types.container :as ctn]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn convert-selected-to-path []
(ptk/reify ::convert-selected-to-path

View File

@@ -10,8 +10,8 @@
[app.main.data.workspace :as dw]
[app.main.data.workspace.path :as drp]
[app.main.store :as st]
[beicon.core :as rx]
[potok.core :as ptk]))
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Shortcuts

View File

@@ -15,9 +15,9 @@
[app.main.store :as st]
[app.main.streams :as ms]
[app.util.mouse :as mse]
[beicon.core :as rx]
[beicon.v2.core :as rx]
[okulary.core :as l]
[potok.core :as ptk]))
[potok.v2.core :as ptk]))
(defonce drag-threshold 5)
@@ -115,7 +115,6 @@
(defn move-handler-stream
[start-point node handler opposite points]
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
ranges (snap/create-ranges points)
d-pos (/ snap/snap-path-accuracy zoom)
@@ -145,16 +144,20 @@
(let [snap (snap/get-snap-delta [handler] ranges d-pos)]
(merge position (gpt/add position snap)))))
position))]
(->> ms/mouse-position
(rx/map to-pixel-snap)
(rx/with-latest merge (->> ms/mouse-position-shift (rx/map #(hash-map :shift? %))))
(rx/with-latest merge (->> ms/mouse-position-alt (rx/map #(hash-map :alt? %))))
(rx/with-latest-from
(fn [position shift? alt?]
(assoc position :shift? shift? :alt? alt?))
ms/mouse-position-shift
ms/mouse-position-alt)
(rx/with-latest-from (snap-toggled-stream))
(rx/map check-path-snap))))
(defn position-stream
[]
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
[state]
(let [zoom (get-in state [:workspace-local :zoom] 1)
d-pos (/ snap/snap-path-accuracy zoom)
get-content #(pst/get-path % :content)
@@ -169,12 +172,14 @@
(->> ms/mouse-position
(rx/map to-pixel-snap)
(rx/with-latest vector ranges-stream)
(rx/with-latest-from (snap-toggled-stream))
(rx/map (fn [[[position ranges] snap-toggled]]
(rx/with-latest-from ranges-stream (snap-toggled-stream))
(rx/map (fn [[position ranges snap-toggled]]
(if snap-toggled
(let [snap (snap/get-snap-delta [position] ranges d-pos)]
(gpt/add position snap))
position)))
(rx/with-latest merge (->> ms/mouse-position-shift (rx/map #(hash-map :shift? %))))
(rx/with-latest merge (->> ms/mouse-position-alt (rx/map #(hash-map :alt? %)))))))
(rx/with-latest-from
(fn [position shift? alt?]
(assoc position :shift? shift? :alt? alt?))
ms/mouse-position-shift
ms/mouse-position-alt))))

Some files were not shown because too many files have changed in this diff Show More