From 29180e4196d8c586faf7f9e6d966446f8038e711 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 12 Nov 2020 13:14:06 +0100 Subject: [PATCH 001/195] :bug: Fixed measurement problem in handoff --- .../ui/viewer/handoff/selection_feedback.cljs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs b/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs index 01bbae2a6d..ec9c781fcf 100644 --- a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs @@ -60,11 +60,9 @@ ;; HELPERS ;; ------------------------------------------------ -(defn frame->selrect [frame] - {:x1 0 - :y1 0 - :x2 (:width frame) - :y2 (:height frame) +(defn frame->bounds [frame] + {:x 0 + :y 0 :width (:width frame) :height (:height frame)}) @@ -88,23 +86,24 @@ (let [zoom (mf/deref selected-zoom) hover-shapes-ref (mf/use-memo (make-hover-shapes-iref)) - hover-shape (-> (mf/deref hover-shapes-ref) + hover-shape (-> (or (mf/deref hover-shapes-ref) frame) (gsh/translate-to-frame frame)) selected-shapes-ref (mf/use-memo (make-selected-shapes-iref)) selected-shapes (->> (mf/deref selected-shapes-ref) (map #(gsh/translate-to-frame % frame))) - selrect (gsh/selection-rect selected-shapes)] + selrect (gsh/selection-rect selected-shapes) + bounds (frame->bounds frame)] (when (seq selected-shapes) [:g.selection-feedback {:pointer-events "none"} [:g.selected-shapes - [:& selection-guides {:selrect selrect :frame frame :zoom zoom}] + [:& selection-guides {:bounds bounds :selrect selrect :zoom zoom}] [:& selection-rect {:selrect selrect :zoom zoom}] [:& size-display {:selrect selrect :zoom zoom}]] - [:& measurement {:bounds frame + [:& measurement {:bounds bounds :selected-shapes selected-shapes :hover-shape hover-shape :zoom zoom}]]))) From 4ad08a744980bb5e0e273ef9b64922ba4174480b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 12 Nov 2020 12:00:32 +0100 Subject: [PATCH 002/195] :tada: Add socket repl. --- backend/deps.edn | 1 - backend/src/app/main.clj | 1 + backend/src/app/srepl/main.clj | 5 +++++ backend/src/app/srepl/server.clj | 30 ++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 backend/src/app/srepl/main.clj create mode 100644 backend/src/app/srepl/server.clj diff --git a/backend/deps.edn b/backend/deps.edn index 15cb1b4a72..ce2109b503 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -37,7 +37,6 @@ funcool/promesa {:mvn/version "5.1.0"} funcool/cuerdas {:mvn/version "2020.03.26-3"} - buddy/buddy-core {:mvn/version "1.8.0"} buddy/buddy-hashers {:mvn/version "1.6.0"} buddy/buddy-sign {:mvn/version "3.2.0"} diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index f116ace244..454cc68bfc 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -27,6 +27,7 @@ (defn run [params] (require 'app.config + 'app.srepl.server 'app.migrations 'app.worker 'app.media diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj new file mode 100644 index 0000000000..5227aba171 --- /dev/null +++ b/backend/src/app/srepl/main.clj @@ -0,0 +1,5 @@ +(ns app.srepl.main + "A main namespace for server repl." + (:require + [clojure.pprint :refer [pprint]] + [app.db :as db])) diff --git a/backend/src/app/srepl/server.clj b/backend/src/app/srepl/server.clj new file mode 100644 index 0000000000..d83d44067b --- /dev/null +++ b/backend/src/app/srepl/server.clj @@ -0,0 +1,30 @@ +(ns app.srepl.server + "Server Repl." + (:require + [clojure.pprint :refer [pprint]] + [clojure.main :as cm] + [clojure.core.server :as ccs] + [app.srepl.main] + [mount.core :as mount :refer [defstate]])) + +(defn- repl-init + [] + (ccs/repl-init) + (in-ns 'app.srepl.main)) + +(defn repl + [] + (cm/repl + :init repl-init + :read ccs/repl-read)) + +(defstate server + :start (ccs/start-server + {:address "127.0.0.1" + :port 6061 + :name "main" + :accept 'app.srepl.server/repl}) + :stop (ccs/stop-server "main")) + + + From e5ea8bf302096e998dd2c5fce808064b251eea5c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 12 Nov 2020 13:35:20 +0100 Subject: [PATCH 003/195] :tada: Include sprite inline in a template. --- frontend/gulpfile.js | 119 +-- frontend/package.json | 10 +- frontend/resources/templates/index.mustache | 7 +- frontend/src/app/main/ui/icons.clj | 4 +- frontend/yarn.lock | 932 +++++++++++++++++--- 5 files changed, 846 insertions(+), 226 deletions(-) diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js index 4e12b670d9..11a4c8a6bb 100644 --- a/frontend/gulpfile.js +++ b/frontend/gulpfile.js @@ -2,93 +2,31 @@ const fs = require("fs"); const path = require("path"); const l = require("lodash"); -const CleanCSS = require("clean-css"); const gulp = require("gulp"); -const gulpif = require("gulp-if"); -const gzip = require("gulp-gzip"); - -const mustache = require("gulp-mustache"); -const rename = require("gulp-rename"); +const gulpSass = require("gulp-sass"); +const gulpGzip = require("gulp-gzip"); +const gulpMustache = require("gulp-mustache"); +const gulpRename = require("gulp-rename"); const svgSprite = require("gulp-svg-sprite"); +const gulpPostcss = require("gulp-postcss"); const mkdirp = require("mkdirp"); const rimraf = require("rimraf"); const sass = require("sass"); const autoprefixer = require("autoprefixer") -const postcss = require("postcss") +const clean = require("postcss-clean"); const mapStream = require("map-stream"); - - const paths = {}; paths.resources = "./resources/"; paths.output = "./resources/public/"; paths.dist = "./target/dist/"; -paths.scss = "./resources/styles/**/*.scss"; + /*********************************************** * Helpers ***********************************************/ -function isProduction() { - return (process.env.NODE_ENV === "production"); -} - -function scssPipeline(options) { - const write = (_path, data) => { - return new Promise((resolve, reject) => { - fs.writeFile(_path, data, function(err) { - if (err) { reject(err); } - else { resolve(); } - }); - }); - }; - - const touch = (_path) => { - return new Promise((resolve, reject) => { - return fs.utimes(_path, new Date(), new Date(), () => { - resolve(_path); - }); - }) - }; - - const render = (input) => { - return new Promise((resolve, reject) => { - sass.render({file: input}, async function(err, result) { - if (err) { - console.log(err.formatted); - reject(err); - } else { - resolve(result.css); - } - }); - }); - }; - - const postprocess = (data, input, output) => { - return postcss([autoprefixer]) - .process(data, {map: false, from: input, to: output}) - }; - - return function(next) { - const input = options.input; - const output = options.output; - - return mkdirp(path.dirname(output)) - .then(() => render(input)) - .then((res) => postprocess(res, input, output)) - .then(async (res) => { - await write(output, res.css); - await touch(output); - return res; - }) - .catch((err) => null) - .then(() => { - next(); - }); - }; -} - // Templates function readLocales() { @@ -158,7 +96,7 @@ function templatePipeline(options) { const locales = readLocales(); const manifest = readManifest(); - const tmpl = mustache({ + const tmpl = gulpMustache({ ts: ts, th: th, manifest: manifest, @@ -168,7 +106,7 @@ function templatePipeline(options) { return gulp.src(input) .pipe(tmpl) - .pipe(rename("index.html")) + .pipe(gulpRename("index.html")) .pipe(gulp.dest(output)) .pipe(touch()); }; @@ -178,18 +116,23 @@ function templatePipeline(options) { * Generic ***********************************************/ -gulp.task("scss:main-default", scssPipeline({ - input: paths.resources + "styles/main-default.scss", - output: paths.output + "css/main-default.css" -})); +gulpSass.compiler = sass; -gulp.task("scss", gulp.parallel("scss:main-default")); +gulp.task("scss", function() { + return gulp.src(paths.resources + "styles/main-default.scss") + .pipe(gulpSass().on('error', gulpSass.logError)) + .pipe(gulpPostcss([ + autoprefixer, + clean({format: "keep-breaks", level: 1}) + ])) + .pipe(gulp.dest(paths.output + "css/")); +}); gulp.task("svg:sprite", function() { return gulp.src(paths.resources + "images/icons/*.svg") - .pipe(rename({prefix: "icon-"})) - .pipe(svgSprite({mode:{symbol: {inline: false}}})) - .pipe(gulp.dest(paths.output + "images/svg-sprite/")); + .pipe(gulpRename({prefix: "icon-"})) + .pipe(svgSprite({mode:{symbol: {inline: true}}})) + .pipe(gulp.dest(paths.output + "images/sprites/")); }); gulp.task("template:main", templatePipeline({ @@ -197,7 +140,7 @@ gulp.task("template:main", templatePipeline({ output: paths.output })); -gulp.task("templates", gulp.series("template:main")); +gulp.task("templates", gulp.series("svg:sprite", "template:main")); /*********************************************** * Development @@ -226,22 +169,16 @@ gulp.task("dev:dirs", async function(next) { }); gulp.task("watch:main", function() { - gulp.watch(paths.scss, gulp.series("scss")); - gulp.watch(paths.resources + "images/**/*", - gulp.series("svg:sprite", "copy:assets:images")); + gulp.watch(paths.resources + "styles/**/**.scss", gulp.series("scss")); + gulp.watch(paths.resources + "images/**/*", gulp.series("copy:assets:images")); gulp.watch([paths.resources + "templates/*.mustache", paths.resources + "locales.json"], gulp.series("templates")); }); -gulp.task("build", gulp.parallel("scss", "svg:sprite", "templates", "copy:assets")); - -gulp.task("watch", gulp.series( - "dev:dirs", - "build", - "watch:main" -)); +gulp.task("build", gulp.parallel("scss", "templates", "copy:assets")); +gulp.task("watch", gulp.series("dev:dirs", "build", "watch:main")); /*********************************************** * Production @@ -258,6 +195,6 @@ gulp.task("dist:copy", function() { gulp.task("dist:gzip", function() { return gulp.src(`${paths.dist}**/!(*.gz|*.br|*.jpg|*.png)`) - .pipe(gzip({gzipOptions: {level: 9}})) + .pipe(gulpGzip({gzipOptions: {level: 9}})) .pipe(gulp.dest(paths.dist)); }); diff --git a/frontend/package.json b/frontend/package.json index c7d4f4b482..10098e8587 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,15 +14,18 @@ "scripts": {}, "devDependencies": { "autoprefixer": "^10.0.1", - "clean-css": "^4.2.3", "gulp": "4.0.2", "gulp-gzip": "^1.4.2", - "gulp-if": "^3.0.0", "gulp-mustache": "^5.0.0", + "gulp-postcss": "^9.0.0", "gulp-rename": "^2.0.0", + "gulp-sass": "^4.1.0", + "gulp-sourcemaps": "^3.0.0", "gulp-svg-sprite": "^1.5.0", + "map-stream": "0.0.7", "mkdirp": "^1.0.4", - "postcss": "^8.1.2", + "postcss": "^8.1.7", + "postcss-clean": "^1.1.0", "rimraf": "^3.0.0", "sass": "^1.26.10", "shadow-cljs": "2.11.5" @@ -31,7 +34,6 @@ "date-fns": "^2.15.0", "highlight.js": "^10.3.1", "js-beautify": "^1.13.0", - "map-stream": "0.0.7", "mousetrap": "^1.6.5", "randomcolor": "^0.6.2", "react": "17.0.1", diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache index def3b53d10..99da487687 100644 --- a/frontend/resources/templates/index.mustache +++ b/frontend/resources/templates/index.mustache @@ -9,14 +9,15 @@ + {{>../public/images/sprites/symbol/svg/sprite.symbol.svg}}
- {{# manifest}} + {{# manifest}} diff --git a/frontend/src/app/main/ui/icons.clj b/frontend/src/app/main/ui/icons.clj index 393e3a974c..c6fcb056a9 100644 --- a/frontend/src/app/main/ui/icons.clj +++ b/frontend/src/app/main/ui/icons.clj @@ -10,11 +10,9 @@ (ns app.main.ui.icons (:require [rumext.alpha])) -(def base-uri "/images/svg-sprite/symbol/svg/sprite.symbol.svg#icon-") - (defmacro icon-xref [id] - (let [href (str base-uri (name id))] + (let [href (str "#icon-" (name id))] `(rumext.alpha/html [:svg {:width 500 :height 500} [:use {:xlinkHref ~href}]]))) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 6be49c138a..9515c97bfb 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/runtime-corejs3@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.1.tgz#51b9092befbeeed938335a109dbe0df51451e9dc" - integrity sha512-umhPIcMrlBZ2aTWlWjUseW9LjQKxi1dpFlQS8DzsxB//5K+u6GLTC/JliPKHsd5kJVPIU6X/Hy0YvWOYPcMxBw== +"@babel/runtime-corejs3@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.5.tgz#ffee91da0eb4c6dae080774e94ba606368e414f4" + integrity sha512-roGr54CsTmNPPzZoCP1AmDXuBoNao7tnSA83TXTwt+UK5QVyh1DIJnrgYRPWKCF2flqZQXwa7Yr8v7VmLzF0YQ== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -19,6 +19,25 @@ enabled "2.0.x" kuler "^2.0.0" +"@gulp-sourcemaps/identity-map@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz#a6e8b1abec8f790ec6be2b8c500e6e68037c0019" + integrity sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q== + dependencies: + acorn "^6.4.1" + normalize-path "^3.0.0" + postcss "^7.0.16" + source-map "^0.6.0" + through2 "^3.0.1" + +"@gulp-sourcemaps/map-sources@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" + integrity sha1-iQrnxdjId/bThIYCFazp1+yUW9o= + dependencies: + normalize-path "^2.0.1" + through2 "^2.0.3" + "@types/esrever@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@types/esrever/-/esrever-0.2.0.tgz#96404a2284b2c7527f08a1e957f8a31705f9880f" @@ -44,6 +63,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + ajv@^6.12.3: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -54,6 +78,11 @@ ajv@^6.12.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + ansi-colors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" @@ -78,7 +107,17 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-styles@^3.2.1: +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -118,11 +157,24 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -164,6 +216,11 @@ array-each@^1.0.0, array-each@^1.0.1: resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + array-initial@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" @@ -248,6 +305,11 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= + async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -283,12 +345,12 @@ atob@^2.1.2: integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.0.1.tgz#e2d9000f84ebd98d77b7bc16f8adb2ff1f7bb946" - integrity sha512-aQo2BDIsoOdemXUAOBpFv4ZQa2DrOtEufarYhtFsK1088Ca0TUwu/aQWf0M3mrILXZ3mTIVn1lR3hPW8acacsw== + version "10.0.2" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.0.2.tgz#a79f9a02bfb95c621998776ac0d85f8f855b367e" + integrity sha512-okBmu9OMdt6DNEcZmnl0IYVv8Xl/xYWRSnc2OJ9UJEOt1u30opG1B8aLsViqKryBaYv1SKB4f85fOGZs5zYxHQ== dependencies: - browserslist "^4.14.5" - caniuse-lite "^1.0.30001137" + browserslist "^4.14.7" + caniuse-lite "^1.0.30001157" colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" @@ -371,6 +433,13 @@ bintrees@1.0.1: resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524" integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ= +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" @@ -488,15 +557,16 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.14.5: - version "4.14.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" - integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== +browserslist@^4.14.7: + version "4.14.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" + integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== dependencies: - caniuse-lite "^1.0.30001135" - electron-to-chromium "^1.3.571" - escalade "^3.1.0" - node-releases "^1.1.61" + caniuse-lite "^1.0.30001157" + colorette "^1.2.1" + electron-to-chromium "^1.3.591" + escalade "^3.1.1" + node-releases "^1.1.66" buffer-crc32@~0.2.3: version "0.2.13" @@ -552,6 +622,38 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= + camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -562,17 +664,28 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001135, caniuse-lite@^1.0.30001137: - version "1.0.30001151" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001151.tgz#1ddfde5e6fff02aad7940b4edb7d3ac76b0cb00b" - integrity sha512-Zh3sHqskX6mHNrqUerh+fkf0N72cMxrmflzje/JyVImfpknscMnkeJrlFGJcqTmaa0iszdYptGpWMJCRQDkBVw== +caniuse-lite@^1.0.30001157: + version "1.0.30001157" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz#2d11aaeb239b340bc1aa730eca18a37fdb07a9ab" + integrity sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.4.1: +chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -633,7 +746,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@^4.2.3: +clean-css@^4.x: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== @@ -658,6 +771,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -824,12 +946,17 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.5.0: +convert-source-map@^1.0.0, convert-source-map@^1.5.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -850,15 +977,25 @@ copy-props@^2.0.1: is-plain-object "^2.0.1" core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.7.0.tgz#28a57c861d5698e053f0ff36905f7a3301b4191e" + integrity sha512-EZD2ckZysv8MMt4J6HSvS9K2GdtlZtdBncKAmF9lr2n0c9dJUaUN88PSTjvgwCgQPWKTkERXITgS6JJRAnljtg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -890,6 +1027,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -959,6 +1104,15 @@ css-what@^3.2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== +css@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" + integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== + dependencies: + inherits "^2.0.4" + source-map "^0.6.1" + source-map-resolve "^0.6.0" + cssmin@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/cssmin/-/cssmin-0.4.3.tgz#c9194077e0ebdacd691d5f59015b9d819f38d015" @@ -976,6 +1130,13 @@ cssom@^0.3.4: resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -1001,6 +1162,15 @@ dateformat@^3.0.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +debug-fabulous@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" + integrity sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg== + dependencies: + debug "3.X" + memoizee "0.4.X" + object-assign "4.X" + debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -1008,6 +1178,13 @@ debug@3.1.0: dependencies: ms "2.0.0" +debug@3.X: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1015,7 +1192,7 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -decamelize@^1.1.1, decamelize@^1.2.0: +decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -1071,6 +1248,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -1084,6 +1266,11 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= +detect-newline@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -1144,16 +1331,6 @@ duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" -duplexify@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61" - integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA== - dependencies: - end-of-stream "^1.4.1" - inherits "^2.0.3" - readable-stream "^3.1.1" - stream-shift "^1.0.0" - each-props@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" @@ -1180,10 +1357,10 @@ editorconfig@^0.15.3: semver "^5.6.0" sigmund "^1.0.1" -electron-to-chromium@^1.3.571: - version "1.3.583" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.583.tgz#47a9fde74740b1205dba96db2e433132964ba3ee" - integrity sha512-L9BwLwJohjZW9mQESI79HRzhicPk1DFgM+8hOCfGgGCFEcA3Otpv7QK6SGtYoZvfQfE3wKLh0Hd5ptqUFv3gvQ== +electron-to-chromium@^1.3.591: + version "1.3.593" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.593.tgz#947ccf6dc8e013e2b053d2463ecd1043c164fcef" + integrity sha512-GvO7G1ZxvffnMvPCr4A7+iQPVuvpyqMrx2VWSERAjG+pHK6tmO9XqYdBfMIq9corRyi4bNImSDEiDvIoDb8HrA== elliptic@^6.5.3: version "6.5.3" @@ -1198,12 +1375,17 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + enabled@2.0.x: version "2.0.0" resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -1215,7 +1397,7 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== -error-ex@^1.2.0: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -1266,7 +1448,7 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: +es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.53" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== @@ -1297,7 +1479,7 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" -es6-weak-map@^2.0.1: +es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== @@ -1307,12 +1489,12 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -escalade@^3.1.0: +escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -1332,6 +1514,14 @@ esrever@^0.2.0: resolved "https://registry.yarnpkg.com/esrever/-/esrever-0.2.0.tgz#96e9d28f4f1b1a76784cd5d490eaae010e7407b8" integrity sha1-lunSj08bGnZ4TNXUkOquAQ50B7g= +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + events@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" @@ -1439,7 +1629,7 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fancy-log@^1.3.2: +fancy-log@^1.3.2, fancy-log@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== @@ -1584,11 +1774,6 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-stream@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" - integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= - form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -1640,16 +1825,57 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fstream@^1.0.0, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gaze@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== + dependencies: + globule "^1.0.0" + get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -1725,7 +1951,7 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1757,6 +1983,15 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" +globule@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" + integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== + dependencies: + glob "~7.1.1" + lodash "~4.17.10" + minimatch "~3.0.2" + glogg@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" @@ -1810,22 +2045,6 @@ gulp-gzip@^1.4.2: stream-to-array "^2.3.0" through2 "^2.0.3" -gulp-if@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-3.0.0.tgz#6c3e7edc8bafadc34f2ebecb314bf43324ba1e40" - integrity sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw== - dependencies: - gulp-match "^1.1.0" - ternary-stream "^3.0.0" - through2 "^3.0.1" - -gulp-match@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.1.0.tgz#552b7080fc006ee752c90563f9fec9d61aafdf4f" - integrity sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ== - dependencies: - minimatch "^3.0.3" - gulp-mustache@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gulp-mustache/-/gulp-mustache-5.0.0.tgz#5ebc8bbb36a0e657391b341f11325579d4502b07" @@ -1837,11 +2056,52 @@ gulp-mustache@^5.0.0: replace-ext "^1.0.0" through2 "^3.0.1" +gulp-postcss@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/gulp-postcss/-/gulp-postcss-9.0.0.tgz#2ade18809ab475dae743a88bd6501af0b04ee54e" + integrity sha512-5mSQ9CK8salSagrXgrVyILfEMy6I5rUGPRiR9rVjgJV9m/rwdZYUhekMr+XxDlApfc5ZdEJ8gXNZrU/TsgT5dQ== + dependencies: + fancy-log "^1.3.3" + plugin-error "^1.0.1" + postcss-load-config "^2.1.1" + vinyl-sourcemaps-apply "^0.2.1" + gulp-rename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== +gulp-sass@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.1.0.tgz#486d7443c32d42bf31a6b1573ebbdaa361de7427" + integrity sha512-xIiwp9nkBLcJDpmYHbEHdoWZv+j+WtYaKD6Zil/67F3nrAaZtWYN5mDwerdo7EvcdBenSAj7Xb2hx2DqURLGdA== + dependencies: + chalk "^2.3.0" + lodash "^4.17.11" + node-sass "^4.8.3" + plugin-error "^1.0.1" + replace-ext "^1.0.0" + strip-ansi "^4.0.0" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-sourcemaps@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz#2e154e1a2efed033c0e48013969e6f30337b2743" + integrity sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ== + dependencies: + "@gulp-sourcemaps/identity-map" "^2.0.1" + "@gulp-sourcemaps/map-sources" "^1.0.0" + acorn "^6.4.1" + convert-source-map "^1.0.0" + css "^3.0.0" + debug-fabulous "^1.0.0" + detect-newline "^2.0.0" + graceful-fs "^4.0.0" + source-map "^0.6.0" + strip-bom-string "^1.0.0" + through2 "^2.0.0" + gulp-svg-sprite@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/gulp-svg-sprite/-/gulp-svg-sprite-1.5.0.tgz#292694c6af8570093f62cba09092ec8e5241d322" @@ -1881,6 +2141,13 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1891,6 +2158,11 @@ has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -1960,9 +2232,9 @@ he@1.1.1: integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= highlight.js@^10.3.1: - version "10.3.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.3.1.tgz#3ca6bf007377faae347e8135ff25900aac734b9a" - integrity sha512-jeW8rdPdhshYKObedYg5XGbpVgb1/DT4AHvDFXhkU7UnGSIjy9kkJ7zHG7qplhFHMitTSzh5/iClKQk3Kb2RFQ== + version "10.3.2" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.3.2.tgz#135fd3619a00c3cbb8b4cd6dbc78d56bfcbc46f1" + integrity sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw== hmac-drbg@^1.0.0: version "1.0.1" @@ -2009,6 +2281,40 @@ immer@^5.0.0: resolved "https://registry.yarnpkg.com/immer/-/immer-5.3.6.tgz#51eab8cbbeb13075fe2244250f221598818cac04" integrity sha512-pqWQ6ozVfNOUDjrLfm4Pt7q4Q12cGw2HUZgry4Q5+Myxu9nmHRkWBpI0J4+MK0AxbdFtdMTwEGVl7Vd+vEiK+A== +import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= + dependencies: + import-from "^2.1.0" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + integrity sha1-M1238qev/VOqpHHUuAId7ja387E= + dependencies: + resolve-from "^3.0.0" + +in-publish@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c" + integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ== + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= + dependencies: + repeating "^2.0.0" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2017,7 +2323,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2152,6 +2458,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -2169,6 +2480,11 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -2239,6 +2555,11 @@ is-plain-object@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== +is-promise@^2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" @@ -2324,6 +2645,11 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +js-base64@^2.1.8: + version "2.6.4" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" + integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== + js-beautify@^1.13.0: version "1.13.0" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.13.0.tgz#a056d5d3acfd4918549aae3ab039f9f3c51eebb2" @@ -2353,6 +2679,11 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2618,7 +2949,7 @@ lodash.pluck@^3.1.2: lodash.isarray "^3.0.0" lodash.map "^3.0.0" -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4: +lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -2641,7 +2972,15 @@ loose-envify@^1.1.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^4.1.5: +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lru-cache@^4.0.1, lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -2649,6 +2988,13 @@ lru-cache@^4.1.5: pseudomap "^1.0.2" yallist "^2.1.2" +lru-queue@0.1: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= + dependencies: + es5-ext "~0.10.2" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -2668,6 +3014,11 @@ map-cache@^0.2.0, map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + map-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" @@ -2718,10 +3069,35 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +memoizee@0.4.X: + version "0.4.14" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== + dependencies: + d "1" + es5-ext "^0.10.45" + es6-weak-map "^2.0.2" + event-emitter "^0.3.5" + is-promise "^2.1" + lru-queue "0.1" + next-tick "1" + timers-ext "^0.1.5" + +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" @@ -2777,7 +3153,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -2789,7 +3165,7 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.2.5: +minimist@^1.1.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -2809,7 +3185,7 @@ mkdirp@0.5.1: dependencies: minimist "0.0.8" -mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -2868,12 +3244,12 @@ mute-stdout@^1.0.0: resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== -nan@^2.12.1: +nan@^2.12.1, nan@^2.13.2: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.15: +nanoid@^3.1.16: version "3.1.16" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" integrity sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w== @@ -2895,6 +3271,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +next-tick@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + next-tick@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" @@ -2905,6 +3286,24 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-gyp@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" + integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "^2.87.0" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -2934,10 +3333,40 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-releases@^1.1.61: - version "1.1.64" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.64.tgz#71b4ae988e9b1dd7c1ffce58dd9e561752dfebc5" - integrity sha512-Iec8O9166/x2HRMJyLLLWkd0sFFLrFNy+Xf+JQfSQsdBJzPcHpNl3JQ9gD4j+aJxmCa25jNsIbM4bmACtSbkSg== +node-releases@^1.1.66: + version "1.1.66" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" + integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== + +node-sass@^4.8.3: + version "4.14.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" + integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash "^4.17.15" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.13.2" + node-gyp "^3.8.0" + npmlog "^4.0.0" + request "^2.88.0" + sass-graph "2.2.5" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" nopt@^5.0.0: version "5.0.0" @@ -2946,7 +3375,7 @@ nopt@^5.0.0: dependencies: abbrev "1" -normalize-package-data@^2.3.2: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -2956,7 +3385,7 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.1.1: +normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= @@ -2987,6 +3416,16 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -3009,7 +3448,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.1: +object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -3127,6 +3566,11 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" @@ -3143,6 +3587,19 @@ os-locale@^3.0.0: lcid "^2.0.0" mem "^4.0.0" +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@0: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -3209,6 +3666,14 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse-node-version@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" @@ -3355,19 +3820,53 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postcss-clean@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-clean/-/postcss-clean-1.1.0.tgz#c2d61d5d8caf19a585adba16897726c2674c4207" + integrity sha512-83g3GqMbCM5NL6MlbbPLJ/m2NrUepBF44MoDk4Gt04QGXeXKh9+ilQa0DzLnYnvqYHQCw83nckuEzBFr2muwbg== + dependencies: + clean-css "^4.x" + postcss "^6.x" + +postcss-load-config@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== + dependencies: + cosmiconfig "^5.0.0" + import-cwd "^2.0.0" + postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^8.1.2: - version "8.1.4" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.4.tgz#356dfef367a70f3d04347f74560c85846e20e4c1" - integrity sha512-LfqcwgMq9LOd8pX7K2+r2HPitlIGC5p6PoZhVELlqhh2YGDVcXKpkCseqan73Hrdik6nBd2OvoDPUaP/oMj9hQ== +postcss@^6.x: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.16: + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^8.1.7: + version "8.1.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f" + integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ== dependencies: colorette "^1.2.1" line-column "^1.0.2" - nanoid "^3.1.15" + nanoid "^3.1.16" source-map "^0.6.1" pretty-hrtime@^1.0.0: @@ -3536,7 +4035,7 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -"readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -3545,7 +4044,7 @@ read-pkg@^1.0.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -3586,6 +4085,14 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + regenerator-runtime@^0.13.4: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" @@ -3631,6 +4138,13 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + replace-ext@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" @@ -3652,7 +4166,7 @@ request-progress@^2.0.1: dependencies: throttleit "^1.0.0" -request@^2.81.0: +request@^2.81.0, request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -3688,6 +4202,11 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" @@ -3696,6 +4215,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: expand-tilde "^2.0.0" global-modules "^1.0.0" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" @@ -3721,6 +4245,13 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rimraf@2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -3765,10 +4296,20 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sass-graph@2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" + integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^13.3.2" + sass@^1.26.10: - version "1.27.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.27.0.tgz#0657ff674206b95ec20dc638a93e179c78f6ada2" - integrity sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig== + version "1.29.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.29.0.tgz#ec4e1842c146d8ea9258c28c141b8c2b7c6ab7f1" + integrity sha512-ZpwAUFgnvAUCdkjwPREny+17BpUj8nh5Yr6zKPGtLNTLrmtoRYIjm7njP24COhjJldjwW1dcv52Lpf4tNZVVRA== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -3792,6 +4333,14 @@ scroll-into-view-if-needed@^2.2.20: dependencies: compute-scroll-into-view "^1.0.16" +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + semver-greatest-satisfied-range@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" @@ -3804,7 +4353,12 @@ semver-greatest-satisfied-range@^1.1.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -set-blocking@^2.0.0: +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -3987,6 +4541,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-resolve@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" @@ -4007,7 +4569,14 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.6: +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha1-66T12pwNyZneaAMti092FzZSA2s= + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.1, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -4093,6 +4662,13 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" +stdout-stream@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" + integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== + dependencies: + readable-stream "^2.0.1" + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -4138,7 +4714,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -4146,6 +4722,15 @@ string-width@^2.0.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string.prototype.trimend@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" @@ -4190,6 +4775,18 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -4202,6 +4799,13 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= + dependencies: + get-stdin "^4.0.1" + supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" @@ -4209,13 +4813,25 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" -supports-color@^5.3.0: +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + sver-compat@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" @@ -4270,6 +4886,15 @@ svgo@^1.1.1: unquote "~1.1.1" util.promisify "~1.0.0" +tar@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== + dependencies: + block-stream "*" + fstream "^1.0.12" + inherits "2" + tdigest@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.1.tgz#2e3cb2c39ea449e55d1e6cd91117accca4588021" @@ -4277,16 +4902,6 @@ tdigest@^0.1.1: dependencies: bintrees "1.0.1" -ternary-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-3.0.0.tgz#7951930ea9e823924d956f03d516151a2d516253" - integrity sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ== - dependencies: - duplexify "^4.1.1" - fork-stream "^0.0.4" - merge-stream "^2.0.0" - through2 "^3.0.1" - text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -4333,6 +4948,14 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timers-ext@^0.1.5: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + tiny-warning@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" @@ -4398,11 +5021,23 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= + triple-beam@^1.2.0, triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== +"true-case-path@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== + dependencies: + glob "^7.1.2" + tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -4631,6 +5266,13 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" +vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= + dependencies: + source-map "^0.5.1" + vinyl@^2.0.0, vinyl@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" @@ -4658,13 +5300,20 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.10, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@1, which@^1.2.10, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + winston-transport@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59" @@ -4696,6 +5345,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4721,11 +5379,11 @@ xpath@^0.0.27: integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ== xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== + version "4.4.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.4.0.tgz#29660f5d6567cd2ef981dd4a50cb05d22c10719d" + integrity sha512-83y4aa8o8o4NZe+L+46wpa+F1cWR/wCGOWI3tzqUso0w3/KAvXy0+Di7Oe/cbNMixDR4Jmi7NEybWU6ps25Wkg== dependencies: - "@babel/runtime-corejs3" "^7.8.3" + "@babel/runtime-corejs3" "^7.12.1" xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" @@ -4737,7 +5395,7 @@ y18n@^3.2.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= -"y18n@^3.2.1 || ^4.0.0": +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== @@ -4763,6 +5421,14 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs@^12.0.2: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" @@ -4781,6 +5447,22 @@ yargs@^12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + yargs@^7.1.0: version "7.1.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" From 51f9dfbc4f34ecbc7c3644985361154af6673942 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 13 Nov 2020 09:30:05 +0100 Subject: [PATCH 004/195] :bug: Fixed port problem --- backend/src/app/srepl/server.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/app/srepl/server.clj b/backend/src/app/srepl/server.clj index d83d44067b..52a69538f4 100644 --- a/backend/src/app/srepl/server.clj +++ b/backend/src/app/srepl/server.clj @@ -21,7 +21,7 @@ (defstate server :start (ccs/start-server {:address "127.0.0.1" - :port 6061 + :port 6062 :name "main" :accept 'app.srepl.server/repl}) :stop (ccs/stop-server "main")) From 388d255243fc4dceaf9393514b4a125486cf4170 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 13 Nov 2020 11:23:09 +0100 Subject: [PATCH 005/195] :bug: Properly handle share-tokens on viewer. --- backend/src/app/http/errors.clj | 6 ++++ backend/src/app/services/queries/viewer.clj | 37 ++++++++++----------- frontend/src/app/main/data/auth.cljs | 3 +- frontend/src/app/main/data/viewer.cljs | 16 ++++----- frontend/src/app/main/ui.cljs | 8 +++-- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index fe87fe3cf5..d723b28c6b 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -16,6 +16,12 @@ (fn [err & rest] (:type (ex-data err)))) + +(defmethod handle-exception :authorization + [err req] + {:status 403 + :body (ex-data err)}) + (defmethod handle-exception :validation [err req] (let [header (get-in req [:headers "accept"]) diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index bfd5b9aaee..172654e8b6 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -35,40 +35,39 @@ (s/def ::id ::us/uuid) (s/def ::file-id ::us/uuid) (s/def ::page-id ::us/uuid) -(s/def ::share-token ::us/string) +(s/def ::token ::us/string) (s/def ::viewer-bundle (s/keys :req-un [::file-id ::page-id] - :opt-un [::profile-id ::share-token])) + :opt-un [::profile-id ::token])) (sq/defquery ::viewer-bundle - [{:keys [profile-id file-id page-id share-token] :as params}] + [{:keys [profile-id file-id page-id token] :as params}] (db/with-atomic [conn db/pool] (let [file (files/retrieve-file conn file-id) - project (retrieve-project conn (:project-id file)) page (get-in file [:data :pages-index page-id]) - - file-library (select-keys (:data file) [:colors :media :typographies]) - bundle {:file (-> (dissoc file :data) - (merge file-library)) - :page (get-in file [:data :pages-index page-id]) - :project project} - ] - (if (string? share-token) + file (merge (dissoc file :data) + (select-keys (:data file) [:colors :media :typographies])) + libs (files/retrieve-file-libraries conn false file-id) + bundle {:file file + :page page + :project project + :libraries libs}] + (if (string? token) (do - (check-shared-token! conn file-id page-id share-token) - (assoc bundle :share-token share-token)) - (let [token (retrieve-shared-token conn file-id page-id)] - (files/check-edition-permissions! conn profile-id file-id) - (assoc bundle :share-token token)))))) + (check-shared-token! conn file-id page-id token) + (assoc bundle :token token)) + (let [stoken (retrieve-shared-token conn file-id page-id)] + (files/check-read-permissions! conn profile-id file-id) + (assoc bundle :share-token (:token stoken))))))) (defn check-shared-token! [conn file-id page-id token] (let [sql "select exists(select 1 from file_share_token where file_id=? and page_id=? and token=?) as exists"] (when-not (:exists (db/exec-one! conn [sql file-id page-id token])) - (ex/raise :type :validation - :code :not-authorized)))) + (ex/raise :type :authorization + :code :unauthorized-token)))) (defn retrieve-shared-token [conn file-id page-id] diff --git a/frontend/src/app/main/data/auth.cljs b/frontend/src/app/main/data/auth.cljs index 2209cdd995..ad0b31e1b9 100644 --- a/frontend/src/app/main/data/auth.cljs +++ b/frontend/src/app/main/data/auth.cljs @@ -120,7 +120,8 @@ (reset! storage {}) (i18n/set-default-locale!)))) -(def logout +(defn logout + [] (ptk/reify ::logout ptk/WatchEvent (watch [_ state stream] diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 67c1310abf..b40917be69 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -71,13 +71,10 @@ (watch [_ state stream] (let [params (cond-> {:page-id page-id :file-id file-id} - (string? token) (assoc :share-token token))] - (->> (rx/zip (rp/query :viewer-bundle params) - (rp/query :file-libraries {:file-id file-id})) + (string? token) (assoc :token token))] + (->> (rp/query :viewer-bundle params) (rx/first) - (rx/map #(apply bundle-fetched %)) - #_(rx/catch (fn [error-data] - (rx/of (rt/nav :not-found))))))))) + (rx/map bundle-fetched)))))) (defn- extract-frames [objects] @@ -89,7 +86,7 @@ (vec)))) (defn bundle-fetched - [{:keys [project file page share-token] :as bundle} libraries] + [{:keys [project file page share-token token libraries] :as bundle}] (us/verify ::bundle bundle) (ptk/reify ::file-fetched ptk/UpdateEvent @@ -103,6 +100,7 @@ :file file :page page :frames frames + :token token :share-token share-token})))))) (def create-share-link @@ -244,12 +242,12 @@ (let [page-id (get-in state [:viewer-local :page-id]) file-id (get-in state [:viewer-local :file-id]) frames (get-in state [:viewer-data :frames]) - share-token (get-in state [:viewer-data :share-token]) + token (get-in state [:viewer-data :token]) index (d/index-of-pred frames #(= (:id %) frame-id))] (rx/of (rt/nav :viewer {:page-id page-id :file-id file-id} - {:token share-token + {:token token :index index})))))) (defn set-current-frame [frame-id] diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 611ba44f1f..e81e7801ca 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -178,7 +178,7 @@ (defmethod ptk/handle-error :validation [error] (ts/schedule - (st/emitf (dm/show {:content "Unexpected validation error." + (st/emitf (dm/show {:content "Unexpected validation error (server side)." :type :error :timeout 5000}))) (when-let [explain (:explain error)] @@ -190,11 +190,13 @@ (defmethod ptk/handle-error :authentication [error] - (ts/schedule 0 #(st/emit! logout))) + (ts/schedule 0 #(st/emit! (logout)))) (defmethod ptk/handle-error :authorization [error] - (ts/schedule 0 #(st/emit! logout))) + (ts/schedule + (st/emitf (dm/show {:content "Not authorized to see this content." + :type :error})))) (defmethod ptk/handle-error :assertion [{:keys [data stack message context] :as error}] From 48663eacdcff971371ac88ce61c6483b6e1fa558 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 13 Nov 2020 11:46:57 +0100 Subject: [PATCH 006/195] :bug: Fix incorrect type handling on group operation. And improve specs related to group attrs. --- common/app/common/pages.cljc | 12 ++++++++---- frontend/src/app/main/data/workspace.cljs | 3 +-- .../src/app/main/data/workspace/selection.cljs | 18 +++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index c5ad442da7..d202743d96 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -262,10 +262,13 @@ :internal.shape/height])) (s/def :internal.shape/point - (s/keys :req-un [:internal.shape/x :internal.shape/y])) + (s/and (s/keys :req-un [:internal.shape/x :internal.shape/y]) gpt/point?)) (s/def :internal.shape/points - (s/coll-of :internal.shape/point :kind vector?)) + (s/every :internal.shape/point :kind vector?)) + +(s/def :internal.shape/shapes + (s/every uuid? :kind vector?)) (s/def ::shape-attrs (s/keys :opt-un [:internal.shape/blocked @@ -292,6 +295,7 @@ :internal.shape/x :internal.shape/y :internal.shape/exports + :internal.shape/shapes :internal.shape/stroke-color :internal.shape/stroke-color-ref-file :internal.shape/stroke-color-ref-id @@ -433,7 +437,7 @@ (s/def :internal.operations.set/attr keyword?) (s/def :internal.operations.set/val any?) -(s/def :internal.operations.set/touched +(s/def :internal.operations.set/touched (s/nilable (s/every keyword? :kind set?))) (defmethod operation-spec :set [_] @@ -475,7 +479,7 @@ (s/keys :req-un [::page-id :internal.changes.reg-objects/shapes])) (defmethod change-spec :mov-objects [_] - (s/keys :req-un [::page-id ::parent-id ::shapes] + (s/keys :req-un [::page-id ::parent-id :internal.shape/shapes] :opt-un [::index])) (defmethod change-spec :add-page [_] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index ef40318313..24cbc6b989 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1479,8 +1479,7 @@ selected (get-in state [:workspace-local :selected]) shapes (dws/shapes-for-grouping objects selected)] (when-not (empty? shapes) - (let [[group rchanges uchanges] - (dws/prepare-create-group page-id shapes "Group-" false)] + (let [[group rchanges uchanges] (dws/prepare-create-group page-id shapes "Group-" false)] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (dws/select-shapes (d/ordered-set (:id group)))))))))) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 136333ef6b..f2ef8af360 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -118,7 +118,7 @@ objects (dwc/lookup-page-objects state page-id)] (rx/of (dwc/expand-all-parents ids objects)))))) -(defn deselect-all +(defn deselect-all "Clear all possible state of drawing, edition or any similar action taken by the user. When `check-modal` the method will check if a modal is opened @@ -202,7 +202,7 @@ (name (gensym prefix)))] (-> (cp/make-minimal-group frame-id selrect group-name) (geom/setup selrect) - (assoc :shapes (map :id shapes))))) + (assoc :shapes (mapv :id shapes))))) (defn prepare-create-group [page-id shapes prefix keep-name] @@ -217,15 +217,15 @@ {:type :mov-objects :page-id page-id :parent-id (:id group) - :shapes (map :id shapes)}] + :shapes (mapv :id shapes)}] uchanges (conj - (map (fn [obj] {:type :mov-objects - :page-id page-id - :parent-id (:parent-id obj) - :index (::index obj) - :shapes [(:id obj)]}) - shapes) + (mapv (fn [obj] {:type :mov-objects + :page-id page-id + :parent-id (:parent-id obj) + :index (::index obj) + :shapes [(:id obj)]}) + shapes) {:type :del-obj :id (:id group) :page-id page-id})] From bf7cfef355aa3ead1f27d0e6cd24b59cfc928782 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 13 Nov 2020 12:11:49 +0100 Subject: [PATCH 007/195] :bug: Fix unaligned share-token dropdown. --- frontend/resources/styles/main/partials/viewer-header.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/resources/styles/main/partials/viewer-header.scss b/frontend/resources/styles/main/partials/viewer-header.scss index 97e076b1be..219048f6bc 100644 --- a/frontend/resources/styles/main/partials/viewer-header.scss +++ b/frontend/resources/styles/main/partials/viewer-header.scss @@ -172,7 +172,7 @@ box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25); display: flex; flex-direction: column; - left: -180px; + left: -135px; position: absolute; padding: 1rem; top: 45px; From 24f0a3945dbe6f52d2ecafe80c1d068103cff627 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 13 Nov 2020 12:44:35 +0100 Subject: [PATCH 008/195] :bug: Temporal workaround. --- common/app/common/pages.cljc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index d202743d96..bb92b63ea4 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -268,7 +268,7 @@ (s/every :internal.shape/point :kind vector?)) (s/def :internal.shape/shapes - (s/every uuid? :kind vector?)) + (s/every uuid?)) (s/def ::shape-attrs (s/keys :opt-un [:internal.shape/blocked @@ -295,7 +295,7 @@ :internal.shape/x :internal.shape/y :internal.shape/exports - :internal.shape/shapes + ;; :internal.shape/shapes :internal.shape/stroke-color :internal.shape/stroke-color-ref-file :internal.shape/stroke-color-ref-id From 1ffdb41cfc7954ad34db3f68c22d9424a48ad6e0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 13 Nov 2020 14:47:34 +0100 Subject: [PATCH 009/195] :bug: Add data migration for ensure proper types on group like shapes. Becuse of a bug, the `:shapes` attribute on group like objects had become to seq when they should be a vector. The real fix is already in other commit. This commit adds a migration for address the old data already stored in the database. --- common/app/common/pages.cljc | 6 ++--- common/app/common/pages_migrations.cljc | 29 +++++++++++-------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index bb92b63ea4..b46f12ed4f 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -20,7 +20,7 @@ [app.common.spec :as us] [app.common.uuid :as uuid])) -(def file-version 1) +(def file-version 2) (def max-safe-int 9007199254740991) (def min-safe-int -9007199254740991) @@ -268,7 +268,7 @@ (s/every :internal.shape/point :kind vector?)) (s/def :internal.shape/shapes - (s/every uuid?)) + (s/every uuid? :kind vector?)) (s/def ::shape-attrs (s/keys :opt-un [:internal.shape/blocked @@ -295,7 +295,7 @@ :internal.shape/x :internal.shape/y :internal.shape/exports - ;; :internal.shape/shapes + :internal.shape/shapes :internal.shape/stroke-color :internal.shape/stroke-color-ref-file :internal.shape/stroke-color-ref-id diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index 33171c9fb2..7d9b89bc03 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -34,21 +34,18 @@ ;; -- MIGRATIONS -- -(defn- generate-child-parent-index - [objects] - (reduce-kv - (fn [index id obj] - (into index (map #(vector % id) (:shapes obj [])))) - {} objects)) +;; Ensure that all :shape attributes on shapes are vectors. -;; (defmethod migrate 5 -;; [data] -;; (update data :objects -;; (fn [objects] -;; (let [index (generate-child-parent-index objects)] -;; (d/mapm -;; (fn [id obj] -;; (let [parent-id (get index id)] -;; (assoc obj :parent-id parent-id))) -;; objects))))) +(defmethod migrate 2 + [data] + (letfn [(update-object [id object] + (d/update-when object :shapes + (fn [shapes] + (if (seq? shapes) + (into [] shapes) + shapes)))) + (update-page [id page] + (update page :objects #(d/mapm update-object %)))] + + (update data :pages-index #(d/mapm update-page %)))) From 0f7773882afc7d254c1fecce874eea2cf422cd28 Mon Sep 17 00:00:00 2001 From: Ryan Fowler Date: Thu, 12 Nov 2020 15:26:36 -0700 Subject: [PATCH 010/195] :books: Fix typo in readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4fcbb7c0b4..ce1214b4a9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ # PENPOT # -We’re excited to share that Uxbox is now Penpot! We’re changing the name, but keeping the same project essence. Stay in the loop for more news comming early 2021. Alpha release is close! +We’re excited to share that Uxbox is now Penpot! We’re changing the name, but keeping the same project essence. Stay in the loop for more news coming early 2021. Alpha release is close! ![PENPOT](https://raw.githubusercontent.com/penpot/penpot/develop/docs/screenshot.png) From 447293bc4e16bb20f95890a26c48007b522fa500 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 09:51:53 +0100 Subject: [PATCH 011/195] :bug: Fix tooltips and modals. --- frontend/resources/styles/main/partials/modal.scss | 13 ++++++++----- .../styles/main/partials/viewer-header.scss | 4 ++-- frontend/src/app/main/ui/viewer/header.cljs | 8 ++++---- frontend/src/app/main/ui/workspace/header.cljs | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index 92100c35ea..f4b4429b28 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -59,7 +59,7 @@ // NEW GEN MODALS .modal-container { - border-radius: 8px; + border-radius: $br-medium; display: flex; flex-direction: column; width: 448px; @@ -78,10 +78,12 @@ .modal-header-title { display: flex; align-items: center; - font-size: $fs24; + font-size: $fs18; padding-left: 16px; h2 { + font-size: $fs18; + font-weight: 400; margin: 0; } } @@ -204,8 +206,9 @@ } .libraries-dialog { - width: 920px; + border-radius: $br-medium; height: 664px; + width: 920px; .modal-content { display: flex; @@ -319,9 +322,9 @@ } .libraries-search { - border: 1px solid $color-gray-30; + border: 1px solid $color-gray-20; margin: $size-4; - padding: $x-small; + padding: $x-small $small; display: flex; align-items: center; diff --git a/frontend/resources/styles/main/partials/viewer-header.scss b/frontend/resources/styles/main/partials/viewer-header.scss index 219048f6bc..4648e1c099 100644 --- a/frontend/resources/styles/main/partials/viewer-header.scss +++ b/frontend/resources/styles/main/partials/viewer-header.scss @@ -126,8 +126,8 @@ svg { fill: $color-gray-20; - width: 24px; - height: 24px; + width: 20px; + height: 20px; } &.active { diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 4992e4b958..62bcb539a4 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -164,12 +164,12 @@ [:span.counters (str (inc index) " / " total)]] [:div.mode-zone - [:button.mode-zone-button {:on-click #(when (not= screen :viewer) + [:button.mode-zone-button.tooltip.tooltip-bottom {:on-click #(when (not= screen :viewer) (change-screen :viewer)) - :class (when (= screen :viewer) "active")} i/play] - [:button.mode-zone-button {:on-click #(when (not= screen :handoff) + :class (when (= screen :viewer) "active") :alt "View mode"} i/play] + [:button.mode-zone-button.tooltip.tooltip-bottom {:on-click #(when (not= screen :handoff) (change-screen :handoff)) - :class (when (= screen :handoff) "active")} i/code]] + :class (when (= screen :handoff) "active") :alt "Code mode"} i/code]] [:div.options-zone [:& interactions-menu {:interactions-mode interactions-mode}] diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 3ceaa5aaf1..2ec8e2e0b3 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -258,7 +258,7 @@ :on-zoom-fit #(st/emit! dw/zoom-to-fit-all) :on-zoom-selected #(st/emit! dw/zoom-to-selected-shape)}] - [:a.btn-icon-dark.btn-small + [:a.btn-icon-dark.btn-small.tooltip.tooltip-bottom {;; :target "__blank" :alt (t locale "workspace.header.viewer") :href (str "#" view-url)} i/play]]])) From 5dc646e44e8e53c75d1243bdf0430de8382d5a50 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 10:44:34 +0100 Subject: [PATCH 012/195] :sparkles: Add color bullet changes --- .../resources/styles/main/partials/color-bullet.scss | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/resources/styles/main/partials/color-bullet.scss b/frontend/resources/styles/main/partials/color-bullet.scss index b4ee15997d..a8041e58b0 100644 --- a/frontend/resources/styles/main/partials/color-bullet.scss +++ b/frontend/resources/styles/main/partials/color-bullet.scss @@ -9,11 +9,15 @@ .color-cell { .color-bullet { - background-color: $color-white; + background-color: transparent; // Creates strange artifacts border: 2px solid $color-gray-60; // box-shadow: 0 0 0 2px $color-gray-60; border-radius: 50%; + + &:hover { + border-color: $color-primary; + } } &.cell-big .color-bullet { @@ -74,10 +78,11 @@ ul.palette-menu .color-bullet { } .asset-group .group-list-item .color-bullet { - width: 20px; - height: 20px; + border: 1px solid $color-gray-20; border-radius: 10px; + height: 20px; margin-right: $x-small; + width: 20px; } .color-cell.add-color:hover .color-bullet { From 385616f3dfeda10257d4bed75659f4574bd92e68 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 12:47:14 +0100 Subject: [PATCH 013/195] :tada: Add new visual changes --- frontend/resources/styles/common/framework.scss | 10 ++++++++++ frontend/resources/styles/main/partials/modal.scss | 2 ++ .../styles/main/partials/sidebar-assets.scss | 11 ++++++++--- .../src/app/main/ui/workspace/sidebar/assets.cljs | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/frontend/resources/styles/common/framework.scss b/frontend/resources/styles/common/framework.scss index 815343e43b..ec14acfb0e 100644 --- a/frontend/resources/styles/common/framework.scss +++ b/frontend/resources/styles/common/framework.scss @@ -1001,6 +1001,16 @@ input[type=range]:focus::-ms-fill-upper { } } + &.tooltip-left { + &:hover { + &::after { + left: unset; + right: 130%; + top: 15%; + } + } + } + &.tooltip-hover { &:hover { &::after { diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index f4b4429b28..12a9ab1d04 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -260,8 +260,10 @@ } .section-title { + color: $color-black; font-size: $fs15; padding: 0 $size-4; + font-weight: 500; } .section-list { diff --git a/frontend/resources/styles/main/partials/sidebar-assets.scss b/frontend/resources/styles/main/partials/sidebar-assets.scss index 29938b2386..7872c0afc8 100644 --- a/frontend/resources/styles/main/partials/sidebar-assets.scss +++ b/frontend/resources/styles/main/partials/sidebar-assets.scss @@ -117,6 +117,7 @@ .asset-group { background-color: $color-gray-60; + border-top: 1px solid $color-gray-50; padding: $small; font-size: $fs12; color: $color-gray-20; @@ -164,10 +165,10 @@ } .group-grid { - margin-top: $small; + margin-top: $medium; display: grid; - grid-template-columns: 1fr 1fr 1fr; - grid-auto-rows: 7vh; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-auto-rows: 6vh; column-gap: 0.5rem; row-gap: 0.5rem; @@ -253,6 +254,10 @@ // overflow-y: scroll; // } + .group-list { + margin-top: $medium; + } + .group-list-item { display: flex; align-items: center; diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 42f4678519..4363dbe8f8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -570,7 +570,7 @@ [:span.tool-badge (t locale "workspace.assets.shared")])] [:* [:span (:name file)] - [:span.tool-link + [:span.tool-link.tooltip.tooltip-left {:alt "Open library file"} [:a {:href (str "#" url) :target "_blank"} i/chain]]])] (when @open? From 6f9cf454a2917a07b8b1e1ad86d77977f8c43843 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 13:10:16 +0100 Subject: [PATCH 014/195] :bug: Fix dashboard options item icon. --- .../styles/main/partials/dashboard-grid.scss | 47 ++----------------- 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/frontend/resources/styles/main/partials/dashboard-grid.scss b/frontend/resources/styles/main/partials/dashboard-grid.scss index 76cda8a6b6..7f0364275c 100644 --- a/frontend/resources/styles/main/partials/dashboard-grid.scss +++ b/frontend/resources/styles/main/partials/dashboard-grid.scss @@ -180,7 +180,7 @@ .project-th-actions { align-items: center; - bottom: 0; + bottom: 4px; display: none; left: 0; justify-content: flex-end; @@ -190,9 +190,9 @@ svg { fill: $color-gray-20; - height: 14px; + height: 18px; margin-right: $x-small; - width: 14px; + width: 18px; } span { @@ -208,13 +208,11 @@ margin-right: 0; svg { - fill: $color-gray-30; + fill: $color-gray-60; margin-right: 0; } &:hover { - transform: scale(1.4); - svg { fill: $color-primary-dark; } @@ -223,43 +221,6 @@ } - &.delete { - margin-right: 0; - - svg { - fill: $color-gray-30; - margin-right: 0; - } - - &:hover { - transform: scale(1.4); - - svg { - fill: $color-danger; - } - - } - - } - - &.edit { - margin-right: 0; - - svg { - fill: $color-gray-30; - } - - &:hover { - transform: scale(1.4); - - svg { - fill: $color-gray-60; - } - - } - - } - } } From 619e51d2581889cf69da77797df1860f584edabf Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 13:31:35 +0100 Subject: [PATCH 015/195] :tada: Change status new style. --- frontend/resources/styles/main/partials/sidebar-assets.scss | 2 +- .../resources/styles/main/partials/workspace-header.scss | 5 +++++ frontend/resources/styles/main/partials/workspace.scss | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-assets.scss b/frontend/resources/styles/main/partials/sidebar-assets.scss index 7872c0afc8..a10d01ced5 100644 --- a/frontend/resources/styles/main/partials/sidebar-assets.scss +++ b/frontend/resources/styles/main/partials/sidebar-assets.scss @@ -44,7 +44,7 @@ .search-block { border: 1px solid $color-gray-30; margin: $small $small 0 $small; - padding: $x-small; + padding: $x-small $small; display: flex; align-items: center; diff --git a/frontend/resources/styles/main/partials/workspace-header.scss b/frontend/resources/styles/main/partials/workspace-header.scss index 060688ff9d..5506421c52 100644 --- a/frontend/resources/styles/main/partials/workspace-header.scss +++ b/frontend/resources/styles/main/partials/workspace-header.scss @@ -209,6 +209,11 @@ .label { color: $color-danger; } .icon svg { fill: $color-danger; } } + + &.pending { + .label { color: $color-warning; } + .icon svg { fill: $color-warning; } + } } .icon { diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index add2038780..ccccec01e1 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -99,7 +99,7 @@ position: fixed; right: calc(#{$width-settings-bar} + 10px); text-align: center; - width: 100px; + width: 110px; padding-bottom: 2px; span { From ac9622ac07a5b59627ac5bb67559e0d44d638eac Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 14:34:24 +0100 Subject: [PATCH 016/195] :bug: Fix firefox flex bugs --- frontend/resources/styles/main/partials/colorpicker.scss | 2 +- .../resources/styles/main/partials/sidebar-element-options.scss | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/resources/styles/main/partials/colorpicker.scss b/frontend/resources/styles/main/partials/colorpicker.scss index 90323f6779..dd88e6b85e 100644 --- a/frontend/resources/styles/main/partials/colorpicker.scss +++ b/frontend/resources/styles/main/partials/colorpicker.scss @@ -309,7 +309,7 @@ font-size: 0.75rem; color: $color-gray-40; cursor: pointer; - border-color: $color-gray-10; + border: 1px solid $color-gray-10; border-radius: 2px; option { diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index b24ef1c5e4..3c47a77c55 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -194,6 +194,7 @@ color: $color-white; font-size: $fs12; margin: $x-small; + min-width: 0; padding: $x-small; width: 100%; From a90f3f2176dc3695b225d794cbd580efc4d51496 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 15:16:02 +0100 Subject: [PATCH 017/195] :tada: Add new libraries assets icon --- frontend/resources/images/icons/icon-list.svg | 1 + frontend/resources/styles/main/partials/sidebar-assets.scss | 6 +++--- frontend/src/app/main/ui/icons.cljs | 1 + frontend/src/app/main/ui/workspace/sidebar/assets.cljs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 frontend/resources/images/icons/icon-list.svg diff --git a/frontend/resources/images/icons/icon-list.svg b/frontend/resources/images/icons/icon-list.svg new file mode 100644 index 0000000000..eb47d32f29 --- /dev/null +++ b/frontend/resources/images/icons/icon-list.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/styles/main/partials/sidebar-assets.scss b/frontend/resources/styles/main/partials/sidebar-assets.scss index a10d01ced5..f19b1a2976 100644 --- a/frontend/resources/styles/main/partials/sidebar-assets.scss +++ b/frontend/resources/styles/main/partials/sidebar-assets.scss @@ -26,9 +26,9 @@ svg { fill: $color-gray-30; - height: 20px; - width: 20px; - padding-right: $x-small; + height: 16px; + width: 16px; + padding-right: 6px; } } diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 08ac0679d7..5f9fc07059 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -49,6 +49,7 @@ (def grid (icon-xref :grid)) (def grid-snap (icon-xref :grid-snap)) (def icon-empty (icon-xref :icon-empty)) +(def icon-list (icon-xref :icon-list)) (def icon-lock (icon-xref :icon-lock)) (def icon-set (icon-xref :icon-set)) (def image (icon-xref :image)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 4363dbe8f8..4d9f56b846 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -667,7 +667,7 @@ [:div.assets-bar-title (t locale "workspace.assets.assets") [:div.libraries-button {:on-click #(modal/show! :libraries-dialog {})} - i/libraries + i/text-align-justify (t locale "workspace.assets.libraries")]] [:div.search-block From 5f4d1b9e10193f0dcd3bbeac0446d8a907884220 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Fri, 13 Nov 2020 15:24:51 +0100 Subject: [PATCH 018/195] :paperclip: Just wording --- frontend/resources/locales.json | 4 ++-- frontend/src/app/main/ui/auth/register.cljs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 111dad5212..844251b9c9 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -56,7 +56,7 @@ "auth.forgot-password" : { "used-in" : [ "src/app/main/ui/auth/login.cljs:122" ], "translations" : { - "en" : "Forgot your password?", + "en" : "Forgot password?", "fr" : "Mot de passe oublié?", "ru" : "Забыли пароль?", "es" : "¿Olvidaste tu contraseña?" @@ -224,7 +224,7 @@ "auth.recovery-request-title" : { "used-in" : [ "src/app/main/ui/auth/recovery_request.cljs:61" ], "translations" : { - "en" : "Forgot your password?", + "en" : "Forgot password?", "fr" : "Vous avez oublié votre mot de passe?", "ru" : "Забыли пароль?", "es" : "¿Olvidaste tu contraseña?" diff --git a/frontend/src/app/main/ui/auth/register.cljs b/frontend/src/app/main/ui/auth/register.cljs index 81674ebf1b..756cd3b5bf 100644 --- a/frontend/src/app/main/ui/auth/register.cljs +++ b/frontend/src/app/main/ui/auth/register.cljs @@ -133,4 +133,4 @@ [:span (t locale "auth.create-demo-profile") " "] [:a {:on-click #(st/emit! da/create-demo-profile) :tab-index "5"} - (t locale "auth.create-demo-profile")]]]]) + (t locale "auth.create-demo-account")]]]]) \ No newline at end of file From 6e57d93f747d4f2fbd590f9ee2f8108452bb766c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 16 Nov 2020 11:30:59 +0100 Subject: [PATCH 019/195] :tada: Add polyfill to requestIdleCallback (not supported on safari). --- frontend/src/app/util/timers.cljs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/util/timers.cljs b/frontend/src/app/util/timers.cljs index ef6f39e299..1861613449 100644 --- a/frontend/src/app/util/timers.cljs +++ b/frontend/src/app/util/timers.cljs @@ -33,16 +33,28 @@ (-dispose [_] (js/clearInterval sem))))) +(if (and (exists? js/window) (.-requestIdleCallback js/window)) + (do + (def ^:private request-idle-callback #(js/requestIdleCallback %)) + (def ^:private cancel-idle-callback #(js/cancelIdleCallback %))) + (do + (def ^:private request-idle-callback #(js/setTimeout % 100)) + (def ^:private cancel-idle-callback #(js/cancelTimeout %)))) + (defn schedule-on-idle [func] - (let [sem (js/requestIdleCallback #(func))] + (let [sem (request-idle-callback #(func))] (reify rx/IDisposable (-dispose [_] - (js/cancelIdleCallback sem))))) + (cancel-idle-callback sem))))) + +(def ^:private request-animation-frame + (or (and (exists? js/window) (.-requestAnimationFrame js/window)) + #(js/setTimeout % 16))) (defn raf [f] - (js/window.requestAnimationFrame f)) + (request-animation-frame f)) (defn idle-then-raf [f] From 08589889fd58ce5ad38212b1dae84bf7ecd11cb0 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 18 Nov 2020 13:36:37 +0100 Subject: [PATCH 020/195] :sparkles: Layout changes --- .../ui/workspace/sidebar/options/text.cljs | 134 +++++++++--------- .../workspace/sidebar/options/typography.cljs | 51 ++++--- 2 files changed, 93 insertions(+), 92 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs index cde0071edc..25644aee75 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs @@ -62,7 +62,7 @@ (on-change {:text-align new-align}))] ;; --- Align - [:div.row-flex.align-icons + [:div.align-icons [:span.tooltip.tooltip-bottom {:alt (t locale "workspace.options.text-options.align-left") :class (dom/classnames :current (= "left" text-align)) @@ -85,58 +85,55 @@ i/text-align-justify]])) -(mf/defc additional-options +(mf/defc vertical-align [{:keys [shapes editor ids values locale on-change] :as props}] (let [{:keys [vertical-align]} values - - to-single-value (fn [coll] (if (> (count coll) 1) nil (first coll))) - - grow-type (->> shapes (map :grow-type) (remove nil?) (into #{}) to-single-value) - vertical-align (or vertical-align "top") - - handle-change-grow - (fn [event grow-type] - (st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type)))) - handle-change (fn [event new-align] (on-change {:vertical-align new-align}))] - [:div.row-flex - [:div.align-icons - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.align-top") - :class (dom/classnames :current (= "top" vertical-align)) - :on-click #(handle-change % "top")} - i/align-top] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.align-middle") - :class (dom/classnames :current (= "center" vertical-align)) - :on-click #(handle-change % "center")} - i/align-middle] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.align-bottom") - :class (dom/classnames :current (= "bottom" vertical-align)) - :on-click #(handle-change % "bottom")} - i/align-bottom]] + [:div.align-icons + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.align-top") + :class (dom/classnames :current (= "top" vertical-align)) + :on-click #(handle-change % "top")} + i/align-top] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.align-middle") + :class (dom/classnames :current (= "center" vertical-align)) + :on-click #(handle-change % "center")} + i/align-middle] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.align-bottom") + :class (dom/classnames :current (= "bottom" vertical-align)) + :on-click #(handle-change % "bottom")} + i/align-bottom]])) - [:div.align-icons - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.grow-fixed") - :class (dom/classnames :current (= :fixed grow-type)) - :on-click #(handle-change-grow % :fixed)} - i/auto-fix] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.grow-auto-width") - :class (dom/classnames :current (= :auto-width grow-type)) - :on-click #(handle-change-grow % :auto-width)} - i/auto-width] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.grow-auto-height") - :class (dom/classnames :current (= :auto-height grow-type)) - :on-click #(handle-change-grow % :auto-height)} - i/auto-height]]])) +(mf/defc grow-options + [{:keys [shapes editor ids values locale on-change] :as props}] + (let [to-single-value (fn [coll] (if (> (count coll) 1) nil (first coll))) + grow-type (->> shapes (map :grow-type) (remove nil?) (into #{}) to-single-value) + handle-change-grow + (fn [event grow-type] + (st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type))))] + + [:div.align-icons + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.grow-fixed") + :class (dom/classnames :current (= :fixed grow-type)) + :on-click #(handle-change-grow % :fixed)} + i/auto-fix] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.grow-auto-width") + :class (dom/classnames :current (= :auto-width grow-type)) + :on-click #(handle-change-grow % :auto-width)} + i/auto-width] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.grow-auto-height") + :class (dom/classnames :current (= :auto-height grow-type)) + :on-click #(handle-change-grow % :auto-height)} + i/auto-height]])) (mf/defc text-decoration-options [{:keys [editor ids values locale on-change] :as props}] @@ -147,26 +144,24 @@ handle-change (fn [event type] (on-change {:text-decoration type}))] - [:div.row-flex - [:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")] - [:div.align-icons - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.none") - :class (dom/classnames :current (= "none" text-decoration)) - :on-click #(handle-change % "none")} - i/minus] + [:div.align-icons + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.none") + :class (dom/classnames :current (= "none" text-decoration)) + :on-click #(handle-change % "none")} + i/minus] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.underline") - :class (dom/classnames :current (= "underline" text-decoration)) - :on-click #(handle-change % "underline")} - i/underline] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.underline") + :class (dom/classnames :current (= "underline" text-decoration)) + :on-click #(handle-change % "underline")} + i/underline] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.strikethrough") - :class (dom/classnames :current (= "line-through" text-decoration)) - :on-click #(handle-change % "line-through")} - i/strikethrough]]])) + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.strikethrough") + :class (dom/classnames :current (= "line-through" text-decoration)) + :on-click #(handle-change % "line-through")} + i/strikethrough]])) (defn generate-typography-name [{:keys [font-id font-variant-id] :as typography}] (let [{:keys [name]} (fonts/get-font-data font-id)] @@ -273,9 +268,16 @@ [:> typography-options opts]) [:div.element-set-content - [:> text-align-options opts] - [:> additional-options opts] - [:> text-decoration-options opts]]])) + + [:div.row-flex + [:> text-align-options opts] + [:> vertical-align opts]] + + [:div.row-flex + [:> grow-options opts] + [:> text-decoration-options opts]] + + ]])) (mf/defc options [{:keys [shape] :as props}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs index 08f83a2c9f..b7a9b8200b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs @@ -135,7 +135,7 @@ (let [new-spacing (dom/get-target-val event)] (on-change {attr new-spacing})))] - [:div.row-flex + [:div.spacing-options [:div.input-icon [:span.icon-before.tooltip.tooltip-bottom {:alt (t locale "workspace.options.text-options.line-height")} @@ -171,29 +171,27 @@ handle-change (fn [event type] (on-change {:text-transform type}))] - [:div.row-flex - [:span.element-set-subtitle (t locale "workspace.options.text-options.text-case")] - [:div.align-icons - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.none") - :class (dom/classnames :current (= "none" text-transform)) - :on-click #(handle-change % "none")} - i/minus] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.uppercase") - :class (dom/classnames :current (= "uppercase" text-transform)) - :on-click #(handle-change % "uppercase")} - i/uppercase] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.lowercase") - :class (dom/classnames :current (= "lowercase" text-transform)) - :on-click #(handle-change % "lowercase")} - i/lowercase] - [:span.tooltip.tooltip-bottom - {:alt (t locale "workspace.options.text-options.titlecase") - :class (dom/classnames :current (= "capitalize" text-transform)) - :on-click #(handle-change % "capitalize")} - i/titlecase]]])) + [:div.align-icons + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.none") + :class (dom/classnames :current (= "none" text-transform)) + :on-click #(handle-change % "none")} + i/minus] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.uppercase") + :class (dom/classnames :current (= "uppercase" text-transform)) + :on-click #(handle-change % "uppercase")} + i/uppercase] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.lowercase") + :class (dom/classnames :current (= "lowercase" text-transform)) + :on-click #(handle-change % "lowercase")} + i/lowercase] + [:span.tooltip.tooltip-bottom + {:alt (t locale "workspace.options.text-options.titlecase") + :class (dom/classnames :current (= "capitalize" text-transform)) + :on-click #(handle-change % "capitalize")} + i/titlecase]])) (mf/defc typography-options [{:keys [ids editor values on-change]}] @@ -206,8 +204,9 @@ [:div.element-set-content [:> font-options opts] - [:> spacing-options opts] - [:> text-transform-options opts]])) + [:div.row-flex + [:> spacing-options opts] + [:> text-transform-options opts]]])) (mf/defc typography-entry From a22ec43cf2d3d4d25314afd6806c404afe2f1edf Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Wed, 18 Nov 2020 15:25:03 +0100 Subject: [PATCH 021/195] :tada: Text design new layout --- .../partials/sidebar-element-options.scss | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index 3c47a77c55..c9a5015861 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -518,16 +518,15 @@ } .align-icons { - border: 1px solid $color-gray-60; - border-radius: $br-small; cursor: pointer; display: flex; flex: 1; - justify-content: space-between; - margin-left: $small; - padding: $small; + justify-content: flex-end; + margin: $small 0 $small $small; + padding: 0 $x-small; &:first-child { + justify-content: space-between; margin-left: 0; } @@ -542,8 +541,8 @@ svg { fill: $color-gray-30; - height: 15px; - width: 15px; + height: 14px; + width: 14px; } &:hover, @@ -651,12 +650,12 @@ display: flex; height: 18px; position: relative; - width: 18px; + width: 14px; svg { fill: $color-gray-30; - height: 16px; - width: 16px; + height: 14px; + width: 14px; } } } @@ -927,6 +926,10 @@ } } +.spacing-options { + display: flex; +} + .asset-group { .typography-entry { margin: 0.25rem 0; From ceed926274d6fd0426824e7232fe60e64c255b17 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Wed, 18 Nov 2020 15:41:05 +0100 Subject: [PATCH 022/195] :bug: Fix visual bugs --- frontend/resources/styles/common/framework.scss | 7 ++++--- .../main/partials/sidebar-element-options.scss | 8 ++++---- .../ui/workspace/sidebar/options/measures.cljs | 17 +++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/frontend/resources/styles/common/framework.scss b/frontend/resources/styles/common/framework.scss index ec14acfb0e..6c1923b926 100644 --- a/frontend/resources/styles/common/framework.scss +++ b/frontend/resources/styles/common/framework.scss @@ -373,9 +373,10 @@ ul.slider-dots { font-size: $fs12; height: 20px; position: absolute; - right: 3px; + right: $small; + text-align: right; top: 26%; - width: 20px; + width: 18px; } .after { @@ -539,7 +540,7 @@ input.element-name { @extend .input-text; background-image: url("/images/icons/arrow-down-white.svg"); background-repeat: no-repeat; - background-position: 95% 48%; + background-position: calc(100% - 4px) 48%; background-size: 10px; cursor: pointer; diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index c9a5015861..4465ef2c35 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -226,17 +226,17 @@ .element-set-subtitle { color: $color-gray-20; font-size: $fs11; - width: 12rem; + width: 64px; } .lock-size { cursor: pointer; - width: 20%; + margin: auto; svg { fill: $color-gray-20; - height: 15px; - width: 15px; + height: 14px; + width: 14px; &:hover { fill: $color-primary; diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index fae050ac3e..f76fa2ee08 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -114,13 +114,6 @@ (when (options :size) [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.size")] - [:div.lock-size {:class (classnames - :selected (true? proportion-lock) - :disabled (= proportion-lock :multiple)) - :on-click on-proportion-lock-change} - (if proportion-lock - i/lock - i/unlock)] [:div.input-element.width [:input.input-text {:type "number" :min "0" @@ -138,7 +131,15 @@ :placeholder "--" :on-click select-all :on-change on-height-change - :value (attr->string :height values)}]]]) + :value (attr->string :height values)}]] + + [:div.lock-size {:class (classnames + :selected (true? proportion-lock) + :disabled (= proportion-lock :multiple)) + :on-click on-proportion-lock-change} + (if proportion-lock + i/lock + i/unlock)]]) ;; POSITION (when (options :position) From 64a6ba194905465a459f186b1be8384f23c62f35 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 18 Nov 2020 17:36:14 +0100 Subject: [PATCH 023/195] :tada: Add comments to viewer. --- backend/src/app/services/queries/files.clj | 2 + backend/src/app/services/queries/viewer.clj | 3 + common/app/common/spec.cljc | 1 + frontend/resources/locales.json | 19 +- .../styles/main/partials/dropdown.scss | 31 +- .../styles/main/partials/viewer-header.scss | 82 +-- .../styles/main/partials/viewer.scss | 5 +- .../main/partials/workspace-comments.scss | 33 +- frontend/src/app/main.cljs | 17 +- frontend/src/app/main/data/comments.cljs | 300 +++++++++++ frontend/src/app/main/data/viewer.cljs | 144 ++++-- frontend/src/app/main/data/workspace.cljs | 2 + .../src/app/main/data/workspace/comments.cljs | 254 +--------- .../app/main/data/workspace/persistence.cljs | 10 +- frontend/src/app/main/refs.cljs | 4 + frontend/src/app/main/repo.cljs | 5 +- frontend/src/app/main/ui.cljs | 177 ++++--- frontend/src/app/main/ui/comments.cljs | 340 +++++++++++++ .../app/main/ui/components/fullscreen.cljs | 57 +++ frontend/src/app/main/ui/context.cljs | 1 + .../src/app/main/ui/{viewer => }/handoff.cljs | 108 ++-- .../ui/{viewer => }/handoff/attributes.cljs | 18 +- .../{viewer => }/handoff/attributes/blur.cljs | 2 +- .../handoff/attributes/common.cljs | 2 +- .../{viewer => }/handoff/attributes/fill.cljs | 4 +- .../handoff/attributes/image.cljs | 2 +- .../handoff/attributes/layout.cljs | 4 +- .../handoff/attributes/shadow.cljs | 4 +- .../handoff/attributes/stroke.cljs | 4 +- .../{viewer => }/handoff/attributes/text.cljs | 4 +- .../main/ui/{viewer => }/handoff/code.cljs | 2 +- .../main/ui/{viewer => }/handoff/exports.cljs | 8 +- .../ui/{viewer => }/handoff/left_sidebar.cljs | 14 +- .../main/ui/{viewer => }/handoff/render.cljs | 4 +- .../{viewer => }/handoff/right_sidebar.cljs | 6 +- .../handoff/selection_feedback.cljs | 2 +- frontend/src/app/main/ui/hooks.cljs | 17 - frontend/src/app/main/ui/viewer.cljs | 261 ++++++++-- frontend/src/app/main/ui/viewer/header.cljs | 215 +++++--- .../src/app/main/ui/viewer/thumbnails.cljs | 3 +- .../src/app/main/ui/workspace/comments.cljs | 466 +++--------------- frontend/src/app/util/avatars.cljs | 6 + frontend/src/app/util/dom.cljs | 32 +- frontend/src/app/util/object.cljs | 4 + frontend/src/app/util/webapi.cljs | 24 +- 45 files changed, 1629 insertions(+), 1074 deletions(-) create mode 100644 frontend/src/app/main/data/comments.cljs create mode 100644 frontend/src/app/main/ui/comments.cljs create mode 100644 frontend/src/app/main/ui/components/fullscreen.cljs rename frontend/src/app/main/ui/{viewer => }/handoff.cljs (55%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes.cljs (74%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/blur.cljs (96%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/common.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/fill.cljs (94%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/image.cljs (97%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/layout.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/shadow.cljs (95%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/stroke.cljs (95%) rename frontend/src/app/main/ui/{viewer => }/handoff/attributes/text.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/code.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/exports.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/left_sidebar.cljs (96%) rename frontend/src/app/main/ui/{viewer => }/handoff/render.cljs (98%) rename frontend/src/app/main/ui/{viewer => }/handoff/right_sidebar.cljs (94%) rename frontend/src/app/main/ui/{viewer => }/handoff/selection_feedback.cljs (98%) diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index 8fa7106ec0..c83d4a80ec 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -203,6 +203,8 @@ (defn retrieve-file-users [conn id] (->> (db/exec! conn [sql:file-users id id]) + ;; TODO: seems like the frontend is no longer uses :photo-uri, + ;; so this can be removed probably. (mapv #(media/resolve-media-uris % [:photo :photo-uri])))) (s/def ::file-users diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index 172654e8b6..0174f5b12d 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -50,8 +50,11 @@ file (merge (dissoc file :data) (select-keys (:data file) [:colors :media :typographies])) libs (files/retrieve-file-libraries conn false file-id) + users (files/retrieve-file-users conn file-id) + bundle {:file file :page page + :users users :project project :libraries libs}] (if (string? token) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index b9ab80199b..4223c93f37 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -119,6 +119,7 @@ (s/def ::url string?) (s/def ::fn fn?) (s/def ::point gpt/point?) +(s/def ::id ::uuid) ;; --- Macros diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 844251b9c9..0c1951a894 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -1608,28 +1608,19 @@ "modals.delete-comment-thread.accept" : { "used-in" : [ "src/app/main/ui/workspace/comments.cljs:236" ], "translations" : { - "en" : null, - "fr" : null, - "ru" : null, - "es" : null + "en" : "Delete conversation" } }, "modals.delete-comment-thread.message" : { "used-in" : [ "src/app/main/ui/workspace/comments.cljs:235" ], "translations" : { - "en" : null, - "fr" : null, - "ru" : null, - "es" : null + "en" : "Are you sure you want to delete this conversation? All comments in this thread will be deleted." } }, "modals.delete-comment-thread.title" : { "used-in" : [ "src/app/main/ui/workspace/comments.cljs:234" ], "translations" : { - "en" : null, - "fr" : null, - "ru" : null, - "es" : null + "en" : "Delete conversation" } }, "modals.delete-file-confirm.accept" : { @@ -1881,6 +1872,10 @@ "es" : "No se encuentra el tablero." } }, + "labels.show-all-comments": "Show all comments", + "labels.show-your-comments": "Show only yours comments", + "labels.hide-resolved-comments": "Hide resolved comments", + "viewer.header.dont-show-interactions" : { "used-in" : [ "src/app/main/ui/viewer/header.cljs:68" ], "translations" : { diff --git a/frontend/resources/styles/main/partials/dropdown.scss b/frontend/resources/styles/main/partials/dropdown.scss index 496cc78fdb..0802e04d2e 100644 --- a/frontend/resources/styles/main/partials/dropdown.scss +++ b/frontend/resources/styles/main/partials/dropdown.scss @@ -11,7 +11,7 @@ border-color: $color-gray-10; } - li { + > li { display: flex; align-items: center; color: $color-gray-60; @@ -20,6 +20,12 @@ height: 40px; padding: 5px 16px; + svg { + fill: $color-gray-20; + height: 12px; + width: 12px; + } + &.title { font-weight: 600; cursor: default; @@ -29,4 +35,27 @@ background-color: $color-primary-lighter; } } + + + &.with-check { + > li { + padding: 5px 10px; + } + + > li:not(.selected) { + svg { display: none; } + } + + svg { + fill: $color-gray-50; + } + + .icon { + display: flex; + align-items: center; + width: 25px; + height: 25px; + margin-right: 7px; + } + } } diff --git a/frontend/resources/styles/main/partials/viewer-header.scss b/frontend/resources/styles/main/partials/viewer-header.scss index 4648e1c099..1edb9a0acf 100644 --- a/frontend/resources/styles/main/partials/viewer-header.scss +++ b/frontend/resources/styles/main/partials/viewer-header.scss @@ -42,28 +42,31 @@ } } - .header-icon { - align-items: center; - cursor: pointer; - display: flex; - justify-content: center; - - a { - height: 16px; - width: 16px; - - svg { - fill: $color-gray-30; - height: 16px; - width: 16px; - } + .view-options { + .icon { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; &:hover { - svg { + > svg { fill: $color-primary; } } } + + svg { + fill: $color-gray-30; + height: 16px; + width: 16px; + } + + .dropdown { + top: 40px; + left: 0px; + width: 260px; + } } .sitemap-zone { @@ -92,12 +95,10 @@ } } - .dropdown-button { - svg { - fill: $color-white; - height: 10px; - width: 10px; - } + .show-thumbnails-button svg { + fill: $color-white; + height: 10px; + width: 10px; } .page-name { @@ -243,42 +244,9 @@ } - .custom-select-dropdown { - position: absolute; - left: 0; - z-index: 12; - max-height: 31rem; - min-width: 7rem; - overflow-y: auto; - - background-color: $color-white; - border-radius: $br-small; - box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25); - - li { - color: $color-gray-60; - cursor: pointer; - font-size: $fs14; - display: flex; - padding: $small $medium $small 25px; - - &.selected { - background-image: url(/images/icons/tick.svg); - background-repeat: no-repeat; - background-position: 5% 48%; - background-size: 10px; - font-weight: bold; - } - - &:hover { - background-color: $color-primary-lighter; - } - } - } - .zoom-dropdown { - left : 116px; - top: 45px; + left: 180px; + top: 40px; } .users-zone { diff --git a/frontend/resources/styles/main/partials/viewer.scss b/frontend/resources/styles/main/partials/viewer.scss index 5ac5b76111..346db1c83c 100644 --- a/frontend/resources/styles/main/partials/viewer.scss +++ b/frontend/resources/styles/main/partials/viewer.scss @@ -7,19 +7,18 @@ } .viewer-preview { - height: 100vh; + height: calc(100vh - 40px); grid-row: 1 / span 2; grid-column: 1 / span 1; - overflow: scroll; + overflow: auto; display: flex; justify-content: center; align-items: center; flex-flow: wrap; - .empty-state { justify-content: center; align-items: center; diff --git a/frontend/resources/styles/main/partials/workspace-comments.scss b/frontend/resources/styles/main/partials/workspace-comments.scss index 6c51747747..1f425ae718 100644 --- a/frontend/resources/styles/main/partials/workspace-comments.scss +++ b/frontend/resources/styles/main/partials/workspace-comments.scss @@ -1,14 +1,29 @@ -.workspace-comments { +.viewer-comments { width: 100%; height: 100%; - grid-column: 1/span 2; - grid-row: 1/span 2; z-index: 1000; - pointer-events: none; - overflow: hidden; + position: absolute; + top: 0px; + left: 0px; +} - .threads { - position: relative; +.viewer-comments, .workspace-comments { + + .comments-layer { + + width: 100%; + height: 100%; + grid-column: 1/span 2; + grid-row: 1/span 2; + z-index: 1000; + pointer-events: none; + overflow: hidden; + + .threads { + position: absolute; + top: 0px; + left: 0px; + } } .thread-bubble { @@ -104,8 +119,6 @@ } } - - .comment-container { position: relative; } @@ -132,7 +145,7 @@ font-size: $fs13; @include text-ellipsis; - width: 110px; + width: 150px; } .timeago { diff --git a/frontend/src/app/main.cljs b/frontend/src/app/main.cljs index 70053ffc4b..787c60de34 100644 --- a/frontend/src/app/main.cljs +++ b/frontend/src/app/main.cljs @@ -10,6 +10,7 @@ (ns app.main (:require [app.common.uuid :as uuid] + [app.common.spec :as us] [app.main.data.auth :refer [logout]] [app.main.data.users :as udu] [app.main.store :as st] @@ -35,12 +36,26 @@ (declare reinit) +(s/def ::any any?) + +(defn match-path + [router path] + (when-let [match (rt/match router path)] + (if-let [conform (get-in match [:data :conform])] + (let [spath (get conform :path-params ::any) + squery (get conform :query-params ::any)] + (-> (dissoc match :params) + (assoc :path-params (us/conform spath (get match :path-params)) + :query-params (us/conform squery (get match :query-params))))) + match))) + (defn on-navigate [router path] - (let [match (rt/match router path) + (let [match (match-path router path) profile (:profile storage) authed? (and (not (nil? profile)) (not= (:id profile) uuid/zero))] + (cond (and (or (= path "") (nil? match)) diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs new file mode 100644 index 0000000000..79b5995a9f --- /dev/null +++ b/frontend/src/app/main/data/comments.cljs @@ -0,0 +1,300 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.data.comments + (:require + [cuerdas.core :as str] + [app.common.data :as d] + [app.common.exceptions :as ex] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as geom] + [app.common.math :as mth] + [app.common.pages :as cp] + [app.common.pages-helpers :as cph] + [app.common.spec :as us] + [app.common.uuid :as uuid] + [app.config :as cfg] + [app.main.constants :as c] + [app.main.repo :as rp] + [app.main.store :as st] + [app.main.streams :as ms] + [app.main.worker :as uw] + [app.util.router :as rt] + [app.util.timers :as ts] + [app.util.transit :as t] + [app.util.webapi :as wapi] + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [clojure.set :as set] + [potok.core :as ptk])) + +(s/def ::content ::us/string) +(s/def ::count-comments ::us/integer) +(s/def ::count-unread-comments ::us/integer) +(s/def ::created-at ::us/inst) +(s/def ::file-id ::us/uuid) +(s/def ::modified-at ::us/inst) +(s/def ::owner-id ::us/uuid) +(s/def ::page-id ::us/uuid) +(s/def ::participants (s/every ::us/uuid :kind set?)) +(s/def ::position ::us/point) +(s/def ::seqn ::us/integer) +(s/def ::thread-id ::us/uuid) + +(s/def ::comment-thread + (s/keys :req-un [::us/id + ::page-id + ::file-id + ::seqn + ::content + ::participants + ::count-unread-comments + ::count-comments + ::created-at + ::modified-at + ::owner-id + ::position])) + +(s/def ::comment + (s/keys :req-un [::us/id + ::thread-id + ::owner-id + ::created-at + ::modified-at + ::content])) + +(declare create-draft-thread) +(declare retrieve-comment-threads) +(declare refresh-comment-thread) + +(s/def ::create-thread-params + (s/keys :req-un [::page-id ::file-id ::position ::content])) + +(defn create-thread + [params] + (us/assert ::create-thread-params params) + (letfn [(created [{:keys [id comment] :as thread} state] + (-> state + (update :comment-threads assoc id (dissoc thread :comment)) + (update :comments-local assoc :open id) + (update :comments-local dissoc :draft) + (update :workspace-drawing dissoc :comment) + (update-in [:comments id] assoc (:id comment) comment)))] + + (ptk/reify ::create-thread + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :create-comment-thread params) + (rx/map #(partial created %))))))) + +(defn update-comment-thread-status + [{:keys [id] :as thread}] + (us/assert ::comment-thread thread) + (ptk/reify ::update-comment-thread-status + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:comment-threads id] assoc :count-unread-comments 0)) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :update-comment-thread-status {:id id}) + (rx/ignore))))) + + +(defn update-comment-thread + [{:keys [id is-resolved] :as thread}] + (us/assert ::comment-thread thread) + (ptk/reify ::update-comment-thread + + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:comment-threads id] assoc :is-resolved is-resolved)) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :update-comment-thread {:id id :is-resolved is-resolved}) + (rx/ignore))))) + + +(defn add-comment + [thread content] + (us/assert ::comment-thread thread) + (us/assert ::us/string content) + (letfn [(created [comment state] + (update-in state [:comments (:id thread)] assoc (:id comment) comment))] + (ptk/reify ::create-comment + ptk/WatchEvent + (watch [_ state stream] + (rx/concat + (->> (rp/mutation :add-comment {:thread-id (:id thread) :content content}) + (rx/map #(partial created %))) + (rx/of (refresh-comment-thread thread))))))) + +(defn update-comment + [{:keys [id content thread-id] :as comment}] + (us/assert ::comment comment) + (ptk/reify :update-comment + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:comments thread-id id] assoc :content content)) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :update-comment {:id id :content content}) + (rx/ignore))))) + +(defn delete-comment-thread + [{:keys [id] :as thread}] + (us/assert ::comment-thread thread) + (ptk/reify :delete-comment-thread + ptk/UpdateEvent + (update [_ state] + (-> state + (update :comments dissoc id) + (update :comment-threads dissoc id))) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :delete-comment-thread {:id id}) + (rx/ignore))))) + +(defn delete-comment + [{:keys [id thread-id] :as comment}] + (us/assert ::comment comment) + (ptk/reify :delete-comment + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:comments thread-id] dissoc id)) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/mutation :delete-comment {:id id}) + (rx/ignore))))) + +(defn refresh-comment-thread + [{:keys [id file-id] :as thread}] + (us/assert ::comment-thread thread) + (letfn [(fetched [thread state] + (assoc-in state [:comment-threads id] thread))] + (ptk/reify ::refresh-comment-thread + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comment-thread {:file-id file-id :id id}) + (rx/map #(partial fetched %))))))) + +(defn retrieve-comment-threads + [file-id] + (us/assert ::us/uuid file-id) + (letfn [(fetched [data state] + (assoc state :comment-threads (d/index-by :id data)))] + (ptk/reify ::retrieve-comment-threads + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comment-threads {:file-id file-id}) + (rx/map #(partial fetched %))))))) + +(defn retrieve-comments + [thread-id] + (us/assert ::us/uuid thread-id) + (letfn [(fetched [comments state] + (update state :comments assoc thread-id (d/index-by :id comments)))] + (ptk/reify ::retrieve-comments + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comments {:thread-id thread-id}) + (rx/map #(partial fetched %))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Local State +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn open-thread + [{:keys [id] :as thread}] + (us/assert ::comment-thread thread) + (ptk/reify ::open-thread + ptk/UpdateEvent + (update [_ state] + (-> state + (update :comments-local assoc :open id) + (update :workspace-drawing dissoc :comment))))) + +(defn close-thread + [] + (ptk/reify ::close-thread + ptk/UpdateEvent + (update [_ state] + (-> state + (update :comments-local dissoc :open :draft) + (update :workspace-drawing dissoc :comment))))) + +(defn update-filters + [{:keys [mode show] :as params}] + (ptk/reify ::update-filters + ptk/UpdateEvent + (update [_ state] + (update state :comments-local + (fn [local] + (cond-> local + (some? mode) + (assoc :mode mode) + + (some? show) + (assoc :show show))))))) + +(s/def ::create-draft-params + (s/keys :req-un [::page-id ::file-id ::position])) + +(defn create-draft + [params] + (us/assert ::create-draft-params params) + (ptk/reify ::create-draft + ptk/UpdateEvent + (update [_ state] + (-> state + (update :workspace-drawing assoc :comment params) + (update :comments-local assoc :draft params))))) + +(defn update-draft-thread + [data] + (ptk/reify ::update-draft-thread + ptk/UpdateEvent + (update [_ state] + (-> state + (d/update-in-when [:workspace-drawing :comment] merge data) + (d/update-in-when [:comments-local :draft] merge data))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Helpers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn group-threads-by-page + [threads] + (letfn [(group-by-page [result thread] + (let [current (first result)] + (if (= (:page-id current) (:page-id thread)) + (cons (update current :items conj thread) + (rest result)) + (cons {:page-id (:page-id thread) :items [thread]} + result))))] + (reverse + (reduce group-by-page nil threads)))) + +(defn apply-filters + [cstate profile threads] + (let [{:keys [show mode open]} cstate] + (cond->> threads + (= :pending show) + (filter (fn [item] + (or (not (:is-resolved item)) + (= (:id item) open)))) + + (= :yours mode) + (filter #(contains? (:participants %) (:id profile)))))) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index b40917be69..3aa7058f50 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -23,7 +23,7 @@ [app.common.uuid :as uuid] [app.common.pages-helpers :as cph])) -;; --- Specs +;; --- General Specs (s/def ::id ::us/uuid) (s/def ::name ::us/string) @@ -32,40 +32,63 @@ (s/def ::file (s/keys :req-un [::id ::name])) (s/def ::page ::cp/page) -(s/def ::interactions-mode #{:hide :show :show-on-click}) - (s/def ::bundle (s/keys :req-un [::project ::file ::page])) -;; --- Initialization +;; --- Local State Initialization +(def ^:private + default-local-state + {:zoom 1 + :interactions-mode :hide + :interactions-show? false + :comments-mode :all + :comments-show :unresolved + :selected #{} + :collapsed #{} + :hover nil}) + +(declare fetch-comment-threads) (declare fetch-bundle) (declare bundle-fetched) +(s/def ::page-id ::us/uuid) +(s/def ::file-id ::us/uuid) +(s/def ::index ::us/integer) +(s/def ::token (s/nilable ::us/string)) +(s/def ::section ::us/string) + +(s/def ::initialize-params + (s/keys :req-un [::page-id ::file-id] + :opt-in [::token])) + (defn initialize - [{:keys [page-id file-id] :as params}] + [{:keys [page-id file-id token] :as params}] + (us/assert ::initialize-params params) (ptk/reify ::initialize ptk/UpdateEvent (update [_ state] - (assoc state :viewer-local {:zoom 1 - :page-id page-id - :file-id file-id - :interactions-mode :hide - :show-interactions? false - - :selected #{} - :collapsed #{} - :hover nil})) + (update state :viewer-local + (fn [lstate] + (if (nil? lstate) + default-local-state + lstate)))) ptk/WatchEvent (watch [_ state stream] - (rx/of (fetch-bundle params))))) + (rx/of (fetch-bundle params) + (fetch-comment-threads params))))) ;; --- Data Fetching +(s/def ::fetch-bundle-params + (s/keys :req-un [::page-id ::file-id] + :opt-in [::token])) + (defn fetch-bundle - [{:keys [page-id file-id token]}] + [{:keys [page-id file-id token] :as params}] + (us/assert ::fetch-bundle-params params) (ptk/reify ::fetch-file ptk/WatchEvent (watch [_ state stream] @@ -76,6 +99,40 @@ (rx/first) (rx/map bundle-fetched)))))) +(defn fetch-comment-threads + [{:keys [file-id page-id] :as params}] + (letfn [(fetched [data state] + (->> data + (filter #(= page-id (:page-id %))) + (d/index-by :id) + (assoc state :comment-threads)))] + (ptk/reify ::fetch-comment-threads + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comment-threads {:file-id file-id}) + (rx/map #(partial fetched %))))))) + +(defn refresh-comment-thread + [{:keys [id file-id] :as thread}] + (letfn [(fetched [thread state] + (assoc-in state [:comment-threads id] thread))] + (ptk/reify ::refresh-comment-thread + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comment-thread {:file-id file-id :id id}) + (rx/map #(partial fetched %))))))) + +(defn fetch-comments + [{:keys [thread-id]}] + (us/assert ::us/uuid thread-id) + (letfn [(fetched [comments state] + (update state :comments assoc thread-id (d/index-by :id comments)))] + (ptk/reify ::retrieve-comments + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :comments {:thread-id thread-id}) + (rx/map #(partial fetched %))))))) + (defn- extract-frames [objects] (let [root (get objects uuid/zero)] @@ -86,7 +143,7 @@ (vec)))) (defn bundle-fetched - [{:keys [project file page share-token token libraries] :as bundle}] + [{:keys [project file page share-token token libraries users] :as bundle}] (us/verify ::bundle bundle) (ptk/reify ::file-fetched ptk/UpdateEvent @@ -94,9 +151,10 @@ (let [objects (:objects page) frames (extract-frames objects)] (-> state - (assoc :viewer-libraries (into {} (map #(vector (:id %) %) libraries)) + (assoc :viewer-libraries (d/index-by :id libraries) :viewer-data {:project project :objects objects + :users (d/index-by :id users) :file file :page page :frames frames @@ -176,11 +234,11 @@ (ptk/reify ::select-prev-frame ptk/WatchEvent (watch [_ state stream] - (let [route (:route state) - screen (-> route :data :name keyword) - qparams (get-in route [:params :query]) - pparams (get-in route [:params :path]) - index (d/parse-integer (:index qparams))] + (let [route (:route state) + screen (-> route :data :name keyword) + qparams (:query-params route) + pparams (:path-params route) + index (:index qparams)] (when (pos? index) (rx/of (rt/nav screen pparams (assoc qparams :index (dec index))))))))) @@ -188,15 +246,17 @@ (ptk/reify ::select-prev-frame ptk/WatchEvent (watch [_ state stream] - (let [route (:route state) - screen (-> route :data :name keyword) - qparams (get-in route [:params :query]) - pparams (get-in route [:params :path]) - index (d/parse-integer (:index qparams)) + (let [route (:route state) + screen (-> route :data :name keyword) + qparams (:query-params route) + pparams (:path-params route) + index (:index qparams) total (count (get-in state [:viewer-data :frames]))] (when (< index (dec total)) (rx/of (rt/nav screen pparams (assoc qparams :index (inc index))))))))) +(s/def ::interactions-mode #{:hide :show :show-on-click}) + (defn set-interactions-mode [mode] (us/verify ::interactions-mode mode) @@ -205,7 +265,7 @@ (update [_ state] (-> state (assoc-in [:viewer-local :interactions-mode] mode) - (assoc-in [:viewer-local :show-interactions?] (case mode + (assoc-in [:viewer-local :interactions-show?] (case mode :hide false :show true :show-on-click false)))))) @@ -216,7 +276,7 @@ (ptk/reify ::flash-interactions ptk/UpdateEvent (update [_ state] - (assoc-in state [:viewer-local :show-interactions?] true)) + (assoc-in state [:viewer-local :interactions-show?] true)) ptk/WatchEvent (watch [_ state stream] @@ -229,26 +289,30 @@ (ptk/reify ::flash-done ptk/UpdateEvent (update [_ state] - (assoc-in state [:viewer-local :show-interactions?] false)))) + (assoc-in state [:viewer-local :interactions-show?] false)))) ;; --- Navigation +(defn go-to-frame-by-index + [index] + (ptk/reify ::go-to-frame + ptk/WatchEvent + (watch [_ state stream] + (let [route (:route state) + screen (-> route :data :name keyword) + qparams (:query-params route) + pparams (:path-params route)] + (rx/of (rt/nav screen pparams (assoc qparams :index index))))))) + (defn go-to-frame [frame-id] (us/verify ::us/uuid frame-id) (ptk/reify ::go-to-frame ptk/WatchEvent (watch [_ state stream] - (let [page-id (get-in state [:viewer-local :page-id]) - file-id (get-in state [:viewer-local :file-id]) - frames (get-in state [:viewer-data :frames]) - token (get-in state [:viewer-data :token]) + (let [frames (get-in state [:viewer-data :frames]) index (d/index-of-pred frames #(= (:id %) frame-id))] - (rx/of (rt/nav :viewer - {:page-id page-id - :file-id file-id} - {:token token - :index index})))))) + (rx/of (go-to-frame-by-index index)))))) (defn set-current-frame [frame-id] (ptk/reify ::current-frame diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 24cbc6b989..6daa481ecf 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -144,6 +144,8 @@ ptk/UpdateEvent (update [_ state] (assoc state + :current-file-id file-id + :current-project-id project-id :workspace-presence {})) ptk/WatchEvent diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index b355be375d..ac1d16c053 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -9,59 +9,34 @@ (ns app.main.data.workspace.comments (:require - [cuerdas.core :as str] [app.common.data :as d] [app.common.exceptions :as ex] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.geom.shapes :as geom] [app.common.math :as mth] - [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] - [app.common.uuid :as uuid] - [app.config :as cfg] [app.main.constants :as c] [app.main.data.workspace.common :as dwc] - [app.main.repo :as rp] + [app.main.data.comments :as dcm] [app.main.store :as st] [app.main.streams :as ms] - [app.main.worker :as uw] - [app.util.router :as rt] - [app.util.timers :as ts] - [app.util.transit :as t] - [app.util.webapi :as wapi] [beicon.core :as rx] [cljs.spec.alpha :as s] - [clojure.set :as set] [potok.core :as ptk])) -(s/def ::comment-thread any?) -(s/def ::comment any?) - -(declare create-draft-thread) -(declare retrieve-comment-threads) -(declare refresh-comment-thread) (declare handle-interrupt) (declare handle-comment-layer-click) (defn initialize-comments [file-id] (us/assert ::us/uuid file-id) - (ptk/reify ::start-commenting - ptk/UpdateEvent - (update [_ state] - (update state :workspace-local assoc :commenting true)) - + (ptk/reify ::initialize-comments ptk/WatchEvent (watch [_ state stream] (let [stoper (rx/filter #(= ::finalize %) stream)] (rx/merge - (rx/of (retrieve-comment-threads file-id)) + (rx/of (dcm/retrieve-comment-threads file-id)) (->> stream (rx/filter ms/mouse-click?) (rx/switch-map #(rx/take 1 ms/mouse-position)) - (rx/mapcat #(rx/take 1 ms/mouse-position)) (rx/map handle-comment-layer-click) (rx/take-until stoper)) (->> stream @@ -72,19 +47,13 @@ (defn- handle-interrupt [] (ptk/reify ::handle-interrupt - ptk/UpdateEvent - (update [_ state] - (let [local (:workspace-comments state) - drawing (:workspace-drawing state)] + ptk/WatchEvent + (watch [_ state stream] + (let [local (:comments-local state)] (cond - (:comment drawing) - (update state :workspace-drawing dissoc :comment) - - (:open local) - (update state :workspace-comments dissoc :open) - - :else - (dissoc state :workspace-drawing)))))) + (:draft local) (rx/of (dcm/close-thread)) + (:open local) (rx/of (dcm/close-thread)) + :else (rx/of #(dissoc % :workspace-drawing))))))) ;; Event responsible of the what should be executed when user clicked ;; on the comments layer. An option can be create a new draft thread, @@ -93,215 +62,32 @@ (defn- handle-comment-layer-click [position] (ptk/reify ::handle-comment-layer-click - ptk/UpdateEvent - (update [_ state] - (let [local (:workspace-comments state)] - (if (:open local) - (update state :workspace-comments dissoc :open) - (update state :workspace-drawing assoc - :comment {:position position :content ""})))))) - -(defn create-thread - [data] - (letfn [(created [{:keys [id comment] :as thread} state] - (-> state - (update :comment-threads assoc id (dissoc thread :comment)) - (update :workspace-comments assoc :open id) - (update :workspace-drawing dissoc :comment) - (update-in [:comments id] assoc (:id comment) comment)))] - - (ptk/reify ::create-thread - ptk/WatchEvent - (watch [_ state stream] - (let [file-id (get-in state [:workspace-file :id]) - page-id (:current-page-id state) - params (assoc data - :page-id page-id - :file-id file-id)] - (->> (rp/mutation :create-comment-thread params) - (rx/map #(partial created %)))))))) - -(defn update-comment-thread-status - [{:keys [id] :as thread}] - (us/assert ::comment-thread thread) - (ptk/reify ::update-comment-thread-status - ptk/UpdateEvent - (update [_ state] - (d/update-in-when state [:comment-threads id] assoc :count-unread-comments 0)) - ptk/WatchEvent (watch [_ state stream] - (->> (rp/mutation :update-comment-thread-status {:id id}) - (rx/ignore))))) - - -(defn update-comment-thread - [{:keys [id is-resolved] :as thread}] - (us/assert ::comment-thread thread) - (ptk/reify ::update-comment-thread - - ptk/UpdateEvent - (update [_ state] - (d/update-in-when state [:comment-threads id] assoc :is-resolved is-resolved)) - - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation :update-comment-thread {:id id :is-resolved is-resolved}) - (rx/ignore))))) - - -(defn add-comment - [thread content] - (us/assert ::comment-thread thread) - (us/assert ::us/string content) - (letfn [(created [comment state] - (update-in state [:comments (:id thread)] assoc (:id comment) comment))] - (ptk/reify ::create-comment - ptk/WatchEvent - (watch [_ state stream] - (rx/concat - (->> (rp/mutation :add-comment {:thread-id (:id thread) :content content}) - (rx/map #(partial created %))) - (rx/of (refresh-comment-thread thread))))))) - -(defn update-comment - [{:keys [id content thread-id] :as comment}] - (us/assert ::comment comment) - (ptk/reify :update-comment - ptk/UpdateEvent - (update [_ state] - (d/update-in-when state [:comments thread-id id] assoc :content content)) - - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation :update-comment {:id id :content content}) - (rx/ignore))))) - -(defn delete-comment-thread - [{:keys [id] :as thread}] - (us/assert ::comment-thread thread) - (ptk/reify :delete-comment-thread - ptk/UpdateEvent - (update [_ state] - (-> state - (update :comments dissoc id) - (update :comment-threads dissoc id))) - - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation :delete-comment-thread {:id id}) - (rx/ignore))))) - -(defn delete-comment - [{:keys [id thread-id] :as comment}] - (us/assert ::comment comment) - (ptk/reify :delete-comment - ptk/UpdateEvent - (update [_ state] - (d/update-in-when state [:comments thread-id] dissoc id)) - - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/mutation :delete-comment {:id id}) - (rx/ignore))))) - -(defn refresh-comment-thread - [{:keys [id file-id] :as thread}] - (us/assert ::comment-thread thread) - (letfn [(fetched [thread state] - (assoc-in state [:comment-threads id] thread))] - (ptk/reify ::refresh-comment-thread - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/query :comment-thread {:file-id file-id :id id}) - (rx/map #(partial fetched %))))))) - -(defn retrieve-comment-threads - [file-id] - (us/assert ::us/uuid file-id) - (letfn [(fetched [data state] - (assoc state :comment-threads (d/index-by :id data)))] - (ptk/reify ::retrieve-comment-threads - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/query :comment-threads {:file-id file-id}) - (rx/map #(partial fetched %))))))) - -(defn retrieve-comments - [thread-id] - (us/assert ::us/uuid thread-id) - (letfn [(fetched [comments state] - (update state :comments assoc thread-id (d/index-by :id comments)))] - (ptk/reify ::retrieve-comments - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/query :comments {:thread-id thread-id}) - (rx/map #(partial fetched %))))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Workspace (local) events -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn open-thread - [{:keys [id] :as thread}] - (us/assert ::comment-thread thread) - (ptk/reify ::open-thread - ptk/UpdateEvent - (update [_ state] - (-> state - (update :workspace-comments assoc :open id) - (update :workspace-drawing dissoc :comment))))) - -(defn close-thread - [] - (ptk/reify ::open-thread - ptk/UpdateEvent - (update [_ state] - (-> state - (update :workspace-comments dissoc :open) - (update :workspace-drawing dissoc :comment))))) - -(defn update-draft-thread - [data] - (ptk/reify ::update-draft-thread - ptk/UpdateEvent - (update [_ state] - (update state :workspace-drawing assoc :comment data)))) - -(defn update-filters - [{:keys [main resolved]}] - (ptk/reify ::update-filters - ptk/UpdateEvent - (update [_ state] - (update state :workspace-comments - (fn [local] - (cond-> local - (some? main) - (assoc :filter main) - - (some? resolved) - (assoc :filter-resolved resolved))))))) - + (let [local (:comments-local state)] + (if (some? (:open local)) + (rx/of (dcm/close-thread)) + (let [page-id (:current-page-id state) + file-id (:current-file-id state) + params {:position position + :page-id page-id + :file-id file-id}] + (rx/of (dcm/create-draft params)))))))) (defn center-to-comment-thread [{:keys [id position] :as thread}] - (us/assert ::comment-thread thread) + (us/assert ::dcm/comment-thread thread) (ptk/reify :center-to-comment-thread ptk/UpdateEvent (update [_ state] (update state :workspace-local (fn [{:keys [vbox vport zoom] :as local}] - ;; (prn "position=" position) - ;; (prn "vbox=" vbox) - ;; (prn "vport=" vport) (let [pw (/ 50 zoom) ph (/ 200 zoom) nw (mth/round (- (/ (:width vbox) 2) pw)) nh (mth/round (- (/ (:height vbox) 2) ph)) nx (- (:x position) nw) ny (- (:y position) nh)] - (update local :vbox assoc :x nx :y ny)))) - - ))) + (update local :vbox assoc :x nx :y ny))))))) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index a35c0ae67b..ec38272231 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -37,8 +37,6 @@ ;; --- Persistence - - (defn initialize-file-persistence [file-id] (ptk/reify ::initialize-persistence @@ -225,12 +223,6 @@ :else (throw error)))))))) -(defn assoc-profile-avatar - [{:keys [photo fullname] :as profile}] - (cond-> profile - (or (nil? photo) (empty? photo)) - (assoc :photo (avatars/generate {:name fullname})))) - (defn- bundle-fetched [file users project libraries] (ptk/reify ::bundle-fetched @@ -243,7 +235,7 @@ ptk/UpdateEvent (update [_ state] - (let [users (map assoc-profile-avatar users)] + (let [users (map avatars/assoc-profile-avatar users)] (assoc state :workspace-undo {} :workspace-project project diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index fd3a2c2cd4..37d5b72006 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -207,3 +207,7 @@ (def viewer-local (l/derived :viewer-local st/state)) + +(def comments-local + (l/derived :comments-local st/state)) + diff --git a/frontend/src/app/main/repo.cljs b/frontend/src/app/main/repo.cljs index 823d1d3734..9221f9ad4f 100644 --- a/frontend/src/app/main/repo.cljs +++ b/frontend/src/app/main/repo.cljs @@ -31,11 +31,14 @@ (rx/throw {:type :authorization :code :not-authorized}) + (= (:status response) 404) + (rx/throw (:body response)) + (= 0 (:status response)) (rx/throw {:type :offline}) :else - (rx/throw {:type :internal-error + (rx/throw {:type :server-error :status (:status response) :body (:body response)}))) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index e81e7801ca..fa0ae92d32 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -13,6 +13,7 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.uuid :as uuid] + [app.common.spec :as us] [app.main.data.auth :refer [logout]] [app.main.data.messages :as dm] [app.main.refs :as refs] @@ -20,6 +21,7 @@ [app.main.ui.auth :refer [auth]] [app.main.ui.auth.verify-token :refer [verify-token]] [app.main.ui.cursors :as c] + [app.main.ui.context :as ctx] [app.main.ui.dashboard :refer [dashboard]] [app.main.ui.icons :as i] [app.main.ui.messages :as msgs] @@ -27,7 +29,7 @@ [app.main.ui.settings :as settings] [app.main.ui.static :refer [not-found-page not-authorized-page]] [app.main.ui.viewer :refer [viewer-page]] - [app.main.ui.viewer.handoff :refer [handoff]] + [app.main.ui.handoff :refer [handoff]] [app.main.ui.workspace :as workspace] [app.util.i18n :as i18n :refer [tr t]] [app.util.timers :as ts] @@ -39,6 +41,19 @@ ;; --- Routes +(s/def ::page-id ::us/uuid) +(s/def ::file-id ::us/uuid) +(s/def ::viewer-path-params + (s/keys :req-un [::file-id ::page-id])) + +(s/def ::section ::us/keyword) +(s/def ::index ::us/integer) +(s/def ::token (s/nilable ::us/string)) + +(s/def ::viewer-query-params + (s/keys :req-un [::index] + :opt-un [::token ::section])) + (def routes [["/auth" ["/login" :auth-login] @@ -53,8 +68,17 @@ ["/password" :settings-password] ["/options" :settings-options]] - ["/view/:file-id/:page-id" :viewer] - ["/handoff/:file-id/:page-id" :handoff] + ["/view/:file-id/:page-id" + {:name :viewer + :conform + {:path-params ::viewer-path-params + :query-params ::viewer-query-params}}] + + ["/handoff/:file-id/:page-id" + {:name :handoff + :conform {:path-params ::viewer-path-params + :query-params ::viewer-query-params}}] + ["/not-found" :not-found] ["/not-authorized" :not-authorized] @@ -86,84 +110,88 @@ (mf/defc app {::mf/wrap [#(mf/catch % {:fallback app-error})]} [{:keys [route] :as props}] - (case (get-in route [:data :name]) - (:auth-login - :auth-register - :auth-goodbye - :auth-recovery-request - :auth-recovery) - [:& auth {:route route}] - :auth-verify-token - [:& verify-token {:route route}] + [:& (mf/provider ctx/current-route) {:value route} + (case (get-in route [:data :name]) + (:auth-login + :auth-register + :auth-goodbye + :auth-recovery-request + :auth-recovery) + [:& auth {:route route}] - (:settings-profile - :settings-password - :settings-options) - [:& settings/settings {:route route}] + :auth-verify-token + [:& verify-token {:route route}] - :debug-icons-preview - (when *assert* - [:div.debug-preview - [:h1 "Cursors"] - [:& c/debug-preview] - [:h1 "Icons"] - [:& i/debug-icons-preview] - ]) + (:settings-profile + :settings-password + :settings-options) + [:& settings/settings {:route route}] - (:dashboard-search - :dashboard-projects - :dashboard-files - :dashboard-libraries - :dashboard-team-members - :dashboard-team-settings) - [:& dashboard {:route route}] + :debug-icons-preview + (when *assert* + [:div.debug-preview + [:h1 "Cursors"] + [:& c/debug-preview] + [:h1 "Icons"] + [:& i/debug-icons-preview] + ]) - :viewer - (let [index (d/parse-integer (get-in route [:params :query :index])) - token (get-in route [:params :query :token]) - file-id (uuid (get-in route [:params :path :file-id])) - page-id (uuid (get-in route [:params :path :page-id]))] - [:& viewer-page {:page-id page-id - :file-id file-id - :index index - :token token}]) + (:dashboard-search + :dashboard-projects + :dashboard-files + :dashboard-libraries + :dashboard-team-members + :dashboard-team-settings) + [:& dashboard {:route route}] - :handoff - (let [index (d/parse-integer (get-in route [:params :query :index])) - file-id (uuid (get-in route [:params :path :file-id])) - page-id (uuid (get-in route [:params :path :page-id]))] - [:& handoff {:page-id page-id - :file-id file-id - :index index}]) + :viewer + (let [index (get-in route [:query-params :index]) + token (get-in route [:query-params :token]) + section (get-in route [:query-params :section] :interactions) + file-id (get-in route [:path-params :file-id]) + page-id (get-in route [:path-params :page-id])] + [:& viewer-page {:page-id page-id + :file-id file-id + :section section + :index index + :token token}]) - :render-object - (do - (let [file-id (uuid (get-in route [:params :path :file-id])) - page-id (uuid (get-in route [:params :path :page-id])) - object-id (uuid (get-in route [:params :path :object-id]))] - [:& render/render-object {:file-id file-id - :page-id page-id - :object-id object-id}])) + :handoff + (let [file-id (get-in route [:path-params :file-id]) + page-id (get-in route [:path-params :page-id]) + index (get-in route [:query-params :index])] + [:& handoff {:page-id page-id + :file-id file-id + :index index}]) - :workspace - (let [project-id (uuid (get-in route [:params :path :project-id])) - file-id (uuid (get-in route [:params :path :file-id])) - page-id (uuid (get-in route [:params :query :page-id])) - layout-name (get-in route [:params :query :layout])] - [:& workspace/workspace {:project-id project-id - :file-id file-id - :page-id page-id - :layout-name (keyword layout-name) - :key file-id}]) + :render-object + (do + (let [file-id (uuid (get-in route [:params :path :file-id])) + page-id (uuid (get-in route [:params :path :page-id])) + object-id (uuid (get-in route [:params :path :object-id]))] + [:& render/render-object {:file-id file-id + :page-id page-id + :object-id object-id}])) - :not-authorized - [:& not-authorized-page] + :workspace + (let [project-id (uuid (get-in route [:params :path :project-id])) + file-id (uuid (get-in route [:params :path :file-id])) + page-id (uuid (get-in route [:params :query :page-id])) + layout-name (get-in route [:params :query :layout])] + [:& workspace/workspace {:project-id project-id + :file-id file-id + :page-id page-id + :layout-name (keyword layout-name) + :key file-id}]) - :not-found - [:& not-found-page] + :not-authorized + [:& not-authorized-page] - nil)) + :not-found + [:& not-found-page] + + nil)]) (mf/defc app-wrapper [] @@ -229,7 +257,7 @@ :type :error :timeout 5000})))))) -(defmethod ptk/handle-error :internal-error +(defmethod ptk/handle-error :server-error [{:keys [status] :as error}] (cond (= status 429) @@ -243,6 +271,13 @@ (st/emitf (dm/show {:content "Unable to connect to backend, wait a little bit and refresh." :type :error}))))) + +(defmethod ptk/handle-error :not-found + [{:keys [status] :as error}] + (ts/schedule + (st/emitf (dm/show {:content "Resource not found." + :type :warning})))) + (defonce uncaught-error-handler (letfn [(on-error [event] (ptk/handle-error (unchecked-get event "error")) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs new file mode 100644 index 0000000000..3cf96c3631 --- /dev/null +++ b/frontend/src/app/main/ui/comments.cljs @@ -0,0 +1,340 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.comments + (:require + [app.config :as cfg] + [app.main.data.comments :as dcm] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.streams :as ms] + [app.main.ui.context :as ctx] + [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.data.modal :as modal] + [app.main.ui.icons :as i] + [app.main.ui.keyboard :as kbd] + [app.util.time :as dt] + [app.util.dom :as dom] + [app.util.object :as obj] + [app.util.i18n :as i18n :refer [t tr]] + [cuerdas.core :as str] + [okulary.core :as l] + [rumext.alpha :as mf])) + +(mf/defc resizing-textarea + {::mf/wrap-props false} + [props] + (let [value (obj/get props "value" "") + on-focus (obj/get props "on-focus") + on-blur (obj/get props "on-blur") + placeholder (obj/get props "placeholder") + on-change (obj/get props "on-change") + on-esc (obj/get props "on-esc") + ref (mf/use-ref) + + on-key-down + (mf/use-callback + (fn [event] + (when (and (kbd/esc? event) + (fn? on-esc)) + (on-esc event)))) + + on-change* + (mf/use-callback + (mf/deps on-change) + (fn [event] + (let [content (dom/get-target-val event)] + (on-change content))))] + + + (mf/use-layout-effect + nil + (fn [] + (let [node (mf/ref-val ref)] + (set! (.-height (.-style node)) "0") + (set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))) + + [:textarea + {:ref ref + :on-key-down on-key-down + :on-focus on-focus + :on-blur on-blur + :value value + :placeholder placeholder + :on-change on-change*}])) + +(mf/defc reply-form + [{:keys [thread] :as props}] + (let [show-buttons? (mf/use-state false) + content (mf/use-state "") + + on-focus + (mf/use-callback + #(reset! show-buttons? true)) + + on-blur + (mf/use-callback + #(reset! show-buttons? false)) + + on-change + (mf/use-callback + #(reset! content %)) + + on-cancel + (mf/use-callback + #(do (reset! content "") + (reset! show-buttons? false))) + + on-submit + (mf/use-callback + (mf/deps thread @content) + (fn [] + (st/emit! (dcm/add-comment thread @content)) + (on-cancel)))] + + [:div.reply-form + [:& resizing-textarea {:value @content + :placeholder "Reply" + :on-blur on-blur + :on-focus on-focus + :on-change on-change}] + (when (or @show-buttons? + (not (empty? @content))) + [:div.buttons + [:input.btn-primary {:type "button" :value "Post" :on-click on-submit}] + [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]])])) + +(mf/defc draft-thread + [{:keys [draft zoom on-cancel on-submit] :as props}] + (let [position (:position draft) + content (:content draft) + pos-x (* (:x position) zoom) + pos-y (* (:y position) zoom) + + on-esc + (mf/use-callback + (mf/deps draft) + (fn [event] + (dom/stop-propagation event) + (if (fn? on-cancel) + (on-cancel) + (st/emit! :interrupt)))) + + on-change + (mf/use-callback + (mf/deps draft) + (fn [content] + (st/emit! (dcm/update-draft-thread {:content content})))) + + on-submit + (mf/use-callback + (mf/deps draft) + (partial on-submit draft))] + + [:* + [:div.thread-bubble + {:style {:top (str pos-y "px") + :left (str pos-x "px")} + :on-click dom/stop-propagation} + [:span "?"]] + [:div.thread-content + {:style {:top (str (- pos-y 14) "px") + :left (str (+ pos-x 14) "px")} + :on-click dom/stop-propagation} + [:div.reply-form + [:& resizing-textarea {:placeholder "Write new comment" + :value (or content "") + :on-esc on-esc + :on-change on-change}] + [:div.buttons + [:input.btn-primary + {:on-click on-submit + :type "button" + :value "Post"}] + [:input.btn-secondary + {:on-click on-esc + :type "button" + :value "Cancel"}]]]]])) + +(mf/defc edit-form + [{:keys [content on-submit on-cancel] :as props}] + (let [content (mf/use-state content) + + on-change + (mf/use-callback + #(reset! content %)) + + on-submit* + (mf/use-callback + (mf/deps @content) + (fn [] (on-submit @content)))] + + [:div.reply-form.edit-form + [:& resizing-textarea {:value @content + :on-change on-change}] + [:div.buttons + [:input.btn-primary {:type "button" :value "Post" :on-click on-submit*}] + [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]]])) + +(mf/defc comment-item + [{:keys [comment thread users] :as props}] + (let [profile (get (or users @refs/workspace-users) (:owner-id comment)) + options (mf/use-state false) + edition? (mf/use-state false) + + on-show-options + (mf/use-callback #(reset! options true)) + + on-hide-options + (mf/use-callback #(reset! options false)) + + on-edit-clicked + (mf/use-callback + (fn [] + (reset! options false) + (reset! edition? true))) + + on-delete-comment + (mf/use-callback + (mf/deps comment) + (st/emitf (dcm/delete-comment comment))) + + delete-thread + (mf/use-callback + (mf/deps thread) + (st/emitf (dcm/close-thread) + (dcm/delete-comment-thread thread))) + + + on-delete-thread + (mf/use-callback + (mf/deps thread) + (st/emitf (modal/show + {:type :confirm + :title (tr "modals.delete-comment-thread.title") + :message (tr "modals.delete-comment-thread.message") + :accept-label (tr "modals.delete-comment-thread.accept") + :on-accept delete-thread}))) + + on-submit + (mf/use-callback + (mf/deps comment thread) + (fn [content] + (reset! edition? false) + (st/emit! (dcm/update-comment (assoc comment :content content))))) + + on-cancel + (mf/use-callback #(reset! edition? false)) + + toggle-resolved + (mf/use-callback + (mf/deps thread) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))] + + [:div.comment-container + [:div.comment + [:div.author + [:div.avatar + [:img {:src (cfg/resolve-media-path (:photo profile))}]] + [:div.name + [:div.fullname (:fullname profile)] + [:div.timeago (dt/timeago (:modified-at comment))]] + + (when (some? thread) + [:div.options-resolve {:on-click toggle-resolved} + (if (:is-resolved thread) + [:span i/checkbox-checked] + [:span i/checkbox-unchecked])]) + + [:div.options + [:div.options-icon {:on-click on-show-options} i/actions]]] + + [:div.content + (if @edition? + [:& edit-form {:content (:content comment) + :on-submit on-submit + :on-cancel on-cancel}] + [:span.text (:content comment)])]] + + [:& dropdown {:show @options + :on-close on-hide-options} + [:ul.dropdown.comment-options-dropdown + [:li {:on-click on-edit-clicked} "Edit"] + (if thread + [:li {:on-click on-delete-thread} "Delete thread"] + [:li {:on-click on-delete-comment} "Delete comment"])]]])) + +(defn comments-ref + [{:keys [id] :as thread}] + (l/derived (l/in [:comments id]) st/state)) + +(mf/defc thread-comments + [{:keys [thread zoom users]}] + (let [ref (mf/use-ref) + pos (:position thread) + pos-x (+ (* (:x pos) zoom) 14) + pos-y (- (* (:y pos) zoom) 14) + + comments-ref (mf/use-memo (mf/deps thread) #(comments-ref thread)) + comments-map (mf/deref comments-ref) + comments (->> (vals comments-map) + (sort-by :created-at)) + comment (first comments)] + + (mf/use-effect + (st/emitf (dcm/update-comment-thread-status thread))) + + (mf/use-effect + (mf/deps thread) + (st/emitf (dcm/retrieve-comments (:id thread)))) + + (mf/use-layout-effect + (mf/deps thread comments-map) + (fn [] + (when-let [node (mf/ref-val ref)] + (.scrollIntoViewIfNeeded ^js node)))) + + [:div.thread-content + {:style {:top (str pos-y "px") + :left (str pos-x "px")} + :on-click dom/stop-propagation} + + [:div.comments + [:& comment-item {:comment comment + :users users + :thread thread}] + (for [item (rest comments)] + [:* + [:hr] + [:& comment-item {:comment item :users users}]]) + [:div {:ref ref}]] + [:& reply-form {:thread thread}]])) + +(mf/defc thread-bubble + {::mf/wrap [mf/memo]} + [{:keys [thread zoom open? on-click] :as params}] + (let [pos (:position thread) + pos-x (* (:x pos) zoom) + pos-y (* (:y pos) zoom) + on-click* (fn [event] + (dom/stop-propagation event) + (on-click thread))] + + [:div.thread-bubble + {:style {:top (str pos-y "px") + :left (str pos-x "px")} + :on-mouse-down (fn [event] + (dom/prevent-default event)) + :class (dom/classnames + :resolved (:is-resolved thread) + :unread (pos? (:count-unread-comments thread))) + :on-click on-click*} + [:span (:seqn thread)]])) diff --git a/frontend/src/app/main/ui/components/fullscreen.cljs b/frontend/src/app/main/ui/components/fullscreen.cljs new file mode 100644 index 0000000000..c7cf120d20 --- /dev/null +++ b/frontend/src/app/main/ui/components/fullscreen.cljs @@ -0,0 +1,57 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.components.fullscreen + (:require + [app.util.dom :as dom] + [app.util.webapi :as wapi] + [beicon.core :as rx] + [rumext.alpha :as mf])) + +(def fullscreen-context + (mf/create-context)) + +(mf/defc fullscreen-wrapper + [{:keys [children] :as props}] + (let [container (mf/use-ref) + state (mf/use-state (dom/fullscreen?)) + + change + (mf/use-callback + (fn [event] + (let [val (dom/fullscreen?)] + (reset! state val)))) + + manager + (mf/use-memo + (mf/deps @state) + (fn [] + (specify! state + cljs.core/IFn + (-invoke + ([it val] + (if val + (wapi/request-fullscreen (mf/ref-val container)) + (wapi/exit-fullscreen)))))))] + + ;; NOTE: the user interaction with F11 keyboard hot-key does not + ;; emits the `fullscreenchange` event; that event is emmited only + ;; when API is used. There are no way to detect the F11 behavior + ;; in a uniform cross browser way. + + (mf/use-effect + (fn [] + (.addEventListener js/document "fullscreenchange" change) + (fn [] + (.removeEventListener js/document "fullscreenchange" change)))) + + [:div.fulllscreen-wrapper {:ref container :class (dom/classnames :fullscreen @state)} + [:& (mf/provider fullscreen-context) {:value manager} + children]])) + diff --git a/frontend/src/app/main/ui/context.cljs b/frontend/src/app/main/ui/context.cljs index 11abc5fdb3..7e063282bf 100644 --- a/frontend/src/app/main/ui/context.cljs +++ b/frontend/src/app/main/ui/context.cljs @@ -14,6 +14,7 @@ (def embed-ctx (mf/create-context false)) (def render-ctx (mf/create-context nil)) +(def current-route (mf/create-context nil)) (def current-team-id (mf/create-context nil)) (def current-project-id (mf/create-context nil)) (def current-page-id (mf/create-context nil)) diff --git a/frontend/src/app/main/ui/viewer/handoff.cljs b/frontend/src/app/main/ui/handoff.cljs similarity index 55% rename from frontend/src/app/main/ui/viewer/handoff.cljs rename to frontend/src/app/main/ui/handoff.cljs index fc06143f4d..f2d2ebb444 100644 --- a/frontend/src/app/main/ui/viewer/handoff.cljs +++ b/frontend/src/app/main/ui/handoff.cljs @@ -7,28 +7,27 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff +(ns app.main.ui.handoff (:require - [rumext.alpha :as mf] - [beicon.core :as rx] - [goog.events :as events] - [okulary.core :as l] [app.common.exceptions :as ex] - [app.util.data :refer [classnames]] - [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [t tr]] [app.main.data.viewer :as dv] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.components.fullscreen :as fs] + [app.main.ui.handoff.left-sidebar :refer [left-sidebar]] + [app.main.ui.handoff.render :refer [render-frame-svg]] + [app.main.ui.handoff.right-sidebar :refer [right-sidebar]] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] [app.main.ui.viewer.header :refer [header]] [app.main.ui.viewer.thumbnails :refer [thumbnails-panel]] - [app.main.ui.viewer.handoff.render :refer [render-frame-svg]] - [app.main.ui.viewer.handoff.left-sidebar :refer [left-sidebar]] - [app.main.ui.viewer.handoff.right-sidebar :refer [right-sidebar]]) + [app.util.dom :as dom] + [app.util.i18n :as i18n :refer [t tr]] + [beicon.core :as rx] + [goog.events :as events] + [okulary.core :as l] + [rumext.alpha :as mf]) (:import goog.events.EventType)) (defn handle-select-frame [frame] @@ -37,7 +36,7 @@ (st/emit! (dv/select-shape (:id frame))))) (mf/defc render-panel - [{:keys [data local index page-id file-id]}] + [{:keys [data state index page-id file-id]}] (let [locale (mf/deref i18n/locale) frames (:frames data []) objects (:objects data) @@ -65,26 +64,23 @@ [:div.handoff-svg-wrapper {:on-click (handle-select-frame frame)} [:div.handoff-svg-container [:& render-frame-svg {:frame-id (:id frame) - :zoom (:zoom local) + :zoom (:zoom state) :objects objects}]]] [:& right-sidebar {:frame frame :page-id page-id :file-id file-id}]])])) (mf/defc handoff-content - [{:keys [data local index page-id file-id] :as props}] - - (let [container (mf/use-ref) - [toggle-fullscreen fullscreen?] (hooks/use-fullscreen container) - - on-mouse-wheel - (fn [event] - (when (kbd/ctrl? event) - (dom/prevent-default event) - (let [event (.getBrowserEvent ^js event)] - (if (pos? (.-deltaY ^js event)) - (st/emit! dv/decrease-zoom) - (st/emit! dv/increase-zoom))))) + [{:keys [data state index page-id file-id] :as props}] + (let [on-mouse-wheel + (mf/use-callback + (fn [event] + (when (kbd/ctrl? event) + (dom/prevent-default event) + (let [event (.getBrowserEvent ^js event)] + (if (pos? (.-deltaY ^js event)) + (st/emit! dv/decrease-zoom) + (st/emit! dv/increase-zoom)))))) on-mount (fn [] @@ -98,37 +94,39 @@ (mf/use-effect on-mount) (hooks/use-shortcuts dv/shortcuts) - [:div.handoff-layout {:class (classnames :fullscreen fullscreen?) - :ref container} - [:& header {:data data - :toggle-fullscreen toggle-fullscreen - :fullscreen? fullscreen? - :local local - :index index - :screen :handoff}] - [:div.viewer-content - (when (:show-thumbnails local) - [:& thumbnails-panel {:index index - :data data - :screen :handoff}]) - [:& render-panel {:data data - :local local - :index index - :page-id page-id - :file-id file-id}]]])) + [:& fs/fullscreen-wrapper {} + [:div.handoff-layout + [:& header + {:data data + :state state + :index index + :section :handoff}] + [:div.viewer-content + (when (:show-thumbnails state) + [:& thumbnails-panel {:index index + :data data + :screen :handoff}]) + [:& render-panel {:data data + :state state + :index index + :page-id page-id + :file-id file-id}]]]])) (mf/defc handoff - [{:keys [file-id page-id index] :as props}] + [{:keys [file-id page-id index token] :as props}] + (mf/use-effect - (mf/deps file-id page-id) + (mf/deps file-id page-id token) (fn [] (st/emit! (dv/initialize props)))) - (let [data (mf/deref refs/viewer-data) - local (mf/deref refs/viewer-local)] - (when data - [:& handoff-content {:file-id file-id - :page-id page-id - :index index - :local local - :data data}]))) + (let [data (mf/deref refs/viewer-data) + state (mf/deref refs/viewer-local)] + + (when (and data state) + [:& handoff-content + {:file-id file-id + :page-id page-id + :index index + :state state + :data data}]))) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes.cljs b/frontend/src/app/main/ui/handoff/attributes.cljs similarity index 74% rename from frontend/src/app/main/ui/viewer/handoff/attributes.cljs rename to frontend/src/app/main/ui/handoff/attributes.cljs index 4b29485eb1..487396f0ae 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes.cljs +++ b/frontend/src/app/main/ui/handoff/attributes.cljs @@ -7,19 +7,19 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes +(ns app.main.ui.handoff.attributes (:require [rumext.alpha :as mf] [app.util.i18n :as i18n] [app.common.geom.shapes :as gsh] - [app.main.ui.viewer.handoff.exports :refer [exports]] - [app.main.ui.viewer.handoff.attributes.layout :refer [layout-panel]] - [app.main.ui.viewer.handoff.attributes.fill :refer [fill-panel]] - [app.main.ui.viewer.handoff.attributes.stroke :refer [stroke-panel]] - [app.main.ui.viewer.handoff.attributes.shadow :refer [shadow-panel]] - [app.main.ui.viewer.handoff.attributes.blur :refer [blur-panel]] - [app.main.ui.viewer.handoff.attributes.image :refer [image-panel]] - [app.main.ui.viewer.handoff.attributes.text :refer [text-panel]])) + [app.main.ui.handoff.exports :refer [exports]] + [app.main.ui.handoff.attributes.layout :refer [layout-panel]] + [app.main.ui.handoff.attributes.fill :refer [fill-panel]] + [app.main.ui.handoff.attributes.stroke :refer [stroke-panel]] + [app.main.ui.handoff.attributes.shadow :refer [shadow-panel]] + [app.main.ui.handoff.attributes.blur :refer [blur-panel]] + [app.main.ui.handoff.attributes.image :refer [image-panel]] + [app.main.ui.handoff.attributes.text :refer [text-panel]])) (def type->options {:multiple [:fill :stroke :image :text :shadow :blur] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/blur.cljs b/frontend/src/app/main/ui/handoff/attributes/blur.cljs similarity index 96% rename from frontend/src/app/main/ui/viewer/handoff/attributes/blur.cljs rename to frontend/src/app/main/ui/handoff/attributes/blur.cljs index 203f5658c5..166779332e 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/blur.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/blur.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.blur +(ns app.main.ui.handoff.attributes.blur (:require [rumext.alpha :as mf] [cuerdas.core :as str] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs b/frontend/src/app/main/ui/handoff/attributes/common.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs rename to frontend/src/app/main/ui/handoff/attributes/common.cljs index 8fe89b976e..f2bcce9a4a 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/common.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.common +(ns app.main.ui.handoff.attributes.common (:require [rumext.alpha :as mf] [cuerdas.core :as str] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/fill.cljs b/frontend/src/app/main/ui/handoff/attributes/fill.cljs similarity index 94% rename from frontend/src/app/main/ui/viewer/handoff/attributes/fill.cljs rename to frontend/src/app/main/ui/handoff/attributes/fill.cljs index 8afb6d5ba0..cf6a8d48aa 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/fill.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/fill.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.fill +(ns app.main.ui.handoff.attributes.fill (:require [rumext.alpha :as mf] [app.util.i18n :refer [t]] @@ -15,7 +15,7 @@ [app.main.ui.icons :as i] [app.util.code-gen :as cg] [app.main.ui.components.copy-button :refer [copy-button]] - [app.main.ui.viewer.handoff.attributes.common :refer [color-row]])) + [app.main.ui.handoff.attributes.common :refer [color-row]])) (def fill-attributes [:fill-color :fill-color-gradient]) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/image.cljs b/frontend/src/app/main/ui/handoff/attributes/image.cljs similarity index 97% rename from frontend/src/app/main/ui/viewer/handoff/attributes/image.cljs rename to frontend/src/app/main/ui/handoff/attributes/image.cljs index c4fd0c6397..5b63e839e6 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/image.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/image.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.image +(ns app.main.ui.handoff.attributes.image (:require [rumext.alpha :as mf] [cuerdas.core :as str] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs b/frontend/src/app/main/ui/handoff/attributes/layout.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs rename to frontend/src/app/main/ui/handoff/attributes/layout.cljs index 3aa984b7b8..02175ece73 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/layout.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.layout +(ns app.main.ui.handoff.attributes.layout (:require [rumext.alpha :as mf] [cuerdas.core :as str] @@ -49,7 +49,7 @@ [:div.attributes-label (t locale "handoff.attributes.layout.left")] [:div.attributes-value (mth/precision (:x shape) 2) "px"] [:& copy-button {:data (copy-data shape :x)}]]) - + (when (not= (:y shape) 0) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.top")] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/shadow.cljs b/frontend/src/app/main/ui/handoff/attributes/shadow.cljs similarity index 95% rename from frontend/src/app/main/ui/viewer/handoff/attributes/shadow.cljs rename to frontend/src/app/main/ui/handoff/attributes/shadow.cljs index 44089cc463..1ddb7b86fc 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/shadow.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/shadow.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.shadow +(ns app.main.ui.handoff.attributes.shadow (:require [rumext.alpha :as mf] [cuerdas.core :as str] @@ -16,7 +16,7 @@ [app.main.ui.icons :as i] [app.util.code-gen :as cg] [app.main.ui.components.copy-button :refer [copy-button]] - [app.main.ui.viewer.handoff.attributes.common :refer [color-row]])) + [app.main.ui.handoff.attributes.common :refer [color-row]])) (defn has-shadow? [shape] (:shadow shape)) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs b/frontend/src/app/main/ui/handoff/attributes/stroke.cljs similarity index 95% rename from frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs rename to frontend/src/app/main/ui/handoff/attributes/stroke.cljs index fe26f8be5e..14faeb5ecb 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/stroke.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.stroke +(ns app.main.ui.handoff.attributes.stroke (:require [rumext.alpha :as mf] [cuerdas.core :as str] @@ -16,7 +16,7 @@ [app.main.ui.icons :as i] [app.util.code-gen :as cg] [app.main.ui.components.copy-button :refer [copy-button]] - [app.main.ui.viewer.handoff.attributes.common :refer [color-row]])) + [app.main.ui.handoff.attributes.common :refer [color-row]])) (defn shape->color [shape] {:color (:stroke-color shape) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/text.cljs b/frontend/src/app/main/ui/handoff/attributes/text.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/attributes/text.cljs rename to frontend/src/app/main/ui/handoff/attributes/text.cljs index 9c1090f416..81c75388a4 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/text.cljs +++ b/frontend/src/app/main/ui/handoff/attributes/text.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.attributes.text +(ns app.main.ui.handoff.attributes.text (:require [rumext.alpha :as mf] [cuerdas.core :as str] @@ -19,7 +19,7 @@ [app.main.fonts :as fonts] [app.main.ui.icons :as i] [app.util.webapi :as wapi] - [app.main.ui.viewer.handoff.attributes.common :refer [color-row]] + [app.main.ui.handoff.attributes.common :refer [color-row]] [app.util.code-gen :as cg] [app.main.store :as st] [app.main.ui.components.copy-button :refer [copy-button]])) diff --git a/frontend/src/app/main/ui/viewer/handoff/code.cljs b/frontend/src/app/main/ui/handoff/code.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/code.cljs rename to frontend/src/app/main/ui/handoff/code.cljs index 19ff75c576..eecdb80f74 100644 --- a/frontend/src/app/main/ui/viewer/handoff/code.cljs +++ b/frontend/src/app/main/ui/handoff/code.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.code +(ns app.main.ui.handoff.code (:require ["js-beautify" :as beautify] [cuerdas.core :as str] diff --git a/frontend/src/app/main/ui/viewer/handoff/exports.cljs b/frontend/src/app/main/ui/handoff/exports.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/exports.cljs rename to frontend/src/app/main/ui/handoff/exports.cljs index 4dbc303c3c..a992b69807 100644 --- a/frontend/src/app/main/ui/viewer/handoff/exports.cljs +++ b/frontend/src/app/main/ui/handoff/exports.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.exports +(ns app.main.ui.handoff.exports (:require [rumext.alpha :as mf] [beicon.core :as rx] @@ -59,7 +59,7 @@ (swap! exports (fn [exports] (let [[before after] (split-at index exports)] (d/concat [] before (rest after))))))) - + on-scale-change (mf/use-callback (mf/deps shape) @@ -68,7 +68,7 @@ value (dom/get-value target) value (d/parse-double value)] (swap! exports assoc-in [index :scale] value)))) - + on-suffix-change (mf/use-callback (mf/deps shape) @@ -76,7 +76,7 @@ (let [target (dom/get-target event) value (dom/get-value target)] (swap! exports assoc-in [index :suffix] value)))) - + on-type-change (mf/use-callback (mf/deps shape) diff --git a/frontend/src/app/main/ui/viewer/handoff/left_sidebar.cljs b/frontend/src/app/main/ui/handoff/left_sidebar.cljs similarity index 96% rename from frontend/src/app/main/ui/viewer/handoff/left_sidebar.cljs rename to frontend/src/app/main/ui/handoff/left_sidebar.cljs index 0c2a4ef829..d44ce15c6a 100644 --- a/frontend/src/app/main/ui/viewer/handoff/left_sidebar.cljs +++ b/frontend/src/app/main/ui/handoff/left_sidebar.cljs @@ -7,18 +7,18 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.left-sidebar +(ns app.main.ui.handoff.left-sidebar (:require - [rumext.alpha :as mf] - [okulary.core :as l] [app.common.data :as d] [app.common.uuid :as uuid] - [app.main.store :as st] - [app.util.dom :as dom] [app.main.data.viewer :as dv] + [app.main.store :as st] [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] - [app.main.ui.workspace.sidebar.layers :refer [element-icon layer-name frame-wrapper]])) + [app.main.ui.workspace.sidebar.layers :refer [element-icon layer-name frame-wrapper]] + [app.util.dom :as dom] + [okulary.core :as l] + [rumext.alpha :as mf])) (def selected-shapes (l/derived (comp :selected :viewer-local) st/state)) @@ -29,7 +29,7 @@ (defn- make-collapsed-iref [id] #(-> (l/in [:viewer-local :collapsed id]) - (l/derived st/state) )) + (l/derived st/state))) (mf/defc layer-item [{:keys [index item selected objects disable-collapse?] :as props}] diff --git a/frontend/src/app/main/ui/viewer/handoff/render.cljs b/frontend/src/app/main/ui/handoff/render.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/render.cljs rename to frontend/src/app/main/ui/handoff/render.cljs index 7f5c238dc6..26e0c8d5d0 100644 --- a/frontend/src/app/main/ui/viewer/handoff/render.cljs +++ b/frontend/src/app/main/ui/handoff/render.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.render +(ns app.main.ui.handoff.render "The main container for a frame in handoff mode" (:require [rumext.alpha :as mf] @@ -30,7 +30,7 @@ [app.main.ui.shapes.path :as path] [app.main.ui.shapes.rect :as rect] [app.main.ui.shapes.text :as text] - [app.main.ui.viewer.handoff.selection-feedback :refer [selection-feedback]] + [app.main.ui.handoff.selection-feedback :refer [selection-feedback]] [app.main.ui.shapes.shape :refer [shape-container]])) (declare shape-container-factory) diff --git a/frontend/src/app/main/ui/viewer/handoff/right_sidebar.cljs b/frontend/src/app/main/ui/handoff/right_sidebar.cljs similarity index 94% rename from frontend/src/app/main/ui/viewer/handoff/right_sidebar.cljs rename to frontend/src/app/main/ui/handoff/right_sidebar.cljs index 210503d6c6..ce9abf05cb 100644 --- a/frontend/src/app/main/ui/viewer/handoff/right_sidebar.cljs +++ b/frontend/src/app/main/ui/handoff/right_sidebar.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.right-sidebar +(ns app.main.ui.handoff.right-sidebar (:require [rumext.alpha :as mf] [okulary.core :as l] @@ -16,8 +16,8 @@ [app.main.ui.icons :as i] [app.main.ui.components.tab-container :refer [tab-container tab-element]] [app.main.ui.workspace.sidebar.layers :refer [element-icon]] - [app.main.ui.viewer.handoff.attributes :refer [attributes]] - [app.main.ui.viewer.handoff.code :refer [code]])) + [app.main.ui.handoff.attributes :refer [attributes]] + [app.main.ui.handoff.code :refer [code]])) (defn make-selected-shapes-iref [] diff --git a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs b/frontend/src/app/main/ui/handoff/selection_feedback.cljs similarity index 98% rename from frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs rename to frontend/src/app/main/ui/handoff/selection_feedback.cljs index ec9c781fcf..371134d568 100644 --- a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs +++ b/frontend/src/app/main/ui/handoff/selection_feedback.cljs @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.main.ui.viewer.handoff.selection-feedback +(ns app.main.ui.handoff.selection-feedback (:require [rumext.alpha :as mf] [cuerdas.core :as str] diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index 178360b683..ab9953317a 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -50,23 +50,6 @@ (fn [] (mousetrap/reset)))) nil) -(defn use-fullscreen - [ref] - (let [state (mf/use-state (dom/fullscreen?)) - change (mf/use-callback #(reset! state (dom/fullscreen?))) - toggle (mf/use-callback (mf/deps @state) - #(let [el (mf/ref-val ref)] - (swap! state not) - (if @state - (wapi/exit-fullscreen) - (wapi/request-fullscreen el))))] - (mf/use-effect - (fn [] - (.addEventListener js/document "fullscreenchange" change) - #(.removeEventListener js/document "fullscreenchange" change))) - - [toggle @state])) - (defn invisible-image [] (let [img (js/Image.) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 21774edd95..6633f236bf 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -9,31 +9,182 @@ (ns app.main.ui.viewer (:require + [app.common.data :as d] [app.common.exceptions :as ex] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as geom] + [app.common.pages-helpers :as cph] [app.main.data.viewer :as dv] + [app.main.data.comments :as dcm] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.components.fullscreen :as fs] [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] [app.main.ui.viewer.header :refer [header]] - [app.main.ui.viewer.shapes :refer [frame-svg]] + [app.main.ui.viewer.shapes :as shapes :refer [frame-svg]] [app.main.ui.viewer.thumbnails :refer [thumbnails-panel]] - [app.util.data :refer [classnames]] + [app.main.ui.comments :as cmt] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t tr]] - [beicon.core :as rx] [goog.events :as events] [okulary.core :as l] - [rumext.alpha :as mf]) - (:import goog.events.EventType)) + [rumext.alpha :as mf])) + +(defn- frame-contains? + [{:keys [x y width height]} {px :x py :y}] + (let [x2 (+ x width) + y2 (+ y height)] + (and (<= x px x2) + (<= y py y2)))) + +(def threads-ref + (l/derived :comment-threads st/state)) + +(def comments-local-ref + (l/derived :comments-local st/state)) + +(mf/defc comments-layer + [{:keys [width height zoom frame data] :as props}] + (let [profile (mf/deref refs/profile) + + modifier1 (-> (gpt/point (:x frame) (:y frame)) + (gpt/negate) + (gmt/translate-matrix)) + + modifier2 (-> (gpt/point (:x frame) (:y frame)) + (gmt/translate-matrix)) + + threads-map (->> (mf/deref threads-ref) + (d/mapm #(update %2 :position gpt/transform modifier1))) + + cstate (mf/deref refs/comments-local) + + mframe (geom/transform-shape frame) + threads (->> (vals threads-map) + (dcm/apply-filters cstate profile) + (filter (fn [{:keys [seqn position]}] + (frame-contains? mframe position)))) + + on-bubble-click + (mf/use-callback + (mf/deps cstate) + (fn [thread] + (if (= (:open cstate) (:id thread)) + (st/emit! (dcm/close-thread)) + (st/emit! (dcm/open-thread thread))))) + + on-click + (mf/use-callback + (mf/deps cstate data) + (fn [event] + (dom/stop-propagation event) + (if (some? (:open cstate)) + (st/emit! (dcm/close-thread)) + (let [event (.-nativeEvent ^js event) + position (-> (dom/get-offset-position event) + (gpt/transform modifier2)) + params {:position position + :page-id (get-in data [:page :id]) + :file-id (get-in data [:file :id])}] + (st/emit! (dcm/create-draft params)))))) + + on-draft-cancel + (mf/use-callback + (mf/deps cstate) + (st/emitf (dcm/close-thread))) + + on-draft-submit + (mf/use-callback + (fn [draft] + (let [params (update draft :position gpt/transform modifier2)] + ;; (prn "on-draft-submit" params) + + (st/emit! (dcm/create-thread params) + (dcm/close-thread))))) + ] + + [:div.viewer-comments {:on-click on-click} + [:div.comments-layer + [:div.threads + (for [item threads] + [:& cmt/thread-bubble {:thread item + :zoom zoom + :on-click on-bubble-click + :open? (= (:id item) (:open cstate)) + :key (:seqn item)}]) + + (when-let [id (:open cstate)] + (when-let [thread (get threads-map id)] + [:& cmt/thread-comments {:thread thread + :users (:users data) + :zoom zoom}])) + + (when-let [draft (:draft cstate)] + [:& cmt/draft-thread {:draft (update draft :position gpt/transform modifier1) + :on-cancel on-draft-cancel + :on-submit on-draft-submit + :zoom zoom}])]]])) + + + +(mf/defc viewport + {::mf/wrap [mf/memo]} + [{:keys [state data index section] :or {zoom 1} :as props}] + (let [zoom (:zoom state) + objects (:objects data) + + frame (get-in data [:frames index]) + frame-id (:id frame) + + modifier (-> (gpt/point (:x frame) (:y frame)) + (gpt/negate) + (gmt/translate-matrix)) + + update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) + + objects (->> (d/concat [frame-id] (cph/get-children frame-id objects)) + (reduce update-fn objects)) + + interactions? (:interactions-show? state) + wrapper (mf/use-memo (mf/deps objects) #(shapes/frame-container-factory objects interactions?)) + + ;; Retrieve frame again with correct modifier + frame (get objects frame-id) + + width (* (:width frame) zoom) + height (* (:height frame) zoom) + vbox (str "0 0 " (:width frame 0) " " (:height frame 0))] + + [:div.viewport-container + {:style {:width width + :height height + :state state + :position "relative"}} + + (when (= section :comments) + [:& comments-layer {:width width + :height height + :frame frame + :data data + :zoom zoom}]) + + [:svg {:view-box vbox + :width width + :height height + :version "1.1" + :xmlnsXlink "http://www.w3.org/1999/xlink" + :xmlns "http://www.w3.org/2000/svg"} + [:& wrapper {:shape frame + :show-interactions? interactions? + :view-box vbox}]]])) (mf/defc main-panel - [{:keys [data local index]}] + [{:keys [data state index section]}] (let [locale (mf/deref i18n/locale) - frames (:frames data []) - objects (:objects data) + frames (:frames data) frame (get frames index)] [:section.viewer-preview (cond @@ -45,22 +196,20 @@ [:section.empty-state [:span (t locale "viewer.frame-not-found")]] - :else - [:& frame-svg {:frame frame - :show-interactions? (:show-interactions? local) - :zoom (:zoom local) - :objects objects}])])) + (some? state) + [:& viewport + {:data data + :section section + :index index + :state state + }])])) (mf/defc viewer-content - [{:keys [data local index] :as props}] - (let [container (mf/use-ref) - - [toggle-fullscreen fullscreen?] (hooks/use-fullscreen container) - - on-click + [{:keys [data state index section] :as props}] + (let [on-click (fn [event] (dom/stop-propagation event) - (let [mode (get local :interactions-mode)] + (let [mode (get state :interactions-mode)] (when (= mode :show-on-click) (st/emit! dv/flash-interactions)))) @@ -73,49 +222,63 @@ (st/emit! dv/decrease-zoom) (st/emit! dv/increase-zoom))))) + on-click + (fn [event] + (st/emit! (dcm/close-thread))) + + on-key-down + (fn [event] + (when (kbd/esc? event) + (st/emit! (dcm/close-thread)))) + on-mount (fn [] ;; bind with passive=false to allow the event to be cancelled ;; https://stackoverflow.com/a/57582286/3219895 - (let [key1 (events/listen goog/global EventType.WHEEL - on-mouse-wheel #js {"passive" false})] + (let [key1 (events/listen goog/global "wheel" on-mouse-wheel #js {"passive" false}) + key2 (events/listen js/document "keydown" on-key-down) + key3 (events/listen js/document "click" on-click)] (fn [] - (events/unlistenByKey key1))))] + (events/unlistenByKey key1) + (events/unlistenByKey key2) + (events/unlistenByKey key3))))] (mf/use-effect on-mount) (hooks/use-shortcuts dv/shortcuts) - [:div.viewer-layout {:class (classnames :fullscreen fullscreen?) - :ref container} + [:& fs/fullscreen-wrapper {} + [:div.viewer-layout + [:& header + {:data data + :state state + :section section + :index index}] - [:& header {:data data - :toggle-fullscreen toggle-fullscreen - :fullscreen? fullscreen? - :local local - :index index - :screen :viewer}] - [:div.viewer-content {:on-click on-click} - (when (:show-thumbnails local) - [:& thumbnails-panel {:screen :viewer - :index index - :data data}]) - [:& main-panel {:data data - :local local - :index index}]]])) + [:div.viewer-content {:on-click on-click} + (when (:show-thumbnails state) + [:& thumbnails-panel {:screen :viewer + :index index + :data data}]) + [:& main-panel {:data data + :section section + :state state + :index index}]]]])) ;; --- Component: Viewer Page (mf/defc viewer-page - [{:keys [file-id page-id index token] :as props}] + [{:keys [file-id page-id index token section] :as props}] + (mf/use-effect (mf/deps file-id page-id token) - (fn [] - (st/emit! (dv/initialize props)))) + (st/emitf (dv/initialize props))) - (let [data (mf/deref refs/viewer-data) - local (mf/deref refs/viewer-local)] - (when data - [:& viewer-content {:index index - :local local - :data data}]))) + (let [data (mf/deref refs/viewer-data) + state (mf/deref refs/viewer-local)] + (when (and data state) + [:& viewer-content + {:index index + :section section + :state state + :data data}]))) diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 62bcb539a4..90aabdc953 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -9,21 +9,23 @@ (ns app.main.ui.viewer.header (:require - [rumext.alpha :as mf] - [cuerdas.core :as str] - [app.main.ui.icons :as i] + [app.common.math :as mth] + [app.common.uuid :as uuid] [app.main.data.messages :as dm] [app.main.data.viewer :as dv] + [app.main.data.comments :as dcm] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.components.fullscreen :as fs] + [app.main.ui.icons :as i] [app.util.data :refer [classnames]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t]] [app.util.router :as rt] - [app.common.math :as mth] - [app.common.uuid :as uuid] - [app.util.webapi :as wapi])) + [app.util.webapi :as wapi] + [cuerdas.core :as str] + [rumext.alpha :as mf])) (mf/defc zoom-widget {:wrap [mf/memo]} @@ -40,7 +42,7 @@ [:span.dropdown-button i/arrow-down] [:& dropdown {:show @show-dropdown? :on-close #(reset! show-dropdown? false)} - [:ul.zoom-dropdown + [:ul.dropdown.zoom-dropdown [:li {:on-click on-increase} "Zoom in" [:span "+"]] [:li {:on-click on-decrease} @@ -52,29 +54,6 @@ [:li {:on-click on-zoom-to-200} "Zoom to 200%" [:span "Shift + 2"]]]]])) -(mf/defc interactions-menu - [{:keys [interactions-mode] :as props}] - (let [show-dropdown? (mf/use-state false) - locale (i18n/use-locale) - on-select-mode #(st/emit! (dv/set-interactions-mode %))] - [:div.header-icon - [:a {:on-click #(swap! show-dropdown? not)} i/eye - [:& dropdown {:show @show-dropdown? - :on-close #(swap! show-dropdown? not)} - [:ul.custom-select-dropdown - [:li {:key :hide - :class (classnames :selected (= interactions-mode :hide)) - :on-click #(on-select-mode :hide)} - (t locale "viewer.header.dont-show-interactions")] - [:li {:key :show - :class (classnames :selected (= interactions-mode :show)) - :on-click #(on-select-mode :show)} - (t locale "viewer.header.show-interactions")] - [:li {:key :show-on-click - :class (classnames :selected (= interactions-mode :show-on-click)) - :on-click #(on-select-mode :show-on-click)} - (t locale "viewer.header.show-interactions-on-click")]]]]])) - (mf/defc share-link [{:keys [page token] :as props}] (let [show-dropdown? (mf/use-state false) @@ -103,7 +82,7 @@ [:& dropdown {:show @show-dropdown? :on-close #(swap! show-dropdown? not) :container dropdown-ref} - [:div.share-link-dropdown {:ref dropdown-ref} + [:div.dropdown.share-link-dropdown {:ref dropdown-ref} [:span.share-link-title (t locale "viewer.header.share.title")] [:div.share-link-input (if (string? token) @@ -121,34 +100,122 @@ [:button.btn-primary {:on-click create} (t locale "viewer.header.share.create-link")])]]]])) +(mf/defc interactions-menu + [{:keys [state locale] :as props}] + (let [imode (:interactions-mode state) + + show-dropdown? (mf/use-state false) + show-dropdown (mf/use-fn #(reset! show-dropdown? true)) + hide-dropdown (mf/use-fn #(reset! show-dropdown? false)) + + select-mode + (mf/use-callback + (fn [mode] + (st/emit! (dv/set-interactions-mode mode))))] + + [:div.view-options + [:div.icon {:on-click #(swap! show-dropdown? not)} i/eye] + [:& dropdown {:show @show-dropdown? + :on-close hide-dropdown} + [:ul.dropdown.with-check + [:li {:class (dom/classnames :selected (= imode :hide)) + :on-click #(select-mode :hide)} + [:span.icon i/tick] + [:span.label (t locale "viewer.header.dont-show-interactions")]] + + [:li {:class (dom/classnames :selected (= imode :show)) + :on-click #(select-mode :show)} + [:span.icon i/tick] + [:span.label (t locale "viewer.header.show-interactions")]] + + [:li {:class (dom/classnames :selected (= imode :show-on-click)) + :on-click #(select-mode :show-on-click)} + [:span.icon i/tick] + [:span.label (t locale "viewer.header.show-interactions-on-click")]]]]])) + + +(mf/defc comments-menu + [{:keys [locale] :as props}] + (let [{cmode :mode cshow :show} (mf/deref refs/comments-local) + + show-dropdown? (mf/use-state false) + show-dropdown (mf/use-fn #(reset! show-dropdown? true)) + hide-dropdown (mf/use-fn #(reset! show-dropdown? false)) + + update-mode + (mf/use-callback + (fn [mode] + (st/emit! (dcm/update-filters {:mode mode})))) + + update-show + (mf/use-callback + (fn [mode] + (st/emit! (dcm/update-filters {:show mode}))))] + + [:div.view-options + [:div.icon {:on-click #(swap! show-dropdown? not)} i/eye] + [:& dropdown {:show @show-dropdown? + :on-close hide-dropdown} + [:ul.dropdown.with-check + [:li {:class (dom/classnames :selected (= :all cmode)) + :on-click #(update-mode :all)} + [:span.icon i/tick] + [:span.label (t locale "labels.show-all-comments")]] + + [:li {:class (dom/classnames :selected (= :yours cmode)) + :on-click #(update-mode :yours)} + [:span.icon i/tick] + [:span.label (t locale "labels.show-your-comments")]] + + [:hr] + + [:li {:class (dom/classnames :selected (= :pending cshow)) + :on-click #(update-show (if (= :pending cshow) :all :pending))} + [:span.icon i/tick] + [:span.label (t locale "labels.hide-resolved-comments")]]]]])) + (mf/defc header - [{:keys [data index local fullscreen? toggle-fullscreen screen] :as props}] + [{:keys [data index section state] :as props}] (let [{:keys [project file page frames]} data - total (count frames) - on-click #(st/emit! dv/toggle-thumbnails-panel) - interactions-mode (:interactions-mode local) - - locale (i18n/use-locale) - - profile (mf/deref refs/profile) + fullscreen (mf/use-ctx fs/fullscreen-context) + total (count frames) + locale (mf/deref i18n/locale) + profile (mf/deref refs/profile) anonymous? (= uuid/zero (:id profile)) project-id (get-in data [:project :id]) - file-id (get-in data [:file :id]) - page-id (get-in data [:page :id]) + file-id (get-in data [:file :id]) + page-id (get-in data [:page :id]) - on-edit #(st/emit! (rt/nav :workspace - {:project-id project-id - :file-id file-id} - {:page-id page-id})) + on-click + (mf/use-callback + (st/emitf dv/toggle-thumbnails-panel)) + + on-edit + (mf/use-callback + (st/emitf (rt/nav :workspace + {:project-id project-id + :file-id file-id} + {:page-id page-id}))) + navigate + (mf/use-callback + (fn [section] + (st/emit! + (case section + :interactions + (rt/nav :viewer + {:file-id file-id :page-id page-id} + {:index index :section "interactions"}) + :comments + (rt/nav :viewer + {:file-id file-id :page-id page-id} + {:index index :section "comments"}) + :handoff + (rt/nav :handoff + {:file-id file-id :page-id page-id} + {:index index})))))] - change-screen - (fn [screen] - (st/emit! - (rt/nav screen - {:file-id file-id :page-id page-id} - {:index index})))] [:header.viewer-header [:div.main-icon [:a {:on-click on-edit} i/logo-icon]] @@ -160,19 +227,33 @@ [:span.file-name (:name file)] [:span "/"] [:span.page-name (:name page)] - [:span.dropdown-button i/arrow-down] + [:span.show-thumbnails-button i/arrow-down] [:span.counters (str (inc index) " / " total)]] [:div.mode-zone - [:button.mode-zone-button.tooltip.tooltip-bottom {:on-click #(when (not= screen :viewer) - (change-screen :viewer)) - :class (when (= screen :viewer) "active") :alt "View mode"} i/play] - [:button.mode-zone-button.tooltip.tooltip-bottom {:on-click #(when (not= screen :handoff) - (change-screen :handoff)) - :class (when (= screen :handoff) "active") :alt "Code mode"} i/code]] + [:button.mode-zone-button.tooltip.tooltip-bottom + {:on-click #(navigate :interactions) + :class (dom/classnames :active (= section :interactions)) + :alt "View mode"} + i/play] + + [:button.mode-zone-button.tooltip.tooltip-bottom + {:on-click #(navigate :comments) + :class (dom/classnames :active (= section :comments)) + :alt "Comments"} + i/chat] + + [:button.mode-zone-button.tooltip.tooltip-bottom + {:on-click #(navigate :handoff) + :class (dom/classnames :active (= section :handoff)) + :alt "Code mode"} + i/code]] [:div.options-zone - [:& interactions-menu {:interactions-mode interactions-mode}] + (case section + :interactions [:& interactions-menu {:state state :locale locale}] + :comments [:& comments-menu {:locale locale}] + nil) (when-not anonymous? [:& share-link {:token (:share-token data) @@ -183,17 +264,17 @@ (t locale "viewer.header.edit-page")]) [:& zoom-widget - {:zoom (:zoom local) - :on-increase #(st/emit! dv/increase-zoom) - :on-decrease #(st/emit! dv/decrease-zoom) - :on-zoom-to-50 #(st/emit! dv/zoom-to-50) - :on-zoom-to-100 #(st/emit! dv/reset-zoom) - :on-zoom-to-200 #(st/emit! dv/zoom-to-200)}] + {:zoom (:zoom state) + :on-increase (st/emitf dv/increase-zoom) + :on-decrease (st/emitf dv/decrease-zoom) + :on-zoom-to-50 (st/emitf dv/zoom-to-50) + :on-zoom-to-100 (st/emitf dv/reset-zoom) + :on-zoom-to-200 (st/emitf dv/zoom-to-200)}] [:span.btn-icon-dark.btn-small.tooltip.tooltip-bottom {:alt (t locale "viewer.header.fullscreen") - :on-click toggle-fullscreen} - (if fullscreen? + :on-click #(if @fullscreen (fullscreen false) (fullscreen true))} + (if @fullscreen i/full-screen-off i/full-screen)] ]])) diff --git a/frontend/src/app/main/ui/viewer/thumbnails.cljs b/frontend/src/app/main/ui/viewer/thumbnails.cljs index 57fb011522..b2af4a5155 100644 --- a/frontend/src/app/main/ui/viewer/thumbnails.cljs +++ b/frontend/src/app/main/ui/viewer/thumbnails.cljs @@ -111,8 +111,7 @@ on-item-click (fn [event index] (compare-and-set! selected false true) - (st/emit! (rt/nav screen {:file-id file-id - :page-id page-id} {:index index})) + (st/emit! (dv/go-to-frame-by-index index)) (when @expanded? (on-close)))] [:& dropdown' {:on-close on-close diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index dd98602982..f2f113e882 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -12,362 +12,54 @@ [app.config :as cfg] [app.main.data.workspace :as dw] [app.main.data.workspace.comments :as dwcm] - [app.main.data.workspace.common :as dwc] + [app.main.data.comments :as dcm] [app.main.refs :as refs] [app.main.store :as st] - [app.main.streams :as ms] [app.main.ui.context :as ctx] [app.main.ui.components.dropdown :refer [dropdown]] - [app.main.data.modal :as modal] - [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] - [app.main.ui.keyboard :as kbd] - [app.main.ui.workspace.colorpicker] - [app.main.ui.workspace.context-menu :refer [context-menu]] + [app.main.ui.comments :as cmt] [app.util.time :as dt] [app.util.timers :as tm] [app.util.dom :as dom] - [app.util.object :as obj] - [beicon.core :as rx] [app.util.i18n :as i18n :refer [t tr]] [cuerdas.core :as str] [okulary.core :as l] [rumext.alpha :as mf])) -(declare group-threads-by-page) -(declare apply-filters) - -(mf/defc resizing-textarea - {::mf/wrap-props false} - [props] - (let [value (obj/get props "value" "") - on-focus (obj/get props "on-focus") - on-blur (obj/get props "on-blur") - placeholder (obj/get props "placeholder") - on-change (obj/get props "on-change") - - on-esc (obj/get props "on-esc") - - ref (mf/use-ref) - ;; state (mf/use-state value) - - on-key-down - (mf/use-callback - (fn [event] - (when (and (kbd/esc? event) - (fn? on-esc)) - (on-esc event)))) - - on-change* - (mf/use-callback - (mf/deps on-change) - (fn [event] - (let [content (dom/get-target-val event)] - (on-change content))))] - - - (mf/use-layout-effect - nil - (fn [] - (let [node (mf/ref-val ref)] - (set! (.-height (.-style node)) "0") - (set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))) - - [:textarea - {:ref ref - :on-key-down on-key-down - :on-focus on-focus - :on-blur on-blur - :value value - :placeholder placeholder - :on-change on-change*}])) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Workspace -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(mf/defc reply-form - [{:keys [thread] :as props}] - (let [show-buttons? (mf/use-state false) - content (mf/use-state "") - - on-focus - (mf/use-callback - #(reset! show-buttons? true)) - - on-blur - (mf/use-callback - #(reset! show-buttons? false)) - - on-change - (mf/use-callback - #(reset! content %)) - - on-cancel - (mf/use-callback - #(do (reset! content "") - (reset! show-buttons? false))) - - on-submit - (mf/use-callback - (mf/deps thread @content) - (fn [] - (st/emit! (dwcm/add-comment thread @content)) - (on-cancel)))] - - [:div.reply-form - [:& resizing-textarea {:value @content - :placeholder "Reply" - :on-blur on-blur - :on-focus on-focus - :on-change on-change}] - (when (or @show-buttons? - (not (empty? @content))) - [:div.buttons - [:input.btn-primary {:type "button" :value "Post" :on-click on-submit}] - [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]])])) - -(mf/defc draft-thread - [{:keys [draft zoom] :as props}] - (let [position (:position draft) - content (:content draft) - pos-x (* (:x position) zoom) - pos-y (* (:y position) zoom) - - on-esc - (mf/use-callback - (mf/deps draft) - (st/emitf :interrupt)) - - on-change - (mf/use-callback - (mf/deps draft) - (fn [content] - (st/emit! (dwcm/update-draft-thread (assoc draft :content content))))) - - on-submit - (mf/use-callback - (mf/deps draft) - (st/emitf (dwcm/create-thread draft)))] - - [:* - [:div.thread-bubble - {:style {:top (str pos-y "px") - :left (str pos-x "px")}} - [:span "?"]] - [:div.thread-content - {:style {:top (str (- pos-y 14) "px") - :left (str (+ pos-x 14) "px")}} - [:div.reply-form - [:& resizing-textarea {:placeholder "Write new comment" - :value content - :on-esc on-esc - :on-change on-change}] - [:div.buttons - [:input.btn-primary - {:on-click on-submit - :type "button" - :value "Post"}] - [:input.btn-secondary - {:on-click on-esc - :type "button" - :value "Cancel"}]]]]])) - - -(mf/defc edit-form - [{:keys [content on-submit on-cancel] :as props}] - (let [content (mf/use-state content) - - on-change - (mf/use-callback - #(reset! content %)) - - on-submit* - (mf/use-callback - (mf/deps @content) - (fn [] (on-submit @content)))] - - [:div.reply-form.edit-form - [:& resizing-textarea {:value @content - :on-change on-change}] - [:div.buttons - [:input.btn-primary {:type "button" :value "Post" :on-click on-submit*}] - [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]]])) - - -(mf/defc comment-item - [{:keys [comment thread] :as props}] - (let [profile (get @refs/workspace-users (:owner-id comment)) - - options (mf/use-state false) - edition? (mf/use-state false) - - on-show-options - (mf/use-callback #(reset! options true)) - - on-hide-options - (mf/use-callback #(reset! options false)) - - on-edit-clicked - (mf/use-callback - (fn [] - (reset! options false) - (reset! edition? true))) - - on-delete-comment - (mf/use-callback - (mf/deps comment) - (st/emitf (dwcm/delete-comment comment))) - - delete-thread - (mf/use-callback - (mf/deps thread) - (st/emitf (dwcm/close-thread) - (dwcm/delete-comment-thread thread))) - - - on-delete-thread - (mf/use-callback - (mf/deps thread) - (st/emitf (modal/show - {:type :confirm - :title (tr "modals.delete-comment-thread.title") - :message (tr "modals.delete-comment-thread.message") - :accept-label (tr "modals.delete-comment-thread.accept") - :on-accept delete-thread}))) - - on-submit - (mf/use-callback - (mf/deps comment thread) - (fn [content] - (reset! edition? false) - (st/emit! (dwcm/update-comment (assoc comment :content content))))) - - on-cancel - (mf/use-callback #(reset! edition? false)) - - toggle-resolved - (mf/use-callback - (mf/deps thread) - (st/emitf (dwcm/update-comment-thread (update thread :is-resolved not))))] - - [:div.comment-container - [:div.comment - [:div.author - [:div.avatar - [:img {:src (cfg/resolve-media-path (:photo profile))}]] - [:div.name - [:div.fullname (:fullname profile)] - [:div.timeago (dt/timeago (:modified-at comment))]] - - (when (some? thread) - [:div.options-resolve {:on-click toggle-resolved} - (if (:is-resolved thread) - [:span i/checkbox-checked] - [:span i/checkbox-unchecked])]) - - [:div.options - [:div.options-icon {:on-click on-show-options} i/actions]]] - - [:div.content - (if @edition? - [:& edit-form {:content (:content comment) - :on-submit on-submit - :on-cancel on-cancel}] - [:span.text (:content comment)])]] - - [:& dropdown {:show @options - :on-close on-hide-options} - [:ul.dropdown.comment-options-dropdown - [:li {:on-click on-edit-clicked} "Edit"] - (if thread - [:li {:on-click on-delete-thread} "Delete thread"] - [:li {:on-click on-delete-comment} "Delete comment"])]]])) - -(defn comments-ref - [{:keys [id] :as thread}] - (l/derived (l/in [:comments id]) st/state)) - -(mf/defc thread-comments - [{:keys [thread zoom]}] - (let [ref (mf/use-ref) - pos (:position thread) - pos-x (+ (* (:x pos) zoom) 14) - pos-y (- (* (:y pos) zoom) 14) - - comments-ref (mf/use-memo (mf/deps thread) #(comments-ref thread)) - comments-map (mf/deref comments-ref) - comments (->> (vals comments-map) - (sort-by :created-at)) - comment (first comments)] - - (mf/use-effect - (st/emitf (dwcm/update-comment-thread-status thread))) - - (mf/use-effect - (mf/deps thread) - (st/emitf (dwcm/retrieve-comments (:id thread)))) - - (mf/use-layout-effect - (mf/deps thread comments-map) - (fn [] - (when-let [node (mf/ref-val ref)] - (.scrollIntoView ^js node)))) - - [:div.thread-content - {:style {:top (str pos-y "px") - :left (str pos-x "px")}} - - [:div.comments - [:& comment-item {:comment comment - :thread thread}] - (for [item (rest comments)] - [:* - [:hr] - [:& comment-item {:comment item}]]) - [:div {:ref ref}]] - [:& reply-form {:thread thread}]])) - -(mf/defc thread-bubble - {::mf/wrap [mf/memo]} - [{:keys [thread zoom open?] :as params}] - (let [pos (:position thread) - pos-x (* (:x pos) zoom) - pos-y (* (:y pos) zoom) - - on-open-toggle - (mf/use-callback - (mf/deps thread open?) - (fn [] - (if open? - (st/emit! (dwcm/close-thread)) - (st/emit! (dwcm/open-thread thread)))))] - - [:div.thread-bubble - {:style {:top (str pos-y "px") - :left (str pos-x "px")} - :class (dom/classnames - :resolved (:is-resolved thread) - :unread (pos? (:count-unread-comments thread))) - :on-click on-open-toggle} - [:span (:seqn thread)]])) - (def threads-ref (l/derived :comment-threads st/state)) -(def workspace-comments-ref - (l/derived :workspace-comments st/state)) - (mf/defc comments-layer [{:keys [vbox vport zoom file-id page-id drawing] :as props}] (let [pos-x (* (- (:x vbox)) zoom) pos-y (* (- (:y vbox)) zoom) + profile (mf/deref refs/profile) - local (mf/deref workspace-comments-ref) + local (mf/deref refs/comments-local) threads-map (mf/deref threads-ref) + threads (->> (vals threads-map) (filter #(= (:page-id %) page-id)) - (apply-filters local profile))] + (dcm/apply-filters local profile)) + + on-bubble-click + (fn [{:keys [id] :as thread}] + (if (= (:open local) id) + (st/emit! (dcm/close-thread)) + (st/emit! (dcm/open-thread thread)))) + + on-draft-cancel + (mf/use-callback + (st/emitf :interrupt)) + + on-draft-submit + (mf/use-callback + (fn [draft] + (st/emit! (dcm/create-thread draft) + #_(dcm/close-thread)))) + ] + (mf/use-effect (mf/deps file-id) @@ -377,22 +69,27 @@ (st/emit! ::dwcm/finalize)))) [:div.workspace-comments - {:style {:width (str (:width vport) "px") - :height (str (:height vport) "px")}} - [:div.threads {:style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}} - (for [item threads] - [:& thread-bubble {:thread item - :zoom zoom - :open? (= (:id item) (:open local)) - :key (:seqn item)}]) + [:div.comments-layer + {:style {:width (str (:width vport) "px") + :height (str (:height vport) "px")}} + [:div.threads {:style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}} + (for [item threads] + [:& cmt/thread-bubble {:thread item + :zoom zoom + :on-click on-bubble-click + :open? (= (:id item) (:open local)) + :key (:seqn item)}]) - (when-let [id (:open local)] - (when-let [thread (get threads-map id)] - [:& thread-comments {:thread thread - :zoom zoom}])) + (when-let [id (:open local)] + (when-let [thread (get threads-map id)] + [:& cmt/thread-comments {:thread thread + :zoom zoom}])) - (when-let [draft (:comment drawing)] - [:& draft-thread {:draft draft :zoom zoom}])]])) + (when-let [draft (:comment drawing)] + [:& cmt/draft-thread {:draft draft + :on-cancel on-draft-cancel + :on-submit on-draft-submit + :zoom zoom}])]]])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -413,7 +110,7 @@ (st/emit! (dw/go-to-page (:page-id item)))) (tm/schedule (st/emitf (dwcm/center-to-comment-thread item) - (dwcm/open-thread item)))))] + (dcm/open-thread item)))))] [:div.comment {:on-click on-click} [:div.author @@ -461,41 +158,49 @@ (mf/defc sidebar-options [{:keys [local] :as props}] - (let [filter-yours - (mf/use-callback - (mf/deps local) - (st/emitf (dwcm/update-filters {:main :yours}))) + (let [{cmode :mode cshow :show} (mf/deref refs/comments-local) + locale (mf/deref i18n/locale) - filter-all + update-mode (mf/use-callback - (mf/deps local) - (st/emitf (dwcm/update-filters {:main :all}))) + (fn [mode] + (st/emit! (dcm/update-filters {:mode mode})))) - toggle-resolved + update-show (mf/use-callback - (mf/deps local) - (st/emitf (dwcm/update-filters {:resolved (not (:filter-resolved local))})))] + (fn [mode] + (st/emit! (dcm/update-filters {:show mode}))))] - [:ul.dropdown.sidebar-options-dropdown - [:li {:on-click filter-all} "All"] - [:li {:on-click filter-yours} "Only yours"] - [:hr] - (if (:filter-resolved local) - [:li {:on-click toggle-resolved} "Show resolved comments"] - [:li {:on-click toggle-resolved} "Hide resolved comments"])])) + [:ul.dropdown.with-check.sidebar-options-dropdown + [:li {:class (dom/classnames :selected (or (= :all cmode) (nil? cmode))) + :on-click #(update-mode :all)} + [:span.icon i/tick] + [:span.label (t locale "labels.show-all-comments")]] + + [:li {:class (dom/classnames :selected (= :yours cmode)) + :on-click #(update-mode :yours)} + [:span.icon i/tick] + [:span.label (t locale "labels.show-your-comments")]] + + [:hr] + + [:li {:class (dom/classnames :selected (= :pending cshow)) + :on-click #(update-show (if (= :pending cshow) :all :pending))} + [:span.icon i/tick] + [:span.label (t locale "labels.hide-resolved-comments")]]])) (mf/defc comments-sidebar [] (let [threads-map (mf/deref threads-ref) profile (mf/deref refs/profile) - local (mf/deref workspace-comments-ref) + local (mf/deref refs/comments-local) options? (mf/use-state false) tgroups (->> (vals threads-map) (sort-by :modified-at) (reverse) - (apply-filters local profile) - (group-threads-by-page))] + (dcm/apply-filters local profile) + (dcm/group-threads-by-page))] [:div.workspace-comments.workspace-comments-sidebar [:div.sidebar-title @@ -520,30 +225,3 @@ :key (:page-id tgroup)}]])])])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Helpers -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn- group-threads-by-page - [threads] - (letfn [(group-by-page [result thread] - (let [current (first result)] - (if (= (:page-id current) (:page-id thread)) - (cons (update current :items conj thread) - (rest result)) - (cons {:page-id (:page-id thread) :items [thread]} - result))))] - (reverse - (reduce group-by-page nil threads)))) - -(defn- apply-filters - [local profile threads] - (cond->> threads - (true? (:filter-resolved local)) - (filter (fn [item] - (or (not (:is-resolved item)) - (= (:id item) (:open local))))) - - (= :yours (:filter local)) - (filter #(contains? (:participants %) (:id profile))))) - diff --git a/frontend/src/app/util/avatars.cljs b/frontend/src/app/util/avatars.cljs index 39f3908a6d..64a79e1ee2 100644 --- a/frontend/src/app/util/avatars.cljs +++ b/frontend/src/app/util/avatars.cljs @@ -35,3 +35,9 @@ (.fillText context letters (/ size 2) (/ size 1.5)) (.toDataURL canvas))) + +(defn assoc-profile-avatar + [{:keys [photo fullname] :as profile}] + (cond-> profile + (or (nil? photo) (empty? photo)) + (assoc :photo (generate {:name fullname})))) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 92edd65357..c5cdc9c094 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -9,12 +9,11 @@ (ns app.util.dom (:require - [goog.dom :as dom] - [cuerdas.core :as str] - [beicon.core :as rx] - [cuerdas.core :as str] + [app.common.exceptions :as ex] [app.common.geom.point :as gpt] - [app.util.transit :as ts])) + [app.util.object :as obj] + [cuerdas.core :as str] + [goog.dom :as dom])) ;; --- Deprecated methods @@ -111,11 +110,11 @@ (defn select-text! [node] - (.select node)) + (.select ^js node)) (defn ^boolean equals? [node-a node-b] - (.isEqualNode node-a node-b)) + (.isEqualNode ^js node-a node-b)) (defn get-event-files "Extract the files from event instance." @@ -162,6 +161,12 @@ y (.-clientY event)] (gpt/point x y))) +(defn get-offset-position + [event] + (let [x (.-offsetX event) + y (.-offsetY event)] + (gpt/point x y))) + (defn get-client-size [node] {:width (.-clientWidth ^js node) @@ -188,7 +193,16 @@ (defn fullscreen? [] - (boolean (.-fullscreenElement js/document))) + (cond + (obj/in? js/document "webkitFullscreenElement") + (boolean (.-webkitFullscreenElement js/document)) + + (obj/in? js/document "fullscreenElement") + (boolean (.-fullscreenElement js/document)) + + :else + (ex/raise :type :not-supported + :hint "seems like the current browset does not support fullscreen api."))) (defn ^boolean blob? [v] @@ -219,6 +233,6 @@ (defn release-pointer [event] (-> event get-target (.releasePointerCapture (.-pointerId event)))) - + (defn get-root [] (query js/document "#app")) diff --git a/frontend/src/app/util/object.cljs b/frontend/src/app/util/object.cljs index a867cc6463..25d9b254fa 100644 --- a/frontend/src/app/util/object.cljs +++ b/frontend/src/app/util/object.cljs @@ -76,3 +76,7 @@ (defn clj->props [props] (clj->js props :keyword-fn props-key-fn)) + +(defn ^boolean in? + [obj prop] + (js* "~{} in ~{}" prop obj)) diff --git a/frontend/src/app/util/webapi.cljs b/frontend/src/app/util/webapi.cljs index f5b3eb75f4..f18cc56082 100644 --- a/frontend/src/app/util/webapi.cljs +++ b/frontend/src/app/util/webapi.cljs @@ -10,6 +10,8 @@ (ns app.util.webapi "HTML5 web api helpers." (:require + [app.common.exceptions :as ex] + [app.util.object :as obj] [promesa.core :as p] [beicon.core :as rx] [cuerdas.core :as str] @@ -97,8 +99,26 @@ (defn request-fullscreen [el] - (.requestFullscreen el)) + (cond + (obj/in? el "requestFullscreen") + (.requestFullscreen el) + + (obj/in? el "webkitRequestFullscreen") + (.webkitRequestFullscreen el) + + :else + (ex/raise :type :not-supported + :hint "seems like the current browset does not support fullscreen api."))) (defn exit-fullscreen [] - (.exitFullscreen js/document)) + (cond + (obj/in? js/document "exitFullscreen") + (.exitFullscreen js/document) + + (obj/in? js/document "webkitExitFullscreen") + (.webkitExitFullscreen js/document) + + :else + (ex/raise :type :not-supported + :hint "seems like the current browset does not support fullscreen api."))) From b71d5d26a6dacad25d704e7b39d96bc565a85f80 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 14:47:08 +0100 Subject: [PATCH 024/195] :bug: Fix logout. --- frontend/src/app/main/ui/dashboard/sidebar.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index c4ceed6da6..e05f064ca2 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -450,7 +450,7 @@ [:li {:on-click (partial on-click :settings-password)} [:span.icon i/lock] [:span.text (t locale "labels.password")]] - [:li {:on-click (partial on-click da/logout)} + [:li {:on-click (partial on-click (da/logout))} [:span.icon i/exit] [:span.text (t locale "labels.logout")]]]]])) From b2957c5f35d7319584915e398d7c46efea040b2c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 17:22:46 +0100 Subject: [PATCH 025/195] :fire: Remove unused media related api. --- backend/src/app/media.clj | 34 +----- backend/src/app/services/init.clj | 1 - backend/src/app/services/mutations/media.clj | 53 --------- backend/src/app/services/queries/files.clj | 5 +- backend/src/app/services/queries/media.clj | 109 ------------------ backend/src/app/services/queries/profile.clj | 11 +- frontend/src/app/main/data/workspace.cljs | 1 - .../app/main/data/workspace/persistence.cljs | 12 -- 8 files changed, 10 insertions(+), 216 deletions(-) delete mode 100644 backend/src/app/services/queries/media.clj diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index 91a59d611b..dd8002e713 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -160,35 +160,6 @@ ;; --- Utility functions -(defn resolve-urls - [row src dst] - (s/assert map? row) - (if (and src dst) - (let [src (if (vector? src) src [src]) - dst (if (vector? dst) dst [dst]) - value (get-in row src)] - (if (empty? value) - row - (let [url (ust/public-uri mst/media-storage value)] - (assoc-in row dst (str url))))) - row)) - -(defn- resolve-uri - [storage row src dst] - (let [src (if (vector? src) src [src]) - dst (if (vector? dst) dst [dst]) - value (get-in row src)] - (if (empty? value) - row - (let [url (ust/public-uri mst/media-storage value)] - (assoc-in row dst (str url)))))) - -(defn resolve-media-uris - [row & pairs] - (us/assert map? row) - (us/assert (s/coll-of vector?) pairs) - (reduce #(resolve-uri mst/media-storage %1 (nth %2 0) (nth %2 1)) row pairs)) - (defn validate-media-type [media-type] (when-not (cm/valid-media-types media-type) @@ -196,6 +167,11 @@ :code :media-type-not-allowed :hint "Seems like you are uploading an invalid media object"))) + +;; TODO: rewrite using jetty http client instead of jvm +;; builtin (because builtin http client uses a lot of memory for the +;; same operation. + (defn download-media-object [url] (let [result (http/get! url {:as :byte-array}) diff --git a/backend/src/app/services/init.clj b/backend/src/app/services/init.clj index 4df4707edc..d0b69fa73c 100644 --- a/backend/src/app/services/init.clj +++ b/backend/src/app/services/init.clj @@ -14,7 +14,6 @@ (defn- load-query-services [] - (require 'app.services.queries.media) (require 'app.services.queries.projects) (require 'app.services.queries.files) (require 'app.services.queries.comments) diff --git a/backend/src/app/services/mutations/media.clj b/backend/src/app/services/mutations/media.clj index 1495656d3a..1d12c8e8ed 100644 --- a/backend/src/app/services/mutations/media.clj +++ b/backend/src/app/services/mutations/media.clj @@ -147,56 +147,3 @@ (-> thumb (dissoc :data :input) (assoc :path path)))) - -;; --- Mutation: Rename Media object - -(declare select-media-object-for-update) - -(s/def ::rename-media-object - (s/keys :req-un [::id ::profile-id ::name])) - -(sm/defmutation ::rename-media-object - [{:keys [id profile-id name] :as params}] - (db/with-atomic [conn db/pool] - (let [obj (select-media-object-for-update conn id)] - (teams/check-edition-permissions! conn profile-id (:team-id obj)) - (db/update! conn :media-object - {:name name} - {:id id})))) - -(def ^:private sql:select-media-object-for-update - "select obj.*, - p.team_id as team_id - from media_object as obj - inner join file as f on (f.id = obj.file_id) - inner join project as p on (p.id = f.project_id) - where obj.id = ? - for update of obj") - -(defn- select-media-object-for-update - [conn id] - (let [row (db/exec-one! conn [sql:select-media-object-for-update id])] - (when-not row - (ex/raise :type :not-found)) - row)) - -;; --- Delete Media object - -(s/def ::delete-media-object - (s/keys :req-un [::id ::profile-id])) - -(sm/defmutation ::delete-media-object - [{:keys [profile-id id] :as params}] - (db/with-atomic [conn db/pool] - (let [obj (select-media-object-for-update conn id)] - (teams/check-edition-permissions! conn profile-id (:team-id obj)) - - ;; Schedule object deletion - (tasks/submit! conn {:name "delete-object" - :delay cfg/default-deletion-delay - :props {:id id :type :media-object}}) - - (db/update! conn :media-object - {:deleted-at (dt/now)} - {:id id}) - nil))) diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index c83d4a80ec..2f8edc3155 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -202,10 +202,7 @@ (defn retrieve-file-users [conn id] - (->> (db/exec! conn [sql:file-users id id]) - ;; TODO: seems like the frontend is no longer uses :photo-uri, - ;; so this can be removed probably. - (mapv #(media/resolve-media-uris % [:photo :photo-uri])))) + (db/exec! conn [sql:file-users id id])) (s/def ::file-users (s/keys :req-un [::profile-id ::id])) diff --git a/backend/src/app/services/queries/media.clj b/backend/src/app/services/queries/media.clj deleted file mode 100644 index 94ff99dcb5..0000000000 --- a/backend/src/app/services/queries/media.clj +++ /dev/null @@ -1,109 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; This Source Code Form is "Incompatible With Secondary Licenses", as -;; defined by the Mozilla Public License, v. 2.0. -;; -;; Copyright (c) 2019-2020 Andrey Antukh - -(ns app.services.queries.media - (:require - [clojure.spec.alpha :as s] - [app.common.exceptions :as ex] - [app.common.spec :as us] - [app.db :as db] - [app.media :as media] - [app.services.queries :as sq] - [app.services.queries.teams :as teams])) - -(s/def ::id ::us/uuid) -(s/def ::name ::us/string) -(s/def ::profile-id ::us/uuid) -(s/def ::team-id ::us/uuid) -(s/def ::file-id ::us/uuid) - - -;; --- Query: Media objects (by file) - -(declare retrieve-media-objects) -(declare retrieve-file) - -(s/def ::is-local ::us/boolean) -(s/def ::media-objects - (s/keys :req-un [::profile-id ::file-id ::is-local])) - -;; TODO: check if we can resolve url with transducer for reduce -;; garbage generation for each request - -(sq/defquery ::media-objects - [{:keys [profile-id file-id is-local] :as params}] - (db/with-atomic [conn db/pool] - (let [file (retrieve-file conn file-id)] - (teams/check-read-permissions! conn profile-id (:team-id file)) - (->> (retrieve-media-objects conn file-id is-local) - (mapv #(media/resolve-urls % :path :uri)) - (mapv #(media/resolve-urls % :thumb-path :thumb-uri)))))) - -(def ^:private sql:media-objects - "select obj.*, - thumb.path as thumb_path - from media_object as obj - inner join media_thumbnail as thumb on obj.id = thumb.media_object_id - where obj.deleted_at is null - and obj.file_id = ? - and obj.is_local = ? - order by obj.created_at desc") - -(defn retrieve-media-objects - [conn file-id is-local] - (db/exec! conn [sql:media-objects file-id is-local])) - -(def ^:private sql:retrieve-file - "select file.*, - project.team_id as team_id - from file - inner join project on (project.id = file.project_id) - where file.id = ?") - -(defn- retrieve-file - [conn id] - (let [row (db/exec-one! conn [sql:retrieve-file id])] - (when-not row - (ex/raise :type :not-found)) - row)) - - -;; --- Query: Media object (by ID) - -(declare retrieve-media-object) - -(s/def ::id ::us/uuid) -(s/def ::media-object - (s/keys :req-un [::profile-id ::id])) - -(sq/defquery ::media-object - [{:keys [profile-id id] :as params}] - (db/with-atomic [conn db/pool] - (let [media-object (retrieve-media-object conn id)] - (teams/check-read-permissions! conn profile-id (:team-id media-object)) - (-> media-object - (media/resolve-urls :path :uri))))) - -(def ^:private sql:media-object - "select obj.*, - p.team_id as team_id - from media_object as obj - inner join file as f on (f.id = obj.file_id) - inner join project as p on (p.id = f.project_id) - where obj.deleted_at is null - and obj.id = ? - order by created_at desc") - -(defn retrieve-media-object - [conn id] - (let [row (db/exec-one! conn [sql:media-object id])] - (when-not row - (ex/raise :type :not-found)) - row)) - diff --git a/backend/src/app/services/queries/profile.clj b/backend/src/app/services/queries/profile.clj index 29b64583e1..14da3b4535 100644 --- a/backend/src/app/services/queries/profile.clj +++ b/backend/src/app/services/queries/profile.clj @@ -9,15 +9,13 @@ (ns app.services.queries.profile (:require - [clojure.spec.alpha :as s] - [cuerdas.core :as str] [app.common.exceptions :as ex] [app.common.spec :as us] - [app.db :as db] - [app.media :as media] - [app.services.queries :as sq] [app.common.uuid :as uuid] - [app.util.blob :as blob])) + [app.db :as db] + [app.services.queries :as sq] + [clojure.spec.alpha :as s] + [cuerdas.core :as str])) ;; --- Helpers & Specs @@ -82,7 +80,6 @@ (defn retrieve-profile [conn id] (let [profile (some-> (retrieve-profile-data conn id) - (media/resolve-urls :photo :photo-uri) (strip-private-attrs) (merge (retrieve-additional-data conn id)))] (when (nil? profile) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 6daa481ecf..7ac9cba4d2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1706,7 +1706,6 @@ (def link-file-to-library dwp/link-file-to-library) (def unlink-file-from-library dwp/unlink-file-from-library) (def upload-media-objects dwp/upload-media-objects) -(def delete-media-object dwp/delete-media-object) ;; Selection diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index ec38272231..70fe89a886 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -422,18 +422,6 @@ (rx/finalize (fn [] (st/emit! (dm/hide-tag :media-loading)))))))))) - -;; --- Delete media object - -(defn delete-media-object - [file-id id] - (ptk/reify ::delete-media-object - ptk/WatchEvent - (watch [_ state stream] - (let [params {:id id}] - (rp/mutation :delete-media-object params))))) - - ;; --- Helpers (defn purge-page From fca48e39ee67fbd28c74c24c9bfc72c8698f4957 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 17:23:26 +0100 Subject: [PATCH 026/195] :sparkles: Make file to library link idempotent. And remove unused api calls. --- backend/src/app/services/mutations/files.clj | 9 ++-- backend/src/app/services/mutations/media.clj | 1 - backend/src/app/tasks/delete_object.clj | 10 ----- .../app/main/data/workspace/persistence.cljs | 43 +++++-------------- 4 files changed, 16 insertions(+), 47 deletions(-) diff --git a/backend/src/app/services/mutations/files.clj b/backend/src/app/services/mutations/files.clj index 0246d58f4e..27da20bd5f 100644 --- a/backend/src/app/services/mutations/files.clj +++ b/backend/src/app/services/mutations/files.clj @@ -162,11 +162,14 @@ (files/check-edition-permissions! conn profile-id file-id) (link-file-to-library conn params))) +(def sql:link-file-to-library + "insert into file_library_rel (file_id, library_file_id) + values (?, ?) + on conflict do nothing;") + (defn- link-file-to-library [conn {:keys [file-id library-id] :as params}] - (db/insert! conn :file-library-rel - {:file-id file-id - :library-file-id library-id})) + (db/exec-one! conn [sql:link-file-to-library file-id library-id])) ;; --- Mutation: Unlink file from library diff --git a/backend/src/app/services/mutations/media.clj b/backend/src/app/services/mutations/media.clj index 1d12c8e8ed..3dd65fb9b5 100644 --- a/backend/src/app/services/mutations/media.clj +++ b/backend/src/app/services/mutations/media.clj @@ -38,7 +38,6 @@ (s/def ::team-id ::us/uuid) (s/def ::url ::us/url) - ;; --- Create Media object (Upload and create from url) (declare create-media-object) diff --git a/backend/src/app/tasks/delete_object.clj b/backend/src/app/tasks/delete_object.clj index e097765578..7bc9874a09 100644 --- a/backend/src/app/tasks/delete_object.clj +++ b/backend/src/app/tasks/delete_object.clj @@ -55,13 +55,3 @@ [conn {:keys [id] :as props}] (let [sql "delete from media_object where id=? and deleted_at is not null"] (db/exec-one! conn [sql id]))) - -(defmethod handle-deletion :color - [conn {:keys [id] :as props}] - (let [sql "delete from color where id=? and deleted_at is not null"] - (db/exec-one! conn [sql id]))) - -(defmethod handle-deletion :page - [conn {:keys [id] :as props}] - (let [sql "delete from page where id=? and deleted_at is not null"] - (db/exec-one! conn [sql id]))) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 70fe89a886..6e8e66715a 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -287,51 +287,28 @@ ;; --- Link and unlink Files -(declare file-linked) - (defn link-file-to-library [file-id library-id] (ptk/reify ::link-file-to-library ptk/WatchEvent (watch [_ state stream] - (let [params {:file-id file-id - :library-id library-id}] - (->> (->> (rp/mutation :link-file-to-library params) - (rx/mapcat - #(rx/zip (rp/query :file-library {:file-id library-id}) - (rp/query :media-objects {:file-id library-id - :is-local false})))) - (rx/map file-linked)))))) - -(defn file-linked - [[library media-objects colors]] - (ptk/reify ::file-linked - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:workspace-libraries (:id library)] - (assoc library - :media-objects media-objects - :colors colors))))) - -(declare file-unlinked) + (let [fetched #(assoc-in %2 [:workspace-libraries (:id %1)] %1) + params {:file-id file-id + :library-id library-id}] + (->> (rp/mutation :link-file-to-library params) + (rx/mapcat #(rp/query :file {:id library-id})) + (rx/map #(partial fetched %))))))) (defn unlink-file-from-library [file-id library-id] (ptk/reify ::unlink-file-from-library ptk/WatchEvent (watch [_ state stream] - (let [params {:file-id file-id - :library-id library-id}] + (let [unlinked #(d/dissoc-in % [:workspace-libraries library-id]) + params {:file-id file-id + :library-id library-id}] (->> (rp/mutation :unlink-file-from-library params) - (rx/map #(file-unlinked file-id library-id))))))) - -(defn file-unlinked - [file-id library-id] - (ptk/reify ::file-unlinked - ptk/UpdateEvent - (update [_ state] - (d/dissoc-in state [:workspace-libraries library-id])))) - + (rx/map (constantly unlinked))))))) ;; --- Fetch Pages From f5967c3c0aa136b42090bd326199110aa5ffbcdb Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 17:28:02 +0100 Subject: [PATCH 027/195] :fire: Add a migration for remove unused tables. --- backend/src/app/migrations.clj | 3 +++ backend/src/app/migrations/sql/0032-del-unused-tables.sql | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 backend/src/app/migrations/sql/0032-del-unused-tables.sql diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index 54fa2a50da..0936f6c5e2 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -110,6 +110,9 @@ {:name "0031-add-conversation-related-tables" :fn (mg/resource "app/migrations/sql/0031-add-conversation-related-tables.sql")} + + {:name "0032-del-unused-tables" + :fn (mg/resource "app/migrations/sql/0032-del-unused-tables.sql")} ]}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/backend/src/app/migrations/sql/0032-del-unused-tables.sql b/backend/src/app/migrations/sql/0032-del-unused-tables.sql new file mode 100644 index 0000000000..f6333939e8 --- /dev/null +++ b/backend/src/app/migrations/sql/0032-del-unused-tables.sql @@ -0,0 +1,3 @@ +DROP TABLE color; +DROP TABLE page_change; +DROP TABLE page_version; From 6800adfaa46f35bdd7fae379bd8e95a00551be3b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 17:28:32 +0100 Subject: [PATCH 028/195] :books: Add some documentation comments to some tasks. --- backend/src/app/tasks/maintenance.clj | 3 +++ backend/src/app/tasks/remove_media.clj | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/backend/src/app/tasks/maintenance.clj b/backend/src/app/tasks/maintenance.clj index c8a622021d..be344a5e9a 100644 --- a/backend/src/app/tasks/maintenance.clj +++ b/backend/src/app/tasks/maintenance.clj @@ -22,6 +22,9 @@ ;; Task: Delete Executed Tasks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This tasks perform a cleanup of already executed tasks from the +;; database. + (s/def ::max-age ::dt/duration) (s/def ::delete-completed-tasks (s/keys :req-un [::max-age])) diff --git a/backend/src/app/tasks/remove_media.clj b/backend/src/app/tasks/remove_media.clj index f6d39df4ac..e4020e081b 100644 --- a/backend/src/app/tasks/remove_media.clj +++ b/backend/src/app/tasks/remove_media.clj @@ -22,6 +22,10 @@ ;; Task: Remove Media ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Task responsible of explicit action of removing a media from file +;; system. Mainly used for profile photo change; when we really know +;; that the previous photo becomes unused. + (s/def ::path ::us/not-empty-string) (s/def ::props (s/keys :req-un [::path])) From fa0e0af5b9aff85193ba0d6ade3b469515f06059 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 19 Nov 2020 17:29:00 +0100 Subject: [PATCH 029/195] :sparkles: Simplify trim-file task implementation. --- backend/src/app/tasks/trim_file.clj | 32 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/backend/src/app/tasks/trim_file.clj b/backend/src/app/tasks/trim_file.clj index b95888440f..80608726ad 100644 --- a/backend/src/app/tasks/trim_file.clj +++ b/backend/src/app/tasks/trim_file.clj @@ -39,23 +39,27 @@ limit 10") (defn retrieve-candidates + "Retrieves a list of ids of files that are candidates to be trimed. A + file is considered candidate when some time passes whith no + modification." [conn] (let [interval (:file-trimming-max-age cfg/config)] (->> (db/exec! conn [sql:retrieve-files-to-trim interval]) (map :id)))) + +(def collect-media-xf + (comp (map :data) + (map :objects) + (mapcat vals) + (filter #(= :image (:type %))) + (map :metadata) + (map :id))) + + (defn collect-used-media [pages] - (let [xf (comp (filter #(= :image (:type %))) - (map :metadata) - (map :id))] - (reduce conj #{} (->> pages - (map :data) - (map :objects) - (mapcat vals) - (filter #(= :image (:type %))) - (map :metadata) - (map :id))))) + (into #{} collect-media-xf pages)) (defn process-file [file-id] @@ -64,17 +68,17 @@ (let [mobjs (db/query conn :media-object {:file-id file-id}) pages (->> (db/query conn :page {:file-id file-id}) (map decode-row)) - used (collect-used-media pages) - unused (into #{} (comp (map :id) - (remove #(contains? used %))) mobjs)] + used (into #{} collect-media-xf pages) + unused (into #{} (comp (map :id) (remove #(contains? used %))) mobjs)] + (log/debugf "Collected media ids: '%s'." (pr-str used)) (log/debugf "Unused media ids: '%s'." (pr-str unused)) - (db/update! conn :file {:has-media-trimmed true} {:id file-id}) (doseq [id unused] + ;; TODO: add task batching (tasks/submit! conn {:name "delete-object" ;; :delay cfg/default-deletion-delay :delay 10000 From 420294aef46bd89f565589d71d9218814509aac2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 09:48:09 +0100 Subject: [PATCH 030/195] :bug: Properly redirect to login on unauthorized request. --- frontend/src/app/main/ui.cljs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index fa0ae92d32..0783ebca12 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -33,6 +33,7 @@ [app.main.ui.workspace :as workspace] [app.util.i18n :as i18n :refer [tr t]] [app.util.timers :as ts] + [app.util.router :as rt] [cuerdas.core :as str] [cljs.spec.alpha :as s] [expound.alpha :as expound] @@ -222,8 +223,10 @@ (defmethod ptk/handle-error :authorization [error] + (st/emit! (rt/nav :login)) (ts/schedule (st/emitf (dm/show {:content "Not authorized to see this content." + :timeout 5000 :type :error})))) (defmethod ptk/handle-error :assertion From 742af4e0669a8f9995666a5840a0d08f8ce5ddc9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sat, 21 Nov 2020 00:14:59 +0100 Subject: [PATCH 031/195] :tada: Add comments to dashboard. --- backend/src/app/migrations.clj | 3 + .../sql/0033-mod-comment-thread-table.sql | 2 + .../src/app/services/mutations/comments.clj | 43 +- backend/src/app/services/queries/comments.clj | 61 ++- backend/src/app/services/queries/files.clj | 19 +- backend/src/app/services/queries/teams.clj | 35 ++ frontend/gulpfile.js | 27 +- frontend/package.json | 1 + frontend/resources/images/icons/comment.svg | 4 + frontend/resources/locales.json | 435 ++++++++++-------- .../polyfills/scrollIntoViewIfNeeded.js | 27 ++ frontend/resources/styles/main-default.scss | 2 +- .../styles/main/layouts/main-layout.scss | 2 +- ...{workspace-comments.scss => comments.scss} | 225 ++++++--- .../main/partials/dashboard-sidebar.scss | 44 +- frontend/resources/templates/index.mustache | 1 + frontend/src/app/main/data/comments.cljs | 58 ++- frontend/src/app/main/data/dashboard.cljs | 30 +- frontend/src/app/main/data/users.cljs | 4 +- .../src/app/main/data/workspace/comments.cljs | 23 +- frontend/src/app/main/refs.cljs | 3 + frontend/src/app/main/ui/comments.cljs | 74 ++- .../src/app/main/ui/dashboard/comments.cljs | 104 +++++ .../src/app/main/ui/dashboard/sidebar.cljs | 37 +- frontend/src/app/main/ui/viewer.cljs | 4 +- .../src/app/main/ui/workspace/comments.cljs | 109 ++--- frontend/src/app/util/avatars.cljs | 13 +- frontend/yarn.lock | 16 + 28 files changed, 968 insertions(+), 438 deletions(-) create mode 100644 backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql create mode 100644 frontend/resources/images/icons/comment.svg create mode 100644 frontend/resources/polyfills/scrollIntoViewIfNeeded.js rename frontend/resources/styles/main/partials/{workspace-comments.scss => comments.scss} (67%) create mode 100644 frontend/src/app/main/ui/dashboard/comments.cljs diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index 0936f6c5e2..6c9ebdba2d 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -113,6 +113,9 @@ {:name "0032-del-unused-tables" :fn (mg/resource "app/migrations/sql/0032-del-unused-tables.sql")} + + {:name "0033-mod-comment-thread-table" + :fn (mg/resource "app/migrations/sql/0033-mod-comment-thread-table.sql")} ]}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql b/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql new file mode 100644 index 0000000000..0e98ef6d1a --- /dev/null +++ b/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql @@ -0,0 +1,2 @@ +ALTER TABLE comment_thread + ADD COLUMN page_name text NULL; diff --git a/backend/src/app/services/mutations/comments.clj b/backend/src/app/services/mutations/comments.clj index af798bb073..8fd4ce4f7a 100644 --- a/backend/src/app/services/mutations/comments.clj +++ b/backend/src/app/services/mutations/comments.clj @@ -29,12 +29,13 @@ (declare upsert-comment-thread-status!) (declare create-comment-thread) +(declare retrieve-page-name) +(s/def ::page-id ::us/uuid) (s/def ::file-id ::us/uuid) (s/def ::profile-id ::us/uuid) (s/def ::position ::us/point) (s/def ::content ::us/string) -(s/def ::page-id ::us/uuid) (s/def ::create-comment-thread (s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id])) @@ -53,13 +54,14 @@ (defn- create-comment-thread* [conn {:keys [profile-id file-id page-id position content] :as params}] - (let [seqn (retrieve-next-seqn conn file-id) - now (dt/now) - + (let [seqn (retrieve-next-seqn conn file-id) + now (dt/now) + pname (retrieve-page-name conn params) thread (db/insert! conn :comment-thread {:file-id file-id :owner-id profile-id :participants (db/tjson #{profile-id}) + :page-name pname :page-id page-id :created-at now :modified-at now @@ -81,10 +83,7 @@ {:comment-thread-seqn seqn} {:id file-id}) - (-> (assoc thread - :content content - :comment comment) - (comments/decode-row)))) + (select-keys thread [:id :file-id :page-id]))) (defn- create-comment-thread [conn params] @@ -104,6 +103,12 @@ :else res)))) +(defn- retrieve-page-name + [conn {:keys [file-id page-id]}] + (let [{:keys [data]} (db/get-by-id conn :file file-id) + data (blob/decode data)] + (get-in data [:pages-index page-id :name]))) + ;; --- Mutation: Update Comment Thread Status @@ -164,14 +169,21 @@ [{:keys [profile-id thread-id content] :as params}] (db/with-atomic [conn db/pool] (let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true}) - (comments/decode-row))] + (comments/decode-row)) + pname (retrieve-page-name conn thread)] ;; Standard Checks - (when-not thread - (ex/raise :type :not-found)) + (when-not thread (ex/raise :type :not-found)) + ;; Permission Checks (files/check-read-permissions! conn profile-id (:file-id thread)) + ;; Update the page-name cachedattribute on comment thread table. + (when (not= pname (:page-name thread)) + (db/update! conn :comment-thread + {:page-name pname} + {:id thread-id})) + ;; NOTE: is important that all timestamptz related fields are ;; created or updated on the database level for avoid clock ;; inconsistencies (some user sees something read that is not @@ -216,15 +228,19 @@ (let [comment (db/get-by-id conn :comment id {:for-update true}) _ (when-not comment (ex/raise :type :not-found)) thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true}) - _ (when-not thread (ex/raise :type :not-found))] + _ (when-not thread (ex/raise :type :not-found)) + pname (retrieve-page-name conn thread)] (files/check-read-permissions! conn profile-id (:file-id thread)) + (db/update! conn :comment {:content content :modified-at (dt/now)} {:id (:id comment)}) + (db/update! conn :comment-thread - {:modified-at (dt/now)} + {:modified-at (dt/now) + :page-name pname} {:id (:id thread)}) nil))) @@ -244,6 +260,7 @@ (db/delete! conn :comment-thread {:id id}) nil))) + ;; --- Mutation: Delete comment (s/def ::delete-comment diff --git a/backend/src/app/services/queries/comments.clj b/backend/src/app/services/queries/comments.clj index 5b000b2123..4d2d569b34 100644 --- a/backend/src/app/services/queries/comments.clj +++ b/backend/src/app/services/queries/comments.clj @@ -16,6 +16,7 @@ [app.db :as db] [app.services.queries :as sq] [app.services.queries.files :as files] + [app.services.queries.teams :as teams] [app.util.time :as dt] [app.util.transit :as t] [clojure.spec.alpha :as s] @@ -32,9 +33,13 @@ (declare retrieve-comment-threads) +(s/def ::team-id ::us/uuid) (s/def ::file-id ::us/uuid) + (s/def ::comment-threads - (s/keys :req-un [::profile-id ::file-id])) + (s/and (s/keys :req-un [::profile-id] + :opt-un [::file-id ::team-id]) + #(or (:file-id %) (:team-id %)))) (sq/defquery ::comment-threads [{:keys [profile-id file-id] :as params}] @@ -45,6 +50,8 @@ (def sql:comment-threads "select distinct on (ct.id) ct.*, + f.name as file_name, + f.project_id as project_id, first_value(c.content) over w as content, (select count(1) from comment as c @@ -55,6 +62,7 @@ and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments from comment_thread as ct inner join comment as c on (c.thread_id = ct.id) + inner join file as f on (f.id = ct.file_id) left join comment_thread_status as cts on (cts.thread_id = ct.id and cts.profile_id = ?) @@ -62,10 +70,59 @@ window w as (partition by c.thread_id order by c.created_at asc)") (defn- retrieve-comment-threads - [conn {:keys [profile-id file-id]}] + [conn {:keys [profile-id file-id team-id]}] + (files/check-read-permissions! conn profile-id file-id) (->> (db/exec! conn [sql:comment-threads profile-id file-id]) (into [] (map decode-row)))) + +;; --- Query: Unread Comment Threads + +(declare retrieve-unread-comment-threads) + +(s/def ::team-id ::us/uuid) +(s/def ::unread-comment-threads + (s/keys :req-un [::profile-id ::team-id])) + +(sq/defquery ::unread-comment-threads + [{:keys [profile-id team-id] :as params}] + (with-open [conn (db/open)] + (teams/check-read-permissions! conn profile-id team-id) + (retrieve-unread-comment-threads conn params))) + +(def sql:comment-threads-by-team + "select distinct on (ct.id) + ct.*, + f.name as file_name, + f.project_id as project_id, + first_value(c.content) over w as content, + (select count(1) + from comment as c + where c.thread_id = ct.id) as count_comments, + (select count(1) + from comment as c + where c.thread_id = ct.id + and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments + from comment_thread as ct + inner join comment as c on (c.thread_id = ct.id) + inner join file as f on (f.id = ct.file_id) + inner join project as p on (p.id = f.project_id) + left join comment_thread_status as cts + on (cts.thread_id = ct.id and + cts.profile_id = ?) + where p.team_id = ? + window w as (partition by c.thread_id order by c.created_at asc)") + +(def sql:unread-comment-threads-by-team + (str "with threads as (" sql:comment-threads-by-team ")" + "select * from threads where count_unread_comments > 0")) + +(defn retrieve-unread-comment-threads + [conn {:keys [profile-id team-id]}] + (->> (db/exec! conn [sql:unread-comment-threads-by-team profile-id team-id]) + (into [] (map decode-row)))) + + ;; --- Query: Single Comment Thread (s/def ::id ::us/uuid) diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index 2f8edc3155..12b2764ea2 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -193,6 +193,12 @@ inner join file_profile_rel as fpr on (fpr.profile_id = pf.id) where fpr.file_id = ? union + select pf.id, pf.fullname, pf.photo + from profile as pf + inner join project_profile_rel as ppr on (ppr.profile_id = pf.id) + inner join file as f on (f.project_id = ppr.project_id) + where f.id = ? + union select pf.id, pf.fullname, pf.photo from profile as pf inner join team_profile_rel as tpr on (tpr.profile_id = pf.id) @@ -202,7 +208,7 @@ (defn retrieve-file-users [conn id] - (db/exec! conn [sql:file-users id id])) + (db/exec! conn [sql:file-users id id id])) (s/def ::file-users (s/keys :req-un [::profile-id ::id])) @@ -215,17 +221,8 @@ ;; --- Query: Shared Library Files -;; TODO: remove the counts, because they are no longer needed. - (def ^:private sql:shared-files - "select f.*, - (select count(*) from color as c - where c.file_id = f.id - and c.deleted_at is null) as colors_count, - (select count(*) from media_object as m - where m.file_id = f.id - and m.is_local = false - and m.deleted_at is null) as graphics_count + "select f.* from file as f inner join project as p on (p.id = f.project_id) where f.is_shared = true diff --git a/backend/src/app/services/queries/teams.clj b/backend/src/app/services/queries/teams.clj index cddd8b5ab8..594ba5633b 100644 --- a/backend/src/app/services/queries/teams.clj +++ b/backend/src/app/services/queries/teams.clj @@ -130,3 +130,38 @@ (defn retrieve-team-members [conn team-id] (db/exec! conn [sql:team-members team-id])) + +;; --- Query: Team Users + +;; This is a similar query to team members but can contain more data +;; because some user can be explicitly added to project or file (not +;; implemented in UI) + +(def sql:team-users + "select pf.id, pf.fullname, pf.photo + from profile as pf + inner join team_profile_rel as tpr on (tpr.profile_id = pf.id) + where tpr.team_id = ? + union + select pf.id, pf.fullname, pf.photo + from profile as pf + inner join project_profile_rel as ppr on (ppr.profile_id = pf.id) + inner join project as p on (ppr.project_id = p.id) + where p.team_id = ? + union + select pf.id, pf.fullname, pf.photo + from profile as pf + inner join file_profile_rel as fpr on (fpr.profile_id = pf.id) + inner join file as f on (fpr.file_id = f.id) + inner join project as p on (f.project_id = p.id) + where p.team_id = ?") + +(s/def ::team-users + (s/keys :req-un [::profile-id ::team-id])) + +(sq/defquery ::team-users + [{:keys [profile-id team-id]}] + (with-open [conn (db/open)] + (check-edition-permissions! conn profile-id team-id) + (db/exec! conn [sql:team-users team-id team-id team-id]))) + diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js index 11a4c8a6bb..c962a72da2 100644 --- a/frontend/gulpfile.js +++ b/frontend/gulpfile.js @@ -1,20 +1,21 @@ const fs = require("fs"); -const path = require("path"); const l = require("lodash"); +const path = require("path"); const gulp = require("gulp"); -const gulpSass = require("gulp-sass"); +const gulpConcat = require("gulp-concat"); const gulpGzip = require("gulp-gzip"); const gulpMustache = require("gulp-mustache"); -const gulpRename = require("gulp-rename"); -const svgSprite = require("gulp-svg-sprite"); const gulpPostcss = require("gulp-postcss"); +const gulpRename = require("gulp-rename"); +const gulpSass = require("gulp-sass"); +const svgSprite = require("gulp-svg-sprite"); +const autoprefixer = require("autoprefixer") +const clean = require("postcss-clean"); const mkdirp = require("mkdirp"); const rimraf = require("rimraf"); const sass = require("sass"); -const autoprefixer = require("autoprefixer") -const clean = require("postcss-clean"); const mapStream = require("map-stream"); const paths = {}; @@ -52,7 +53,8 @@ function readManifest() { const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"})); const index = { - "config": "/js/config.js?ts=" + Date.now() + "config": "/js/config.js?ts=" + Date.now(), + "polyfills": "js/polyfills.js?ts=" + Date.now(), }; for (let item of content) { @@ -64,6 +66,7 @@ function readManifest() { console.error("Error on reading manifest, using default."); return { "config": "/js/config.js", + "polyfills": "js/polyfills.js", "main": "/js/main.js", "shared": "/js/shared.js", "worker": "/js/worker.js" @@ -123,7 +126,7 @@ gulp.task("scss", function() { .pipe(gulpSass().on('error', gulpSass.logError)) .pipe(gulpPostcss([ autoprefixer, - clean({format: "keep-breaks", level: 1}) + // clean({format: "keep-breaks", level: 1}) ])) .pipe(gulp.dest(paths.output + "css/")); }); @@ -142,6 +145,12 @@ gulp.task("template:main", templatePipeline({ gulp.task("templates", gulp.series("svg:sprite", "template:main")); +gulp.task("polyfills", function() { + return gulp.src(paths.resources + "polyfills/*.js") + .pipe(gulpConcat("polyfills.js")) + .pipe(gulp.dest(paths.output + "js/")); +}); + /*********************************************** * Development ***********************************************/ @@ -177,7 +186,7 @@ gulp.task("watch:main", function() { gulp.series("templates")); }); -gulp.task("build", gulp.parallel("scss", "templates", "copy:assets")); +gulp.task("build", gulp.parallel("polyfills", "scss", "templates", "copy:assets")); gulp.task("watch", gulp.series("dev:dirs", "build", "watch:main")); /*********************************************** diff --git a/frontend/package.json b/frontend/package.json index 10098e8587..2bffc5c7ab 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,6 +15,7 @@ "devDependencies": { "autoprefixer": "^10.0.1", "gulp": "4.0.2", + "gulp-concat": "^2.6.1", "gulp-gzip": "^1.4.2", "gulp-mustache": "^5.0.0", "gulp-postcss": "^9.0.0", diff --git a/frontend/resources/images/icons/comment.svg b/frontend/resources/images/icons/comment.svg new file mode 100644 index 0000000000..f6c098e081 --- /dev/null +++ b/frontend/resources/images/icons/comment.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 0c1951a894..f08ce41e82 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -18,7 +18,7 @@ } }, "auth.create-demo-account" : { - "used-in" : [ "src/app/main/ui/auth/login.cljs:147" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:136", "src/app/main/ui/auth/login.cljs:147" ], "translations" : { "en" : "Create demo account", "fr" : "Vous voulez juste essayer?", @@ -27,7 +27,7 @@ } }, "auth.create-demo-profile" : { - "used-in" : [ "src/app/main/ui/auth/login.cljs:144", "src/app/main/ui/auth/register.cljs:133", "src/app/main/ui/auth/register.cljs:136" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:133", "src/app/main/ui/auth/login.cljs:144" ], "translations" : { "en" : "Just wanna try it?", "fr" : "Vous voulez juste essayer?", @@ -45,7 +45,7 @@ } }, "auth.email" : { - "used-in" : [ "src/app/main/ui/auth/login.cljs:92", "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47", "src/app/main/ui/auth/login.cljs:92" ], "translations" : { "en" : "Email", "fr" : "Adresse email", @@ -186,7 +186,7 @@ } }, "auth.password" : { - "used-in" : [ "src/app/main/ui/auth/login.cljs:99", "src/app/main/ui/auth/register.cljs:106" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:106", "src/app/main/ui/auth/login.cljs:99" ], "translations" : { "en" : "Password", "fr" : "Mot de passe", @@ -249,7 +249,7 @@ } }, "auth.register-submit" : { - "used-in" : [ "src/app/main/ui/auth/login.cljs:128", "src/app/main/ui/auth/register.cljs:110" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:110", "src/app/main/ui/auth/login.cljs:128" ], "translations" : { "en" : "Create an account", "fr" : "Créer un compte", @@ -303,20 +303,20 @@ } }, "dashboard.create-new-team" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:155" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:159" ], "translations" : { "en" : "+ Create new team", "es" : "+ Crear nuevo equipo" } }, "dashboard.default-team-name" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:325" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:329" ], "translations" : { "en" : "Your penpot" } }, "dashboard.delete-team" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:309" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:313" ], "translations" : { "en" : "Delete team" } @@ -340,14 +340,14 @@ } }, "dashboard.invite-profile" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:69" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:72" ], "translations" : { "en" : "Invite to team", "es" : "Invitar al equipo" } }, "dashboard.leave-team" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:302", "src/app/main/ui/dashboard/sidebar.cljs:305" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:306", "src/app/main/ui/dashboard/sidebar.cljs:309" ], "translations" : { "en" : "Leave team" } @@ -470,7 +470,7 @@ } }, "dashboard.no-projects-placeholder" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:423" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:424" ], "translations" : { "en" : "Pinned projects will appear here" } @@ -503,7 +503,7 @@ } }, "dashboard.num-of-members" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:291" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:294" ], "translations" : { "en" : "%s members" } @@ -527,7 +527,7 @@ } }, "dashboard.promote-to-owner" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:193" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:196" ], "translations" : { "en" : "Promote to owner" } @@ -551,7 +551,7 @@ } }, "dashboard.search-placeholder" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:110" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:113" ], "translations" : { "en" : "Search...", "fr" : "Rechercher...", @@ -603,25 +603,25 @@ "unused" : true }, "dashboard.switch-team" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:140" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:144" ], "translations" : { "en" : "Switch Team" } }, "dashboard.team-info" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:274" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:277" ], "translations" : { "en" : "Team info" } }, "dashboard.team-members" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:285" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:288" ], "translations" : { "en" : "Team members" } }, "dashboard.team-projects" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:294" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:297" ], "translations" : { "en" : "Team projects" } @@ -645,7 +645,7 @@ } }, "dashboard.update-settings" : { - "used-in" : [ "src/app/main/ui/settings/options.cljs:72", "src/app/main/ui/settings/profile.cljs:80", "src/app/main/ui/settings/password.cljs:96" ], + "used-in" : [ "src/app/main/ui/settings/profile.cljs:80", "src/app/main/ui/settings/password.cljs:96", "src/app/main/ui/settings/options.cljs:72" ], "translations" : { "en" : "Update settings", "fr" : "Mettre à jour les paramètres", @@ -679,7 +679,7 @@ } }, "dashboard.your-penpot" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:144" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:148" ], "translations" : { "en" : "Your penpot" } @@ -766,7 +766,7 @@ } }, "errors.email-already-exists" : { - "used-in" : [ "src/app/main/ui/settings/change_email.cljs:47", "src/app/main/ui/auth/verify_token.cljs:80" ], + "used-in" : [ "src/app/main/ui/auth/verify_token.cljs:80", "src/app/main/ui/settings/change_email.cljs:47" ], "translations" : { "en" : "Email already used", "fr" : "Adresse e-mail déjà utilisée", @@ -793,7 +793,7 @@ } }, "errors.generic" : { - "used-in" : [ "src/app/main/ui/settings/options.cljs:32", "src/app/main/ui/settings/profile.cljs:40", "src/app/main/ui/auth/verify_token.cljs:89" ], + "used-in" : [ "src/app/main/ui/auth/verify_token.cljs:89", "src/app/main/ui/settings/profile.cljs:40", "src/app/main/ui/settings/options.cljs:32" ], "translations" : { "en" : "Something wrong has happened.", "fr" : "Quelque chose c'est mal passé.", @@ -820,7 +820,7 @@ } }, "errors.media-type-mismatch" : { - "used-in" : [ "src/app/main/data/media.cljs:61", "src/app/main/data/workspace/persistence.cljs:421" ], + "used-in" : [ "src/app/main/data/workspace/persistence.cljs:390", "src/app/main/data/media.cljs:61" ], "translations" : { "en" : "Seems that the contents of the image does not match the file extension.", "fr" : "", @@ -829,7 +829,7 @@ } }, "errors.media-type-not-allowed" : { - "used-in" : [ "src/app/main/data/media.cljs:58", "src/app/main/data/workspace/persistence.cljs:418" ], + "used-in" : [ "src/app/main/data/workspace/persistence.cljs:387", "src/app/main/data/media.cljs:58" ], "translations" : { "en" : "Seems that this is not a valid image.", "fr" : "", @@ -874,7 +874,7 @@ } }, "errors.unexpected-error" : { - "used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66" ], + "used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/handoff/exports.cljs:41" ], "translations" : { "en" : "An unexpected error occurred.", "fr" : "Une erreur inattendue c'est produite", @@ -901,31 +901,31 @@ } }, "handoff.attributes.blur" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/blur.cljs:33" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/blur.cljs:34" ], "translations" : { "en" : "Blur" } }, "handoff.attributes.blur.value" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/blur.cljs:39" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/blur.cljs:40" ], "translations" : { "en" : "Value" } }, "handoff.attributes.color.hex" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:72" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:70" ], "translations" : { "en" : "HEX" } }, "handoff.attributes.color.hsla" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:78" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:76" ], "translations" : { "en" : "HSLA" } }, "handoff.attributes.color.rgba" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:75" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:73" ], "translations" : { "en" : "RGBA" } @@ -937,97 +937,97 @@ "unused" : true }, "handoff.attributes.fill" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/fill.cljs:58" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/fill.cljs:57" ], "translations" : { "en" : "Fill" } }, "handoff.attributes.image.download" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:44" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:45" ], "translations" : { "en" : "Dowload source image" } }, "handoff.attributes.image.height" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:36" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:37" ], "translations" : { "en" : "Height" } }, "handoff.attributes.image.width" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:31" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:32" ], "translations" : { "en" : "Width" } }, "handoff.attributes.layout" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:76" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:76" ], "translations" : { "en" : "Layout" } }, "handoff.attributes.layout.height" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:36" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:43" ], "translations" : { "en" : "Height" } }, "handoff.attributes.layout.left" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:44" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:49" ], "translations" : { "en" : "Left" } }, "handoff.attributes.layout.radius" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:60" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:61" ], "translations" : { "en" : "Radius" } }, "handoff.attributes.layout.rotation" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:60" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:67" ], "translations" : { "en" : "Rotation" } }, "handoff.attributes.layout.top" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:52" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:55" ], "translations" : { "en" : "Top" } }, "handoff.attributes.layout.width" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:29" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:38" ], "translations" : { "en" : "Width" } }, "handoff.attributes.shadow" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:71" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:71" ], "translations" : { "en" : "Shadow" } }, "handoff.attributes.shadow.shorthand.blur" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:44" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:53" ], "translations" : { "en" : "B" } }, "handoff.attributes.shadow.shorthand.offset-x" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:36" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:45" ], "translations" : { "en" : "X" } }, "handoff.attributes.shadow.shorthand.offset-y" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:40" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:49" ], "translations" : { "en" : "Y" } }, "handoff.attributes.shadow.shorthand.spread" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:48" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:57" ], "translations" : { "en" : "S" } @@ -1045,7 +1045,7 @@ "unused" : true }, "handoff.attributes.stroke" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/stroke.cljs:75" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/stroke.cljs:75" ], "translations" : { "en" : "Stroke" } @@ -1099,49 +1099,49 @@ "unused" : true }, "handoff.attributes.stroke.width" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/stroke.cljs:57" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/stroke.cljs:63" ], "translations" : { "en" : "Width" } }, "handoff.attributes.typography" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:159" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:190" ], "translations" : { "en" : "Typography" } }, "handoff.attributes.typography.font-family" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:89" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:121" ], "translations" : { "en" : "Font Family" } }, "handoff.attributes.typography.font-size" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:101" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:133" ], "translations" : { "en" : "Font Size" } }, "handoff.attributes.typography.font-style" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:95" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:127" ], "translations" : { "en" : "Font Style" } }, "handoff.attributes.typography.letter-spacing" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:113" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:145" ], "translations" : { "en" : "Letter Spacing" } }, "handoff.attributes.typography.line-height" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:107" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:139" ], "translations" : { "en" : "Line Height" } }, "handoff.attributes.typography.text-decoration" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:119" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:151" ], "translations" : { "en" : "Text Decoration" } @@ -1165,7 +1165,7 @@ "unused" : true }, "handoff.attributes.typography.text-transform" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:125" ], + "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:157" ], "translations" : { "en" : "Text Transform" } @@ -1195,7 +1195,7 @@ "unused" : true }, "handoff.tabs.code" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:78" ], + "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:65" ], "translations" : { "en" : "Code" } @@ -1231,7 +1231,7 @@ "unused" : true }, "handoff.tabs.code.selected.multiple" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:65" ], + "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:48" ], "translations" : { "en" : "%s Selected" } @@ -1255,7 +1255,7 @@ "unused" : true }, "handoff.tabs.info" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:74" ], + "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:59" ], "translations" : { "en" : "Info" } @@ -1270,13 +1270,13 @@ "unused" : true }, "labels.admin" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:82", "src/app/main/ui/dashboard/team.cljs:171", "src/app/main/ui/dashboard/team.cljs:187" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:85", "src/app/main/ui/dashboard/team.cljs:174", "src/app/main/ui/dashboard/team.cljs:190" ], "translations" : { "en" : "Admin" } }, "labels.cancel" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:199" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:203" ], "translations" : { "en" : "Cancel", "fr" : "Annuler", @@ -1284,6 +1284,12 @@ "es" : "Cancelar" } }, + "labels.comments" : { + "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:75" ], + "translations" : { + "en" : "Comments" + } + }, "labels.confirm-password" : { "used-in" : [ "src/app/main/ui/settings/password.cljs:93" ], "translations" : { @@ -1300,7 +1306,7 @@ } }, "labels.delete" : { - "used-in" : [ "src/app/main/ui/dashboard/files.cljs:85", "src/app/main/ui/dashboard/grid.cljs:177" ], + "used-in" : [ "src/app/main/ui/dashboard/grid.cljs:177", "src/app/main/ui/dashboard/files.cljs:85" ], "translations" : { "en" : "Delete", "fr" : "Supprimer", @@ -1308,8 +1314,20 @@ "es" : "Borrar" } }, + "labels.delete-comment" : { + "used-in" : [ "src/app/main/ui/comments.cljs:273" ], + "translations" : { + "en" : "Delete comment" + } + }, + "labels.delete-comment-thread" : { + "used-in" : [ "src/app/main/ui/comments.cljs:272" ], + "translations" : { + "en" : "Delete thread" + } + }, "labels.drafts" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:402" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:404" ], "translations" : { "en" : "Drafts", "fr" : "Brouillons", @@ -1317,14 +1335,20 @@ "es" : "Borradores" } }, + "labels.edit" : { + "used-in" : [ "src/app/main/ui/comments.cljs:270" ], + "translations" : { + "en" : "Edit" + } + }, "labels.editor" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:83", "src/app/main/ui/dashboard/team.cljs:174", "src/app/main/ui/dashboard/team.cljs:188" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:86", "src/app/main/ui/dashboard/team.cljs:177", "src/app/main/ui/dashboard/team.cljs:191" ], "translations" : { "en" : "Editor" } }, "labels.email" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:109", "src/app/main/ui/dashboard/team.cljs:212" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:112", "src/app/main/ui/dashboard/team.cljs:215" ], "translations" : { "en" : "Email", "fr" : "Adresse email", @@ -1332,6 +1356,12 @@ "es" : "Correo electrónico" } }, + "labels.hide-resolved-comments" : { + "used-in" : [ "src/app/main/ui/workspace/comments.cljs:129", "src/app/main/ui/viewer/header.cljs:175" ], + "translations" : { + "en" : "Hide resolved comments" + } + }, "labels.language" : { "used-in" : [ "src/app/main/ui/settings/options.cljs:54" ], "translations" : { @@ -1342,7 +1372,7 @@ } }, "labels.logout" : { - "used-in" : [ "src/app/main/ui/settings.cljs:31", "src/app/main/ui/dashboard/sidebar.cljs:457" ], + "used-in" : [ "src/app/main/ui/settings.cljs:31", "src/app/main/ui/dashboard/sidebar.cljs:456" ], "translations" : { "en" : "Logout", "fr" : "Quitter", @@ -1351,13 +1381,13 @@ } }, "labels.members" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:295", "src/app/main/ui/dashboard/team.cljs:59", "src/app/main/ui/dashboard/team.cljs:63" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:60", "src/app/main/ui/dashboard/team.cljs:66", "src/app/main/ui/dashboard/sidebar.cljs:299" ], "translations" : { "en" : "Members" } }, "labels.name" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:211" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:214" ], "translations" : { "en" : "Name", "fr" : "Nom", @@ -1374,6 +1404,12 @@ "es" : "Nueva contraseña" } }, + "labels.no-comments-available" : { + "translations" : { + "en" : "No comments" + }, + "unused" : true + }, "labels.old-password" : { "used-in" : [ "src/app/main/ui/settings/password.cljs:81" ], "translations" : { @@ -1384,13 +1420,13 @@ } }, "labels.owner" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:168" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:171", "src/app/main/ui/dashboard/team.cljs:291" ], "translations" : { "en" : "Owner" } }, "labels.password" : { - "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:75", "src/app/main/ui/dashboard/sidebar.cljs:454" ], + "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:75", "src/app/main/ui/dashboard/sidebar.cljs:453" ], "translations" : { "en" : "Password", "fr" : "Mot de passe", @@ -1399,14 +1435,14 @@ } }, "labels.permissions" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:213" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:216" ], "translations" : { "en" : "Permissions", "es" : "Permisos" } }, "labels.profile" : { - "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:70", "src/app/main/ui/dashboard/sidebar.cljs:451" ], + "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:70", "src/app/main/ui/dashboard/sidebar.cljs:450" ], "translations" : { "en" : "Profile", "fr" : "Profil", @@ -1415,7 +1451,7 @@ } }, "labels.projects" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:397" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:400" ], "translations" : { "en" : "Projects", "fr" : "Projetes", @@ -1424,7 +1460,7 @@ } }, "labels.remove" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:91", "src/app/main/ui/dashboard/team.cljs:199" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:92", "src/app/main/ui/dashboard/team.cljs:202" ], "translations" : { "en" : "Remove", "fr" : "", @@ -1433,20 +1469,20 @@ } }, "labels.rename" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:298", "src/app/main/ui/dashboard/files.cljs:84", "src/app/main/ui/dashboard/grid.cljs:176" ], + "used-in" : [ "src/app/main/ui/dashboard/grid.cljs:176", "src/app/main/ui/dashboard/sidebar.cljs:302", "src/app/main/ui/dashboard/files.cljs:84" ], "translations" : { "en" : "Rename", "es" : "Renombrar" } }, "labels.role" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:81" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:84" ], "translations" : { "en" : "Role" } }, "labels.settings" : { - "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/sidebar.cljs:296", "src/app/main/ui/dashboard/team.cljs:65" ], + "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/team.cljs:61", "src/app/main/ui/dashboard/team.cljs:68", "src/app/main/ui/dashboard/sidebar.cljs:300" ], "translations" : { "en" : "Settings", "fr" : "Settings", @@ -1455,7 +1491,7 @@ } }, "labels.shared-libraries" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:408" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:409" ], "translations" : { "en" : "Shared Libraries", "fr" : "", @@ -1463,6 +1499,18 @@ "es" : "Bibliotecas Compartidas" } }, + "labels.show-all-comments" : { + "used-in" : [ "src/app/main/ui/workspace/comments.cljs:117", "src/app/main/ui/viewer/header.cljs:163" ], + "translations" : { + "en" : "Show all comments" + } + }, + "labels.show-your-comments" : { + "used-in" : [ "src/app/main/ui/workspace/comments.cljs:122", "src/app/main/ui/viewer/header.cljs:168" ], + "translations" : { + "en" : "Show only yours comments" + } + }, "labels.update" : { "used-in" : [ "src/app/main/ui/settings/profile.cljs:106" ], "translations" : { @@ -1473,14 +1521,20 @@ } }, "labels.viewer" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:84", "src/app/main/ui/dashboard/team.cljs:177", "src/app/main/ui/dashboard/team.cljs:189" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:87", "src/app/main/ui/dashboard/team.cljs:180", "src/app/main/ui/dashboard/team.cljs:192" ], "translations" : { "en" : "Viewer", "es" : "Visualizador" } }, + "labels.write-new-comment" : { + "used-in" : [ "src/app/main/ui/comments.cljs:151" ], + "translations" : { + "en" : "Write new comment" + } + }, "media.loading" : { - "used-in" : [ "src/app/main/data/media.cljs:43", "src/app/main/data/workspace/persistence.cljs:402" ], + "used-in" : [ "src/app/main/data/workspace/persistence.cljs:371", "src/app/main/data/media.cljs:43" ], "translations" : { "en" : "Loading image...", "fr" : "Chargement de l'image...", @@ -1606,19 +1660,19 @@ } }, "modals.delete-comment-thread.accept" : { - "used-in" : [ "src/app/main/ui/workspace/comments.cljs:236" ], + "used-in" : [ "src/app/main/ui/comments.cljs:222" ], "translations" : { "en" : "Delete conversation" } }, "modals.delete-comment-thread.message" : { - "used-in" : [ "src/app/main/ui/workspace/comments.cljs:235" ], + "used-in" : [ "src/app/main/ui/comments.cljs:221" ], "translations" : { "en" : "Are you sure you want to delete this conversation? All comments in this thread will be deleted." } }, "modals.delete-comment-thread.title" : { - "used-in" : [ "src/app/main/ui/workspace/comments.cljs:234" ], + "used-in" : [ "src/app/main/ui/comments.cljs:220" ], "translations" : { "en" : "Delete conversation" } @@ -1660,109 +1714,109 @@ } }, "modals.delete-team-confirm.accept" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:285" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:289" ], "translations" : { "en" : "Delete team" } }, "modals.delete-team-confirm.message" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:284" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:288" ], "translations" : { "en" : "Are you sure you want to delete this team? All projects and files associated with team will be permanently deleted." } }, "modals.delete-team-confirm.title" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:283" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:287" ], "translations" : { "en" : "Deleting team" } }, "modals.delete-team-member-confirm.accept" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:157" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:160" ], "translations" : { "en" : "Delete member" } }, "modals.delete-team-member-confirm.message" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:156" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:159" ], "translations" : { "en" : "Are you sure wan't to delete this user from team?" } }, "modals.delete-team-member-confirm.title" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:155" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:158" ], "translations" : { "en" : "Delete team member" } }, "modals.invite-member.title" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:105" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:108" ], "translations" : { "en" : "Invite a new team member" } }, "modals.leave-and-reassign.hint1" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:188" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:192" ], "translations" : { "en" : "You are %s owner." } }, "modals.leave-and-reassign.hint2" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:189" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:193" ], "translations" : { "en" : "Select an other member to promote before leave" } }, "modals.leave-and-reassign.promote-and-leave" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:206" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:210" ], "translations" : { "en" : "Promote and leave" } }, "modals.leave-and-reassign.select-memeber-to-promote" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:166" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:170" ], "translations" : { "en" : "Select a member to promote" } }, "modals.leave-and-reassign.title" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:183" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:187" ], "translations" : { "en" : "Select a member to promote" } }, "modals.leave-confirm.accept" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:260" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:264" ], "translations" : { "en" : "Leave team" } }, "modals.leave-confirm.message" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:259" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:263" ], "translations" : { "en" : "Are you sure you want to leave this team?" } }, "modals.leave-confirm.title" : { - "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:258" ], + "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:262" ], "translations" : { "en" : "Leaving team" } }, "modals.promote-owner-confirm.accept" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:144" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:147" ], "translations" : { "en" : "Promote" } }, "modals.promote-owner-confirm.message" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:143" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:146" ], "translations" : { "en" : "Are you sure you wan't to promote this user to owner?" } }, "modals.promote-owner-confirm.title" : { - "used-in" : [ "src/app/main/ui/dashboard/team.cljs:142" ], + "used-in" : [ "src/app/main/ui/dashboard/team.cljs:145" ], "translations" : { "en" : "Promote to owner" } @@ -1804,7 +1858,7 @@ } }, "notifications.profile-saved" : { - "used-in" : [ "src/app/main/ui/settings/options.cljs:36", "src/app/main/ui/settings/profile.cljs:36" ], + "used-in" : [ "src/app/main/ui/settings/profile.cljs:36", "src/app/main/ui/settings/options.cljs:36" ], "translations" : { "en" : "Profile saved successfully!", "fr" : "Profil enregistré avec succès!", @@ -1813,7 +1867,7 @@ } }, "notifications.validation-email-sent" : { - "used-in" : [ "src/app/main/ui/settings/change_email.cljs:56", "src/app/main/ui/auth/register.cljs:54" ], + "used-in" : [ "src/app/main/ui/auth/register.cljs:54", "src/app/main/ui/settings/change_email.cljs:56" ], "translations" : { "en" : "Verification email sent to %s; check your email!" } @@ -1828,7 +1882,7 @@ } }, "settings.multiple" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/stroke.cljs:147" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:147", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162" ], "translations" : { "en" : "Mixed", "fr" : null, @@ -1855,7 +1909,7 @@ "unused" : true }, "viewer.empty-state" : { - "used-in" : [ "src/app/main/ui/viewer/handoff.cljs:56", "src/app/main/ui/viewer.cljs:42" ], + "used-in" : [ "src/app/main/ui/handoff.cljs:55", "src/app/main/ui/viewer.cljs:193" ], "translations" : { "en" : "No frames found on the page.", "fr" : "Aucun cadre trouvé sur la page.", @@ -1864,7 +1918,7 @@ } }, "viewer.frame-not-found" : { - "used-in" : [ "src/app/main/ui/viewer/handoff.cljs:60", "src/app/main/ui/viewer.cljs:46" ], + "used-in" : [ "src/app/main/ui/handoff.cljs:59", "src/app/main/ui/viewer.cljs:197" ], "translations" : { "en" : "Frame not found.", "fr" : "Cadre introuvable.", @@ -1872,12 +1926,8 @@ "es" : "No se encuentra el tablero." } }, - "labels.show-all-comments": "Show all comments", - "labels.show-your-comments": "Show only yours comments", - "labels.hide-resolved-comments": "Hide resolved comments", - "viewer.header.dont-show-interactions" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:68" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:124" ], "translations" : { "en" : "Don't show interactions", "fr" : "Ne pas afficher les interactions", @@ -1886,7 +1936,7 @@ } }, "viewer.header.edit-page" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:183" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:264" ], "translations" : { "en" : "Edit page", "fr" : "Editer la page", @@ -1895,7 +1945,7 @@ } }, "viewer.header.fullscreen" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:194" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:275" ], "translations" : { "en" : "Full Screen", "fr" : "Plein écran", @@ -1904,7 +1954,7 @@ } }, "viewer.header.share.copy-link" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:113" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:92" ], "translations" : { "en" : "Copy link", "fr" : "Copier lien", @@ -1913,7 +1963,7 @@ } }, "viewer.header.share.create-link" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:122" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:101" ], "translations" : { "en" : "Create link", "fr" : "Créer lien", @@ -1922,7 +1972,7 @@ } }, "viewer.header.share.placeholder" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:114" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:93" ], "translations" : { "en" : "Share link will appear here", "fr" : "Le lien de partage apparaîtra ici", @@ -1931,7 +1981,7 @@ } }, "viewer.header.share.remove-link" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:120" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:99" ], "translations" : { "en" : "Remove link", "fr" : "Supprimer le lien", @@ -1940,7 +1990,7 @@ } }, "viewer.header.share.subtitle" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:116" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:95" ], "translations" : { "en" : "Anyone with the link will have access", "fr" : "Toute personne disposant du lien aura accès", @@ -1949,7 +1999,7 @@ } }, "viewer.header.share.title" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:99", "src/app/main/ui/viewer/header.cljs:101", "src/app/main/ui/viewer/header.cljs:107" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:78", "src/app/main/ui/viewer/header.cljs:80", "src/app/main/ui/viewer/header.cljs:86" ], "translations" : { "en" : "Share link", "fr" : "Lien de partage", @@ -1958,7 +2008,7 @@ } }, "viewer.header.show-interactions" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:72" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:129" ], "translations" : { "en" : "Show interactions", "fr" : "Afficher les interactions", @@ -1967,7 +2017,7 @@ } }, "viewer.header.show-interactions-on-click" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:76" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:134" ], "translations" : { "en" : "Show interactions on click", "fr" : "Afficher les interactions au clic", @@ -1976,7 +2026,7 @@ } }, "viewer.header.sitemap" : { - "used-in" : [ "src/app/main/ui/viewer/header.cljs:156" ], + "used-in" : [ "src/app/main/ui/viewer/header.cljs:223" ], "translations" : { "en" : "Sitemap", "fr" : "Plan du site", @@ -2057,7 +2107,7 @@ } }, "workspace.assets.assets" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:630" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:668" ], "translations" : { "en" : "Assets", "fr" : "", @@ -2066,7 +2116,7 @@ } }, "workspace.assets.box-filter-all" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:650" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:688" ], "translations" : { "en" : "All assets", "fr" : "", @@ -2093,7 +2143,7 @@ "unused" : true }, "workspace.assets.colors" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:330", "src/app/main/ui/workspace/sidebar/assets.cljs:653" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:366", "src/app/main/ui/workspace/sidebar/assets.cljs:691" ], "translations" : { "en" : "Colors", "fr" : "", @@ -2102,7 +2152,7 @@ } }, "workspace.assets.components" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:84", "src/app/main/ui/workspace/sidebar/assets.cljs:651" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:109", "src/app/main/ui/workspace/sidebar/assets.cljs:689" ], "translations" : { "en" : "Components", "fr" : "", @@ -2111,7 +2161,7 @@ } }, "workspace.assets.delete" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:104", "src/app/main/ui/workspace/sidebar/assets.cljs:192", "src/app/main/ui/workspace/sidebar/assets.cljs:306", "src/app/main/ui/workspace/sidebar/assets.cljs:434" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:140", "src/app/main/ui/workspace/sidebar/assets.cljs:228", "src/app/main/ui/workspace/sidebar/assets.cljs:342", "src/app/main/ui/workspace/sidebar/assets.cljs:470" ], "translations" : { "en" : "Delete", "fr" : "", @@ -2120,6 +2170,7 @@ } }, "workspace.assets.duplicate" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:139" ], "translations" : { "en" : "Duplicate", "fr" : "", @@ -2128,7 +2179,7 @@ } }, "workspace.assets.edit" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:305", "src/app/main/ui/workspace/sidebar/assets.cljs:433" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:341", "src/app/main/ui/workspace/sidebar/assets.cljs:469" ], "translations" : { "en" : "Edit", "fr" : "", @@ -2137,7 +2188,7 @@ } }, "workspace.assets.file-library" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:532" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:568" ], "translations" : { "en" : "File library", "fr" : "", @@ -2146,7 +2197,7 @@ } }, "workspace.assets.graphics" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:165", "src/app/main/ui/workspace/sidebar/assets.cljs:652" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:201", "src/app/main/ui/workspace/sidebar/assets.cljs:690" ], "translations" : { "en" : "Graphics", "fr" : "", @@ -2155,7 +2206,7 @@ } }, "workspace.assets.libraries" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:633" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:671" ], "translations" : { "en" : "Libraries", "fr" : "", @@ -2164,7 +2215,7 @@ } }, "workspace.assets.not-found" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:593" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:629" ], "translations" : { "en" : "No assets found", "fr" : "", @@ -2173,7 +2224,7 @@ } }, "workspace.assets.rename" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:304", "src/app/main/ui/workspace/sidebar/assets.cljs:432" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:138", "src/app/main/ui/workspace/sidebar/assets.cljs:340", "src/app/main/ui/workspace/sidebar/assets.cljs:468" ], "translations" : { "en" : "Rename", "fr" : "", @@ -2182,7 +2233,7 @@ } }, "workspace.assets.search" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:637" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:675" ], "translations" : { "en" : "Search assets", "fr" : "", @@ -2191,7 +2242,7 @@ } }, "workspace.assets.shared" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:534" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:570" ], "translations" : { "en" : "SHARED", "fr" : "", @@ -2200,7 +2251,7 @@ } }, "workspace.assets.typography" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:421", "src/app/main/ui/workspace/sidebar/assets.cljs:654" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:457", "src/app/main/ui/workspace/sidebar/assets.cljs:692" ], "translations" : { "en" : "Typographies" } @@ -2242,7 +2293,7 @@ } }, "workspace.assets.typography.sample" : { - "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:65", "src/app/main/ui/workspace/sidebar/options/typography.cljs:255" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/typography.cljs:255", "src/app/main/ui/handoff/attributes/text.cljs:97", "src/app/main/ui/handoff/attributes/text.cljs:106" ], "translations" : { "en" : "Ag" } @@ -2254,13 +2305,13 @@ } }, "workspace.gradients.linear" : { - "used-in" : [ "src/app/main/data/workspace/libraries.cljs:39", "src/app/main/ui/components/color_bullet.cljs:31" ], + "used-in" : [ "src/app/main/data/workspace/libraries.cljs:42", "src/app/main/ui/components/color_bullet.cljs:31" ], "translations" : { "en" : "Linear gradient" } }, "workspace.gradients.radial" : { - "used-in" : [ "src/app/main/data/workspace/libraries.cljs:40", "src/app/main/ui/components/color_bullet.cljs:32" ], + "used-in" : [ "src/app/main/data/workspace/libraries.cljs:43", "src/app/main/ui/components/color_bullet.cljs:32" ], "translations" : { "en" : "Radial gradient" } @@ -2425,7 +2476,7 @@ } }, "workspace.libraries.add" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:115" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:116" ], "translations" : { "en" : "Add", "fr" : "", @@ -2434,7 +2485,7 @@ } }, "workspace.libraries.colors" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:43" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:44" ], "translations" : { "en" : "%s colors", "fr" : "", @@ -2473,7 +2524,7 @@ } }, "workspace.libraries.components" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:37" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:38" ], "translations" : { "en" : "%s components", "fr" : "", @@ -2482,7 +2533,7 @@ } }, "workspace.libraries.file-library" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:84" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:85" ], "translations" : { "en" : "File library", "fr" : "", @@ -2491,7 +2542,7 @@ } }, "workspace.libraries.graphics" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:40" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:41" ], "translations" : { "en" : "%s graphics", "fr" : "", @@ -2500,7 +2551,7 @@ } }, "workspace.libraries.in-this-file" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:81" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:82" ], "translations" : { "en" : "LIBRARIES IN THIS FILE", "fr" : "", @@ -2509,7 +2560,7 @@ } }, "workspace.libraries.libraries" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:175" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:177" ], "translations" : { "en" : "LIBRARIES", "fr" : "", @@ -2518,7 +2569,7 @@ } }, "workspace.libraries.library" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:135" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:136" ], "translations" : { "en" : "LIBRARY", "fr" : "", @@ -2527,7 +2578,7 @@ } }, "workspace.libraries.no-libraries-need-sync" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:133" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:134" ], "translations" : { "en" : "There are no Shared Libraries that need update", "fr" : "", @@ -2536,7 +2587,7 @@ } }, "workspace.libraries.no-matches-for" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:121" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:122" ], "translations" : { "en" : "No matches found for “%s“", "fr" : "Aucune correspondance pour “%s“", @@ -2545,7 +2596,7 @@ } }, "workspace.libraries.no-shared-libraries-available" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:120" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:121" ], "translations" : { "en" : "There are no Shared Libraries available", "fr" : "", @@ -2554,7 +2605,7 @@ } }, "workspace.libraries.search-shared-libraries" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:98" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:99" ], "translations" : { "en" : "Search shared libraries", "fr" : "", @@ -2563,7 +2614,7 @@ } }, "workspace.libraries.shared-libraries" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:95" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:96" ], "translations" : { "en" : "SHARED LIBRARIES", "fr" : "", @@ -2584,13 +2635,13 @@ } }, "workspace.libraries.typography" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:46" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:47" ], "translations" : { "en" : "%s typographies" } }, "workspace.libraries.update" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:142" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:143" ], "translations" : { "en" : "Update", "fr" : "", @@ -2599,7 +2650,7 @@ } }, "workspace.libraries.updates" : { - "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:179" ], + "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:181" ], "translations" : { "en" : "UPDATES", "fr" : "", @@ -2689,6 +2740,7 @@ } }, "workspace.options.component" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:62" ], "translations" : { "en" : "Component", "es" : "Componente" @@ -2704,21 +2756,21 @@ } }, "workspace.options.export" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:123" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:123", "src/app/main/ui/handoff/exports.cljs:96" ], "translations" : { "en" : "Export", "ru" : "Экспорт" } }, "workspace.options.export-object" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:156" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:156", "src/app/main/ui/handoff/exports.cljs:131" ], "translations" : { "en" : "Export shape", "ru" : "Экспорт фигуры" } }, "workspace.options.exporting-object" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:155" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:155", "src/app/main/ui/handoff/exports.cljs:130" ], "translations" : { "en" : "Exporting...", "ru" : "Экспортирую ..." @@ -2959,7 +3011,7 @@ } }, "workspace.options.position" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:127", "src/app/main/ui/workspace/sidebar/options/measures.cljs:146" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:146", "src/app/main/ui/workspace/sidebar/options/frame.cljs:127" ], "translations" : { "en" : "Position", "fr" : "Position", @@ -3073,7 +3125,7 @@ } }, "workspace.options.size" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:100", "src/app/main/ui/workspace/sidebar/options/measures.cljs:116" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:116", "src/app/main/ui/workspace/sidebar/options/frame.cljs:100" ], "translations" : { "en" : "Size", "fr" : "Taille", @@ -3280,7 +3332,7 @@ } }, "workspace.options.text-options.none" : { - "used-in" : [ "src/app/main/ui/workspace/sidebar/options/typography.cljs:178", "src/app/main/ui/workspace/sidebar/options/text.cljs:154" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:154", "src/app/main/ui/workspace/sidebar/options/typography.cljs:178" ], "translations" : { "en" : "None", "fr" : "Aucune", @@ -3377,138 +3429,139 @@ } }, "workspace.shape.menu.back" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:103" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:104" ], "translations" : { "en" : "Send to back" } }, "workspace.shape.menu.backward" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:100" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:101" ], "translations" : { "en" : "Send backward" } }, "workspace.shape.menu.copy" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:81" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:82" ], "translations" : { "en" : "Copy" } }, "workspace.shape.menu.create-component" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:145" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:147" ], "translations" : { "en" : "Create component" } }, "workspace.shape.menu.cut" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:84" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:85" ], "translations" : { "en" : "Cut" } }, "workspace.shape.menu.delete" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:163" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:177" ], "translations" : { "en" : "Delete" } }, "workspace.shape.menu.detach-instance" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:152" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:76", "src/app/main/ui/workspace/sidebar/options/component.cljs:81", "src/app/main/ui/workspace/context_menu.cljs:159", "src/app/main/ui/workspace/context_menu.cljs:169" ], "translations" : { "en" : "Detach instance" } }, "workspace.shape.menu.duplicate" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:90" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:91" ], "translations" : { "en" : "Duplicate" } }, "workspace.shape.menu.forward" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:94" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:95" ], "translations" : { "en" : "Bring forward" } }, "workspace.shape.menu.front" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:97" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:98" ], "translations" : { "en" : "Bring to front" } }, "workspace.shape.menu.go-master" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:159" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:83", "src/app/main/ui/workspace/context_menu.cljs:173" ], "translations" : { "en" : "Go to master component file" } }, - "workspace.shape.menu.show-master" : { - "translations" : { - "en" : "Show master component" - } - }, "workspace.shape.menu.group" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:110" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:111" ], "translations" : { "en" : "Group" } }, "workspace.shape.menu.hide" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:133" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:134" ], "translations" : { "en" : "Hide" } }, "workspace.shape.menu.lock" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:139" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:140" ], "translations" : { "en" : "Lock" } }, "workspace.shape.menu.mask" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:113" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:114" ], "translations" : { "en" : "Mask" } }, "workspace.shape.menu.paste" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:87", "src/app/main/ui/workspace/context_menu.cljs:172" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:88", "src/app/main/ui/workspace/context_menu.cljs:186" ], "translations" : { "en" : "Paste" } }, "workspace.shape.menu.reset-overrides" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:154" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:77", "src/app/main/ui/workspace/sidebar/options/component.cljs:82", "src/app/main/ui/workspace/context_menu.cljs:161", "src/app/main/ui/workspace/context_menu.cljs:171" ], "translations" : { "en" : "Reset overrides" } }, "workspace.shape.menu.show" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:131" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:132" ], "translations" : { "en" : "Show" } }, + "workspace.shape.menu.show-master" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:79", "src/app/main/ui/workspace/context_menu.cljs:165" ], + "translations" : { + "en" : "Show master component" + } + }, "workspace.shape.menu.ungroup" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:119" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:120" ], "translations" : { "en" : "Ungroup" } }, "workspace.shape.menu.unlock" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:137" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:138" ], "translations" : { "en" : "Unlock" } }, "workspace.shape.menu.unmask" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:123" ], + "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:124" ], "translations" : { "en" : "Unmask" } }, "workspace.shape.menu.update-master" : { - "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:157" ], + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:78", "src/app/main/ui/workspace/context_menu.cljs:163" ], "translations" : { "en" : "Update master component" } @@ -3860,7 +3913,7 @@ } }, "workspace.updates.dismiss" : { - "used-in" : [ "src/app/main/data/workspace/libraries.cljs:541" ], + "used-in" : [ "src/app/main/data/workspace/libraries.cljs:638" ], "translations" : { "en" : "Dismiss", "fr" : "", @@ -3869,7 +3922,7 @@ } }, "workspace.updates.there-are-updates" : { - "used-in" : [ "src/app/main/data/workspace/libraries.cljs:537" ], + "used-in" : [ "src/app/main/data/workspace/libraries.cljs:634" ], "translations" : { "en" : "There are updates in shared libraries", "fr" : "", @@ -3878,7 +3931,7 @@ } }, "workspace.updates.update" : { - "used-in" : [ "src/app/main/data/workspace/libraries.cljs:539" ], + "used-in" : [ "src/app/main/data/workspace/libraries.cljs:636" ], "translations" : { "en" : "Update", "fr" : "", diff --git a/frontend/resources/polyfills/scrollIntoViewIfNeeded.js b/frontend/resources/polyfills/scrollIntoViewIfNeeded.js new file mode 100644 index 0000000000..a341b3e406 --- /dev/null +++ b/frontend/resources/polyfills/scrollIntoViewIfNeeded.js @@ -0,0 +1,27 @@ +;(function() { + if (!Element.prototype.scrollIntoViewIfNeeded) { + Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { + centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; + + var parent = this.parentNode, + parentComputedStyle = window.getComputedStyle(parent, null), + parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')), + parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')), + overTop = this.offsetTop - parent.offsetTop < parent.scrollTop, + overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight), + overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft, + overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth), + alignWithTop = overTop && !overBottom; + + if ((overTop || overBottom) && centerIfNeeded) { + parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2; + } + if ((overLeft || overRight) && centerIfNeeded) { + parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2; + } + if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) { + this.scrollIntoView(alignWithTop); + } + }; + } +})() diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss index b8860a4b43..a18f57a447 100644 --- a/frontend/resources/styles/main-default.scss +++ b/frontend/resources/styles/main-default.scss @@ -80,6 +80,6 @@ @import 'main/partials/user-settings'; @import 'main/partials/workspace'; @import 'main/partials/workspace-header'; -@import 'main/partials/workspace-comments'; +@import 'main/partials/comments'; @import 'main/partials/color-bullet'; @import "main/partials/handoff"; diff --git a/frontend/resources/styles/main/layouts/main-layout.scss b/frontend/resources/styles/main/layouts/main-layout.scss index 22a1cd54c9..b7045cd39a 100644 --- a/frontend/resources/styles/main/layouts/main-layout.scss +++ b/frontend/resources/styles/main/layouts/main-layout.scss @@ -23,7 +23,7 @@ .dashboard-sidebar { grid-row: 1 / span 2; grid-column: 1 / span 2; - overflow: hidden; + // overflow: hidden; } .dashboard-content { diff --git a/frontend/resources/styles/main/partials/workspace-comments.scss b/frontend/resources/styles/main/partials/comments.scss similarity index 67% rename from frontend/resources/styles/main/partials/workspace-comments.scss rename to frontend/resources/styles/main/partials/comments.scss index 1f425ae718..b15588d898 100644 --- a/frontend/resources/styles/main/partials/workspace-comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -1,31 +1,4 @@ -.viewer-comments { - width: 100%; - height: 100%; - z-index: 1000; - position: absolute; - top: 0px; - left: 0px; -} - -.viewer-comments, .workspace-comments { - - .comments-layer { - - width: 100%; - height: 100%; - grid-column: 1/span 2; - grid-row: 1/span 2; - z-index: 1000; - pointer-events: none; - overflow: hidden; - - .threads { - position: absolute; - top: 0px; - left: 0px; - } - } - +.comments-section { .thread-bubble { position: absolute; display: flex; @@ -101,6 +74,8 @@ padding: $small; resize: none; width: 100%; + border-radius: 2px; + border: 1px solid $color-gray-10; } .buttons { @@ -142,7 +117,7 @@ .fullname { font-weight: 700; color: $color-gray-60; - font-size: $fs13; + font-size: $fs10; @include text-ellipsis; width: 150px; @@ -150,7 +125,7 @@ } .timeago { margin-top: -2px; - font-size: $fs11; + font-size: $fs10; color: $color-gray-30; } } @@ -163,8 +138,8 @@ img { border-radius: 50%; flex-shrink: 0; - height: 24px; - width: 24px; + height: 20px; + width: 20px; } } @@ -205,9 +180,8 @@ } .content { - margin: $medium 0; - // margin-left: 26px; - font-size: $fs13; + margin: 10px 0; + font-size: $fs10; color: $color-black; .text { margin-left: 26px; @@ -225,51 +199,51 @@ border: 1px solid #B1B2B5; } - } -.workspace-comments-sidebar { - pointer-events: auto; +.workspace-comment-threads-sidebar-header { + display: flex; + background-color: $color-black; + height: 34px; + align-items: center; + padding: 0px 9px; + color: $color-gray-10; + font-size: $fs12; + justify-content: space-between; - .sidebar-title { + .options { display: flex; - background-color: $color-black; - height: 34px; - align-items: center; - padding: 0px 9px; - color: $color-gray-10; - font-size: $fs12; - justify-content: space-between; + margin-right: 3px; + cursor: pointer; - .options { + .label { + padding-right: 8px; + } + + .icon { display: flex; - margin-right: 3px; - cursor: pointer; + align-items: center; + } - .label { - padding-right: 8px; - } - - .icon { - display: flex; - align-items: center; - } - - svg { - fill: $color-gray-10; - width: 10px; - height: 10px; - } + svg { + fill: $color-gray-10; + width: 10px; + height: 10px; } } - .sidebar-options-dropdown { + .dropdown { top: 80px; right: 7px; } +} - .threads { + +.comment-threads-section { + pointer-events: auto; + + .thread-groups { hr { border: 0; height: 1px; @@ -278,7 +252,7 @@ } } - .page-section { + .thread-group { display: flex; flex-direction: column; font-size: $fs12; @@ -292,6 +266,9 @@ } .label { + &.filename { + font-weight: 700; + } } svg { @@ -312,6 +289,7 @@ } .comment { + cursor: pointer; .author { margin-bottom: 10px; .name { @@ -351,3 +329,118 @@ } } } + + +.viewer-comments-container { + width: 100%; + height: 100%; + z-index: 1000; + position: absolute; + top: 0px; + left: 0px; +} + +.workspace-comments-container { + width: 100%; + height: 100%; + grid-column: 1/span 2; + grid-row: 1/span 2; + z-index: 1000; + pointer-events: none; + overflow: hidden; + + .threads { + position: absolute; + top: 0px; + left: 0px; + } +} + +.dashboard-comments-section { + width: 25px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; + background-color: $color-dashboard; + border-radius: 3px; + position: relative; + + .button { + width: 25px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; + background-color: $color-dashboard; + border-radius: 3px; + + svg { + width: 15px; + height: 15px; + } + + &.unread { + background-color: $color-warning; + } + + &.open { + background-color: $color-black; + svg { fill: $color-primary; } + } + } + + .dropdown { + width: 233px; + bottom: 35px; + left: 0px; + border-radius: 3px; + } + + .header { + display: flex; + height: 40px; + align-items: center; + padding: 0px 11px; + + h3 { + font-weight: 400; + color: $color-black; + font-size: $fs12; + line-height: $fs18; + flex-grow: 1; + } + + .close { + display: flex; + align-items: center; + } + + + svg { + width: 15px; + height: 15px; + transform: rotate(45deg); + } + } + + .thread-groups-placeholder { + padding: 16px; + } + + .thread-group { + .section-title { + color: $color-black; + } + } + + .comment { + .author .name .fullname { + color: $color-gray-40; + } + .content { + color: $color-black; + } + } +} + diff --git a/frontend/resources/styles/main/partials/dashboard-sidebar.scss b/frontend/resources/styles/main/partials/dashboard-sidebar.scss index 04f1daf17a..658411737d 100644 --- a/frontend/resources/styles/main/partials/dashboard-sidebar.scss +++ b/frontend/resources/styles/main/partials/dashboard-sidebar.scss @@ -363,26 +363,32 @@ padding: 10px 15px; position: relative; - span { - @include text-ellipsis; - color: $color-black; - margin: 10px 5px; - font-size: $fs14; - max-width: 160px; - } + .profile { + align-items: center; + cursor: pointer; + display: flex; + flex-grow: 1; - img { - border-radius: 50%; - flex-shrink: 0; - height: 25px; - width: 25px; - } + span { + @include text-ellipsis; + color: $color-black; + margin: 10px 5px; + font-size: $fs14; + max-width: 160px; + } - svg { - height: 10px; - margin-left: auto; - margin-right: $small; - width: 10px; + img { + border-radius: 50%; + flex-shrink: 0; + height: 25px; + width: 25px; + } + svg { + height: 10px; + margin-left: auto; + margin-right: $small; + width: 10px; + } } .dropdown { @@ -400,6 +406,8 @@ svg { fill: $color-gray-20; + margin-right: $small; + height: 12px; width: 12px; } diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache index 99da487687..801633eb1f 100644 --- a/frontend/resources/templates/index.mustache +++ b/frontend/resources/templates/index.mustache @@ -20,6 +20,7 @@ {{# manifest}} + {{/manifest}} diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 79b5995a9f..75a1faaeac 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -40,11 +40,14 @@ (s/def ::count-unread-comments ::us/integer) (s/def ::created-at ::us/inst) (s/def ::file-id ::us/uuid) +(s/def ::file-name ::us/string) (s/def ::modified-at ::us/inst) (s/def ::owner-id ::us/uuid) (s/def ::page-id ::us/uuid) +(s/def ::page-name ::us/string) (s/def ::participants (s/every ::us/uuid :kind set?)) (s/def ::position ::us/point) +(s/def ::project-id ::us/uuid) (s/def ::seqn ::us/integer) (s/def ::thread-id ::us/uuid) @@ -52,15 +55,18 @@ (s/keys :req-un [::us/id ::page-id ::file-id + ::project-id + ::page-name + ::file-name ::seqn ::content ::participants - ::count-unread-comments - ::count-comments ::created-at ::modified-at ::owner-id - ::position])) + ::position] + :opt-un [::count-unread-comments + ::count-comments])) (s/def ::comment (s/keys :req-un [::us/id @@ -92,20 +98,18 @@ ptk/WatchEvent (watch [_ state stream] (->> (rp/mutation :create-comment-thread params) + (rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %)})) (rx/map #(partial created %))))))) (defn update-comment-thread-status [{:keys [id] :as thread}] (us/assert ::comment-thread thread) (ptk/reify ::update-comment-thread-status - ptk/UpdateEvent - (update [_ state] - (d/update-in-when state [:comment-threads id] assoc :count-unread-comments 0)) - ptk/WatchEvent (watch [_ state stream] - (->> (rp/mutation :update-comment-thread-status {:id id}) - (rx/ignore))))) + (let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0)] + (->> (rp/mutation :update-comment-thread-status {:id id}) + (rx/map (constantly done))))))) (defn update-comment-thread @@ -211,6 +215,18 @@ (->> (rp/query :comments {:thread-id thread-id}) (rx/map #(partial fetched %))))))) +(defn retrieve-unread-comment-threads + "A event used mainly in dashboard for retrieve all unread threads of a team." + [team-id] + (us/assert ::us/uuid team-id) + (ptk/reify ::retrieve-unread-comment-threads + ptk/WatchEvent + (watch [_ state stream] + (let [fetched #(assoc %2 :comment-threads (d/index-by :id %1))] + (->> (rp/query :unread-comment-threads {:team-id team-id}) + (rx/map #(partial fetched %))))))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Local State ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -221,6 +237,7 @@ (ptk/reify ::open-thread ptk/UpdateEvent (update [_ state] + (prn "open-thread" id) (-> state (update :comments-local assoc :open id) (update :workspace-drawing dissoc :comment))))) @@ -230,6 +247,7 @@ (ptk/reify ::close-thread ptk/UpdateEvent (update [_ state] + (prn "close-thread") (-> state (update :comments-local dissoc :open :draft) (update :workspace-drawing dissoc :comment))))) @@ -282,11 +300,31 @@ (if (= (:page-id current) (:page-id thread)) (cons (update current :items conj thread) (rest result)) - (cons {:page-id (:page-id thread) :items [thread]} + (cons {:page-id (:page-id thread) + :page-name (:page-name thread) + :items [thread]} result))))] (reverse (reduce group-by-page nil threads)))) + +(defn group-threads-by-file-and-page + [threads] + (letfn [(group-by-file-and-page [result thread] + (let [current (first result)] + (if (and (= (:page-id current) (:page-id thread)) + (= (:file-id current) (:file-id thread))) + (cons (update current :items conj thread) + (rest result)) + (cons {:page-id (:page-id thread) + :page-name (:page-name thread) + :file-id (:file-id thread) + :file-name (:file-name thread) + :items [thread]} + result))))] + (reverse + (reduce group-by-file-and-page nil threads)))) + (defn apply-filters [cstate profile threads] (let [{:keys [show mode open]} cstate] diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 52ae6f79ab..862a90ba77 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -64,13 +64,6 @@ ;; --- Fetch Team -(defn assoc-team-avatar - [{:keys [photo name] :as team}] - (us/assert ::team team) - (cond-> team - (or (nil? photo) (empty? photo)) - (assoc :photo (avatars/generate {:name name})))) - (defn fetch-team [{:keys [id] :as params}] (letfn [(fetched [team state] @@ -80,20 +73,36 @@ (watch [_ state stream] (let [profile (:profile state)] (->> (rp/query :team params) - (rx/map assoc-team-avatar) + (rx/map #(avatars/assoc-avatar % :name)) (rx/map #(partial fetched %)))))))) (defn fetch-team-members [{:keys [id] :as params}] (us/assert ::us/uuid id) (letfn [(fetched [members state] - (assoc-in state [:team-members id] (d/index-by :id members)))] + (->> (map #(avatars/assoc-avatar % :name) members) + (d/index-by :id) + (assoc-in state [:team-members id])))] (ptk/reify ::fetch-team-members ptk/WatchEvent (watch [_ state stream] (->> (rp/query :team-members {:team-id id}) (rx/map #(partial fetched %))))))) + +(defn fetch-team-users + [{:keys [id] :as params}] + (us/assert ::us/uuid id) + (letfn [(fetched [users state] + (->> (map #(avatars/assoc-avatar % :fullname) users) + (d/index-by :id) + (assoc-in state [:team-users id])))] + (ptk/reify ::fetch-team-users + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :team-users {:team-id id}) + (rx/map #(partial fetched %))))))) + ;; --- Fetch Projects (defn fetch-projects @@ -115,7 +124,8 @@ (watch [_ state stream] (let [profile (:profile state)] (->> (rx/merge (ptk/watch (fetch-team params) state stream) - (ptk/watch (fetch-projects {:team-id id}) state stream)) + (ptk/watch (fetch-projects {:team-id id}) state stream) + (ptk/watch (fetch-team-users params) state stream)) (rx/catch (fn [{:keys [type code] :as error}] (cond (and (= :not-found type) diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs index 2e990f7d09..56b624ae98 100644 --- a/frontend/src/app/main/data/users.cljs +++ b/frontend/src/app/main/data/users.cljs @@ -55,8 +55,8 @@ (update [_ state] (assoc state :profile (cond-> data - (nil? (:photo-uri data)) - (assoc :photo-uri (avatars/generate {:name fullname})) + (empty? (:photo data)) + (assoc :photo (avatars/generate {:name fullname})) (nil? (:lang data)) (assoc :lang cfg/default-language) diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index ac1d16c053..ccbbd8c306 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -14,10 +14,12 @@ [app.common.math :as mth] [app.common.spec :as us] [app.main.constants :as c] + [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.comments :as dcm] [app.main.store :as st] [app.main.streams :as ms] + [app.util.router :as rt] [beicon.core :as rx] [cljs.spec.alpha :as s] [potok.core :as ptk])) @@ -82,12 +84,31 @@ (update [_ state] (update state :workspace-local (fn [{:keys [vbox vport zoom] :as local}] + (prn "center-to-comment-thread" vbox) (let [pw (/ 50 zoom) ph (/ 200 zoom) nw (mth/round (- (/ (:width vbox) 2) pw)) nh (mth/round (- (/ (:height vbox) 2) ph)) nx (- (:x position) nw) ny (- (:y position) nh)] - (update local :vbox assoc :x nx :y ny))))))) + (update local :vbox assoc :x nx :y ny))))))) + +(defn navigate + [{:keys [project-id file-id page-id] :as thread}] + (us/assert ::dcm/comment-thread thread) + (ptk/reify ::navigate + ptk/WatchEvent + (watch [_ state stream] + (let [pparams {:project-id (:project-id thread) + :file-id (:file-id thread)} + qparams {:page-id (:page-id thread)}] + (rx/merge + (rx/of (rt/nav :workspace pparams qparams) + (dw/select-for-drawing :comments)) + (->> stream + (rx/filter (ptk/type? ::dw/initialize-viewport)) + (rx/take 1) + (rx/mapcat #(rx/of (center-to-comment-thread thread) + (dcm/open-thread thread))))))))) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 37d5b72006..58fa20a6ed 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -208,6 +208,9 @@ (def viewer-local (l/derived :viewer-local st/state)) +(def comment-threads + (l/derived :comment-threads st/state)) + (def comments-local (l/derived :comments-local st/state)) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 3cf96c3631..d681003d2a 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -148,7 +148,7 @@ :left (str (+ pos-x 14) "px")} :on-click dom/stop-propagation} [:div.reply-form - [:& resizing-textarea {:placeholder "Write new comment" + [:& resizing-textarea {:placeholder (tr "labels.write-new-comment") :value (or content "") :on-esc on-esc :on-change on-change}] @@ -267,10 +267,10 @@ [:& dropdown {:show @options :on-close on-hide-options} [:ul.dropdown.comment-options-dropdown - [:li {:on-click on-edit-clicked} "Edit"] + [:li {:on-click on-edit-clicked} (tr "labels.edit")] (if thread - [:li {:on-click on-delete-thread} "Delete thread"] - [:li {:on-click on-delete-comment} "Delete comment"])]]])) + [:li {:on-click on-delete-thread} (tr "labels.delete-comment-thread")] + [:li {:on-click on-delete-comment} (tr "labels.delete-comment")])]]])) (defn comments-ref [{:keys [id] :as thread}] @@ -289,12 +289,13 @@ (sort-by :created-at)) comment (first comments)] - (mf/use-effect - (st/emitf (dcm/update-comment-thread-status thread))) + (mf/use-layout-effect + (mf/deps thread) + (st/emitf (dcm/retrieve-comments (:id thread)))) (mf/use-effect (mf/deps thread) - (st/emitf (dcm/retrieve-comments (:id thread)))) + (st/emitf (dcm/update-comment-thread-status thread))) (mf/use-layout-effect (mf/deps thread comments-map) @@ -338,3 +339,62 @@ :unread (pos? (:count-unread-comments thread))) :on-click on-click*} [:span (:seqn thread)]])) + +(mf/defc comment-thread + [{:keys [item users on-click] :as props}] + (let [profile (get users (:owner-id item)) + + on-click* + (mf/use-callback + (mf/deps item) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (when (fn? on-click) + (on-click item))))] + + [:div.comment {:on-click on-click*} + [:div.author + [:div.thread-bubble + {:class (dom/classnames + :resolved (:is-resolved item) + :unread (pos? (:count-unread-comments item)))} + (:seqn item)] + [:div.avatar + [:img {:src (cfg/resolve-media-path (:photo profile))}]] + [:div.name + [:div.fullname (:fullname profile) ", "] + [:div.timeago (dt/timeago (:modified-at item))]]] + [:div.content + [:span.text (:content item)]] + [:div.content.replies + (let [unread (:count-unread-comments item ::none) + total (:count-comments item 1)] + [:* + (when (> total 1) + (if (= total 2) + [:span.total-replies "1 reply"] + [:span.total-replies (str (dec total) " replies")])) + + (when (and (> total 1) (> unread 0)) + (if (= unread 1) + [:span.new-replies "1 new reply"] + [:span.new-replies (str unread " new replies")]))])]])) + +(mf/defc comment-thread-group + [{:keys [group users on-thread-click]}] + [:div.thread-group + (if (:file-name group) + [:div.section-title + [:span.label.filename (:file-name group) ", "] + [:span.label (:page-name group)]] + [:div.section-title + [:span.icon i/file-html] + [:span.label (:page-name group)]]) + [:div.threads + (for [item (:items group)] + [:& comment-thread + {:item item + :on-click on-thread-click + :users users + :key (:id item)}])]]) diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs new file mode 100644 index 0000000000..3febd79e1d --- /dev/null +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -0,0 +1,104 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.dashboard.comments + (:require + [okulary.core :as l] + [app.common.data :as d] + [app.common.spec :as us] + [app.config :as cfg] + [app.main.data.auth :as da] + [app.main.data.dashboard :as dd] + [app.main.data.workspace :as dw] + [app.main.data.workspace.comments :as dwcm] + [app.main.data.comments :as dcm] + [app.main.refs :as refs] + [app.main.repo :as rp] + [app.main.store :as st] + [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.comments :as cmt] + [app.main.ui.icons :as i] + [app.util.dom :as dom] + [app.util.i18n :as i18n :refer [t tr]] + [app.util.object :as obj] + [app.util.router :as rt] + [app.util.time :as dt] + [app.util.timers :as tm] + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [cuerdas.core :as str] + [rumext.alpha :as mf])) + + +(defn team-members-ref + [{:keys [id] :as team}] + (l/derived (l/in [:team-users id]) st/state)) + +(mf/defc comments-section + [{:keys [profile team]}] + + (mf/use-effect + (mf/deps team) + (st/emitf (dcm/retrieve-unread-comment-threads (:id team)))) + + (let [show-dropdown? (mf/use-state false) + show-dropdown (mf/use-fn #(reset! show-dropdown? true)) + hide-dropdown (mf/use-fn #(reset! show-dropdown? false)) + threads-map (mf/deref refs/comment-threads) + + users-ref (mf/use-memo (mf/deps team) #(team-members-ref team)) + users (mf/deref users-ref) + + tgroups (->> (vals threads-map) + (sort-by :modified-at) + (reverse) + (dcm/apply-filters {} profile) + (dcm/group-threads-by-file-and-page)) + + + on-navigate + (mf/use-callback + (fn [thread] + (st/emit! (dwcm/navigate thread))))] + + [:div.dashboard-comments-section + [:div.button + {:on-click show-dropdown + :class (dom/classnames :open @show-dropdown? + :unread (boolean (seq tgroups)))} + i/chat] + + [:& dropdown {:show @show-dropdown? :on-close hide-dropdown} + [:div.dropdown.comments-section.comment-threads-section. + [:div.header + [:h3 (tr "labels.comments")] + [:span.close {:on-click hide-dropdown} i/close]] + + [:hr] + + (if (seq tgroups) + [:div.thread-groups + [:& cmt/comment-thread-group + {:group (first tgroups) + :on-thread-click on-navigate + :show-file-name true + :users users}] + (for [tgroup (rest tgroups)] + [:* + [:hr] + + [:& cmt/comment-thread-group + {:group tgroup + :on-thread-click on-navigate + :show-file-name true + :users users + :key (:page-id tgroup)}]])] + + [:div.thread-groups-placeholder + (tr "labels.no-comments-available")])]]])) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index e05f064ca2..73554a5146 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -15,21 +15,24 @@ [app.main.data.auth :as da] [app.main.data.dashboard :as dd] [app.main.data.messages :as dm] + [app.main.data.modal :as modal] + [app.main.data.comments :as dcm] [app.main.refs :as refs] [app.main.repo :as rp] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] - [app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.components.forms :as fm] + [app.main.ui.dashboard.comments :refer [comments-section]] + [app.main.ui.dashboard.inline-edition :refer [inline-edition]] [app.main.ui.dashboard.team-form] [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] - [app.main.data.modal :as modal] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t tr]] [app.util.object :as obj] [app.util.router :as rt] [app.util.time :as dt] + [app.util.avatars :as avatars] [beicon.core :as rx] [cljs.spec.alpha :as s] [cuerdas.core :as str] @@ -133,7 +136,8 @@ (mf/deps (:id team)) (fn [] (->> (rp/query! :teams) - (rx/map #(mapv dd/assoc-team-avatar %)) + (rx/map (fn [teams] + (mapv #(avatars/assoc-avatar % :name) teams))) (rx/subs #(reset! teams %))))) [:ul.dropdown.teams-dropdown @@ -421,12 +425,9 @@ (mf/defc profile-section - [{:keys [profile locale] :as props}] + [{:keys [profile locale team] :as props}] (let [show (mf/use-state false) - photo (:photo-uri profile "") - photo (if (str/empty? photo) - "/images/avatar.jpg" - photo) + photo (cfg/resolve-media-path (:photo profile)) on-click (mf/use-callback @@ -436,10 +437,10 @@ (st/emit! (rt/nav section)) (st/emit! section))))] - [:div.profile-section {:on-click #(reset! show true)} - [:img {:src photo}] - [:span (:fullname profile)] - i/arrow-down + [:div.profile-section + [:div.profile {:on-click #(reset! show true)} + [:img {:src photo}] + [:span (:fullname profile)] [:& dropdown {:on-close #(reset! show false) :show @show} @@ -452,17 +453,25 @@ [:span.text (t locale "labels.password")]] [:li {:on-click (partial on-click (da/logout))} [:span.icon i/exit] - [:span.text (t locale "labels.logout")]]]]])) + [:span.text (t locale "labels.logout")]]]]] + + (when (and team profile) + [:& comments-section {:profile profile + :team team}])])) (mf/defc sidebar {::mf/wrap-props false ::mf/wrap [mf/memo]} [props] (let [locale (mf/deref i18n/locale) + team (obj/get props "team") profile (obj/get props "profile") props (-> (obj/clone props) (obj/set! "locale" locale))] [:div.dashboard-sidebar [:div.sidebar-inside [:> sidebar-content props] - [:& profile-section {:profile profile :locale locale}]]])) + [:& profile-section + {:profile profile + :team team + :locale locale}]]])) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 6633f236bf..73017aaeb3 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -106,8 +106,8 @@ (dcm/close-thread))))) ] - [:div.viewer-comments {:on-click on-click} - [:div.comments-layer + [:div.comments-section {:on-click on-click} + [:div.viewer-comments-container [:div.threads (for [item threads] [:& cmt/thread-bubble {:thread item diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index f2f113e882..25a69c9f8a 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -60,7 +60,6 @@ #_(dcm/close-thread)))) ] - (mf/use-effect (mf/deps file-id) (fn [] @@ -68,8 +67,8 @@ (fn [] (st/emit! ::dwcm/finalize)))) - [:div.workspace-comments - [:div.comments-layer + [:div.comments-section + [:div.workspace-comments-container {:style {:width (str (:width vport) "px") :height (str (:height vport) "px")}} [:div.threads {:style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}} @@ -96,66 +95,6 @@ ;; Sidebar ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(mf/defc sidebar-group-item - [{:keys [item] :as props}] - (let [profile (get @refs/workspace-users (:owner-id item)) - page-id (mf/use-ctx ctx/current-page-id) - file-id (mf/use-ctx ctx/current-file-id) - - on-click - (mf/use-callback - (mf/deps item page-id) - (fn [] - (when (not= page-id (:page-id item)) - (st/emit! (dw/go-to-page (:page-id item)))) - (tm/schedule - (st/emitf (dwcm/center-to-comment-thread item) - (dcm/open-thread item)))))] - - [:div.comment {:on-click on-click} - [:div.author - [:div.thread-bubble - {:class (dom/classnames - :resolved (:is-resolved item) - :unread (pos? (:count-unread-comments item)))} - (:seqn item)] - [:div.avatar - [:img {:src (cfg/resolve-media-path (:photo profile))}]] - [:div.name - [:div.fullname (:fullname profile) ", "] - [:div.timeago (dt/timeago (:modified-at item))]]] - [:div.content - [:span.text (:content item)]] - [:div.content.replies - (let [unread (:count-unread-comments item ::none) - total (:count-comments item 1)] - [:* - (when (> total 1) - (if (= total 2) - [:span.total-replies "1 reply"] - [:span.total-replies (str (dec total) " replies")])) - - (when (and (> total 1) (> unread 0)) - (if (= unread 1) - [:span.new-replies "1 new reply"] - [:span.new-replies (str unread " new replies")]))])]])) - -(defn page-name-ref - [id] - (l/derived (l/in [:workspace-data :pages-index id :name]) st/state)) - -(mf/defc sidebar-item - [{:keys [group]}] - (let [page-name-ref (mf/use-memo (mf/deps (:page-id group)) #(page-name-ref (:page-id group))) - page-name (mf/deref page-name-ref)] - [:div.page-section - [:div.section-title - [:span.icon i/file-html] - [:span.label page-name]] - [:div.comments-container - (for [item (:items group)] - [:& sidebar-group-item {:item item :key (:id item)}])]])) - (mf/defc sidebar-options [{:keys [local] :as props}] (let [{cmode :mode cshow :show} (mf/deref refs/comments-local) @@ -171,7 +110,7 @@ (fn [mode] (st/emit! (dcm/update-filters {:show mode}))))] - [:ul.dropdown.with-check.sidebar-options-dropdown + [:ul.dropdown.with-check [:li {:class (dom/classnames :selected (or (= :all cmode) (nil? cmode))) :on-click #(update-mode :all)} [:span.icon i/tick] @@ -193,6 +132,7 @@ [] (let [threads-map (mf/deref threads-ref) profile (mf/deref refs/profile) + users (mf/deref refs/workspace-users) local (mf/deref refs/comments-local) options? (mf/use-state false) @@ -200,28 +140,45 @@ (sort-by :modified-at) (reverse) (dcm/apply-filters local profile) - (dcm/group-threads-by-page))] + (dcm/group-threads-by-page)) - [:div.workspace-comments.workspace-comments-sidebar - [:div.sidebar-title + page-id (mf/use-ctx ctx/current-page-id) + + on-thread-click + (mf/use-callback + (fn [thread] + (when (not= page-id (:page-id thread)) + (st/emit! (dw/go-to-page (:page-id thread)))) + (tm/schedule + (st/emitf (dwcm/center-to-comment-thread thread) + (dcm/open-thread thread)))))] + + [:div.comments-section.comment-threads-section + [:div.workspace-comment-threads-sidebar-header [:div.label "Comments"] [:div.options {:on-click #(reset! options? true)} - [:div.label (case (:filter local) + [:div.label (case (:mode local) (nil :all) "All" :yours "Only yours")] - [:div.icon i/arrow-down]]] + [:div.icon i/arrow-down]] - [:& dropdown {:show @options? - :on-close #(reset! options? false)} - [:& sidebar-options {:local local}]] + [:& dropdown {:show @options? + :on-close #(reset! options? false)} + [:& sidebar-options {:local local}]]] (when (seq tgroups) - [:div.threads - [:& sidebar-item {:group (first tgroups)}] + [:div.thread-groups + [:& cmt/comment-thread-group + {:group (first tgroups) + :on-thread-click on-thread-click + :users users}] (for [tgroup (rest tgroups)] [:* [:hr] - [:& sidebar-item {:group tgroup - :key (:page-id tgroup)}]])])])) + [:& cmt/comment-thread-group + {:group tgroup + :on-thread-click on-thread-click + :users users + :key (:page-id tgroup)}]])])])) diff --git a/frontend/src/app/util/avatars.cljs b/frontend/src/app/util/avatars.cljs index 64a79e1ee2..04a9bd38c9 100644 --- a/frontend/src/app/util/avatars.cljs +++ b/frontend/src/app/util/avatars.cljs @@ -36,8 +36,13 @@ (.toDataURL canvas))) -(defn assoc-profile-avatar - [{:keys [photo fullname] :as profile}] - (cond-> profile +(defn assoc-avatar + [{:keys [photo] :as object} key] + (cond-> object (or (nil? photo) (empty? photo)) - (assoc :photo (generate {:name fullname})))) + (assoc :photo (generate {:name (get object key)})))) + +(defn assoc-profile-avatar + [object] + (assoc-avatar object :fullname)) + diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 9515c97bfb..0225cfb407 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -933,6 +933,13 @@ concat-stream@^1.6.0, concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" +concat-with-sourcemaps@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== + dependencies: + source-map "^0.6.1" + config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -2033,6 +2040,15 @@ gulp-cli@^2.2.0: v8flags "^3.2.0" yargs "^7.1.0" +gulp-concat@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353" + integrity sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M= + dependencies: + concat-with-sourcemaps "^1.0.0" + through2 "^2.0.0" + vinyl "^2.0.0" + gulp-gzip@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/gulp-gzip/-/gulp-gzip-1.4.2.tgz#0422a94014248655b5b1a9eea1c2abee1d4f4337" From 0e43fb3f06387fedc5ccf13758c845bfa4cdfbc4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 11:24:33 +0100 Subject: [PATCH 032/195] :paperclip: Minor cosmetic changes. --- common/app/common/pages.cljc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index b46f12ed4f..0feaccbfc0 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -39,15 +39,16 @@ (s/def ::type keyword?) (s/def ::uuid uuid?) +(s/def ::component-id uuid?) +(s/def ::component-file uuid?) +(s/def ::component-root? boolean?) +(s/def ::shape-ref uuid?) + (s/def ::safe-integer #(and (integer? %) (>= % min-safe-int) (<= % max-safe-int))) -(s/def ::component-id uuid?) -(s/def ::component-file uuid?) -(s/def ::component-root? boolean?) -(s/def ::shape-ref uuid?) (s/def ::safe-number #(and @@ -55,6 +56,7 @@ (>= % min-safe-int) (<= % max-safe-int))) + ;; GRADIENTS (s/def :internal.gradient.stop/color ::string) From 17de1414ef382e9234ea778154cf1c1966cbe745 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 11:24:49 +0100 Subject: [PATCH 033/195] :fire: Remove prn traces. --- frontend/src/app/main/data/comments.cljs | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 75a1faaeac..7dd2e8df2d 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -237,7 +237,6 @@ (ptk/reify ::open-thread ptk/UpdateEvent (update [_ state] - (prn "open-thread" id) (-> state (update :comments-local assoc :open id) (update :workspace-drawing dissoc :comment))))) @@ -247,7 +246,6 @@ (ptk/reify ::close-thread ptk/UpdateEvent (update [_ state] - (prn "close-thread") (-> state (update :comments-local dissoc :open :draft) (update :workspace-drawing dissoc :comment))))) From d862406b44f0ea50a35b1ffe6be4d9885757a9e2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 11:32:59 +0100 Subject: [PATCH 034/195] :bug: Don't show/allow update or delete comments to not owners. --- .../src/app/services/mutations/comments.clj | 9 +++++++-- frontend/src/app/main/ui/comments.cljs | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/backend/src/app/services/mutations/comments.clj b/backend/src/app/services/mutations/comments.clj index 8fd4ce4f7a..5838ab7c52 100644 --- a/backend/src/app/services/mutations/comments.clj +++ b/backend/src/app/services/mutations/comments.clj @@ -233,6 +233,11 @@ (files/check-read-permissions! conn profile-id (:file-id thread)) + ;; Don't allow edit comments to not owners + (when-not (= (:owner-id thread) profile-id) + (ex/raise :type :validation + :code :not-allowed)) + (db/update! conn :comment {:content content :modified-at (dt/now)} @@ -253,8 +258,8 @@ (sm/defmutation ::delete-comment-thread [{:keys [profile-id id] :as params}] (db/with-atomic [conn db/pool] - (let [cthr (db/get-by-id conn :comment-thread id {:for-update true})] - (when-not (= (:owner-id cthr) profile-id) + (let [thread (db/get-by-id conn :comment-thread id {:for-update true})] + (when-not (= (:owner-id thread) profile-id) (ex/raise :type :validation :code :not-allowed)) (db/delete! conn :comment-thread {:id id}) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index d681003d2a..48861817f6 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -184,7 +184,8 @@ (mf/defc comment-item [{:keys [comment thread users] :as props}] - (let [profile (get (or users @refs/workspace-users) (:owner-id comment)) + (let [owner (get (or users @refs/workspace-users) (:owner-id comment)) + profile (mf/use-state refs/profile) options (mf/use-state false) edition? (mf/use-state false) @@ -243,9 +244,9 @@ [:div.comment [:div.author [:div.avatar - [:img {:src (cfg/resolve-media-path (:photo profile))}]] + [:img {:src (cfg/resolve-media-path (:photo owner))}]] [:div.name - [:div.fullname (:fullname profile)] + [:div.fullname (:fullname owner)] [:div.timeago (dt/timeago (:modified-at comment))]] (when (some? thread) @@ -253,9 +254,9 @@ (if (:is-resolved thread) [:span i/checkbox-checked] [:span i/checkbox-unchecked])]) - - [:div.options - [:div.options-icon {:on-click on-show-options} i/actions]]] + (when (= (:id profile) (:id owner)) + [:div.options + [:div.options-icon {:on-click on-show-options} i/actions]])] [:div.content (if @edition? @@ -342,7 +343,7 @@ (mf/defc comment-thread [{:keys [item users on-click] :as props}] - (let [profile (get users (:owner-id item)) + (let [owner (get users (:owner-id item)) on-click* (mf/use-callback @@ -361,9 +362,9 @@ :unread (pos? (:count-unread-comments item)))} (:seqn item)] [:div.avatar - [:img {:src (cfg/resolve-media-path (:photo profile))}]] + [:img {:src (cfg/resolve-media-path (:photo owner))}]] [:div.name - [:div.fullname (:fullname profile) ", "] + [:div.fullname (:fullname owner) ", "] [:div.timeago (dt/timeago (:modified-at item))]]] [:div.content [:span.text (:content item)]] From 9f9f146444adc040156dc556637b66a54e46d84f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 11:34:57 +0100 Subject: [PATCH 035/195] :paperclip: Minor cosmetic changes on comments ui code. --- frontend/src/app/main/ui/comments.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 48861817f6..b09fe8f923 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -184,7 +184,7 @@ (mf/defc comment-item [{:keys [comment thread users] :as props}] - (let [owner (get (or users @refs/workspace-users) (:owner-id comment)) + (let [owner (get users (:owner-id comment)) profile (mf/use-state refs/profile) options (mf/use-state false) edition? (mf/use-state false) From 686f96eb27447635aa7cc2fbd786d836df113c1f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 11:43:30 +0100 Subject: [PATCH 036/195] :bug: Properly pass users to comments component on workspace. --- frontend/resources/locales.json | 30 +++++++++++++------ .../src/app/main/ui/workspace/comments.cljs | 10 +++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index f08ce41e82..30e1542718 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -1275,6 +1275,12 @@ "en" : "Admin" } }, + "labels.all" : { + "used-in" : [ "src/app/main/ui/workspace/comments.cljs:161" ], + "translations" : { + "en" : "All" + } + }, "labels.cancel" : { "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:203" ], "translations" : { @@ -1285,7 +1291,7 @@ } }, "labels.comments" : { - "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:75" ], + "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:80" ], "translations" : { "en" : "Comments" } @@ -1315,13 +1321,13 @@ } }, "labels.delete-comment" : { - "used-in" : [ "src/app/main/ui/comments.cljs:273" ], + "used-in" : [ "src/app/main/ui/comments.cljs:274" ], "translations" : { "en" : "Delete comment" } }, "labels.delete-comment-thread" : { - "used-in" : [ "src/app/main/ui/comments.cljs:272" ], + "used-in" : [ "src/app/main/ui/comments.cljs:273" ], "translations" : { "en" : "Delete thread" } @@ -1336,7 +1342,7 @@ } }, "labels.edit" : { - "used-in" : [ "src/app/main/ui/comments.cljs:270" ], + "used-in" : [ "src/app/main/ui/comments.cljs:271" ], "translations" : { "en" : "Edit" } @@ -1405,10 +1411,10 @@ } }, "labels.no-comments-available" : { + "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:104" ], "translations" : { "en" : "No comments" - }, - "unused" : true + } }, "labels.old-password" : { "used-in" : [ "src/app/main/ui/settings/password.cljs:81" ], @@ -1419,6 +1425,12 @@ "es" : "Contraseña anterior" } }, + "labels.only-yours" : { + "used-in" : [ "src/app/main/ui/workspace/comments.cljs:162" ], + "translations" : { + "en" : "Only yours" + } + }, "labels.owner" : { "used-in" : [ "src/app/main/ui/dashboard/team.cljs:171", "src/app/main/ui/dashboard/team.cljs:291" ], "translations" : { @@ -1660,19 +1672,19 @@ } }, "modals.delete-comment-thread.accept" : { - "used-in" : [ "src/app/main/ui/comments.cljs:222" ], + "used-in" : [ "src/app/main/ui/comments.cljs:223" ], "translations" : { "en" : "Delete conversation" } }, "modals.delete-comment-thread.message" : { - "used-in" : [ "src/app/main/ui/comments.cljs:221" ], + "used-in" : [ "src/app/main/ui/comments.cljs:222" ], "translations" : { "en" : "Are you sure you want to delete this conversation? All comments in this thread will be deleted." } }, "modals.delete-comment-thread.title" : { - "used-in" : [ "src/app/main/ui/comments.cljs:220" ], + "used-in" : [ "src/app/main/ui/comments.cljs:221" ], "translations" : { "en" : "Delete conversation" } diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index 25a69c9f8a..a753f60ae4 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -36,6 +36,7 @@ pos-y (* (- (:y vbox)) zoom) profile (mf/deref refs/profile) + users (mf/deref refs/workspace-users) local (mf/deref refs/comments-local) threads-map (mf/deref threads-ref) @@ -56,9 +57,7 @@ on-draft-submit (mf/use-callback (fn [draft] - (st/emit! (dcm/create-thread draft) - #_(dcm/close-thread)))) - ] + (st/emit! (dcm/create-thread draft))))] (mf/use-effect (mf/deps file-id) @@ -82,6 +81,7 @@ (when-let [id (:open local)] (when-let [thread (get threads-map id)] [:& cmt/thread-comments {:thread thread + :users users :zoom zoom}])) (when-let [draft (:comment drawing)] @@ -158,8 +158,8 @@ [:div.label "Comments"] [:div.options {:on-click #(reset! options? true)} [:div.label (case (:mode local) - (nil :all) "All" - :yours "Only yours")] + (nil :all) (tr "labels.all") + :yours (tr "labels.only-yours"))] [:div.icon i/arrow-down]] [:& dropdown {:show @options? From 45f17f78f3fe54f9b0bfa785026c2cc16ec87267 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 12:10:07 +0100 Subject: [PATCH 037/195] :bug: Force persist operation on go-viewer clicked. --- frontend/src/app/main/data/workspace.cljs | 10 ++- .../app/main/data/workspace/persistence.cljs | 3 +- .../src/app/main/ui/workspace/header.cljs | 61 +++++++++++-------- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 7ac9cba4d2..ce2aa0c890 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1225,6 +1225,15 @@ qparams {:page-id page-id}] (rx/of (rt/nav :workspace pparams qparams)))))) + +(defn go-to-viewer + [{:keys [file-id page-id] :as params}] + (ptk/reify ::go-to-viewer + ptk/WatchEvent + (watch [_ state stream] + (rx/of ::dwp/force-persist + (rt/nav :viewer params {:index 0}))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Context Menu ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1769,6 +1778,5 @@ "down" #(st/emit! (dwt/move-selected :down false)) "right" #(st/emit! (dwt/move-selected :right false)) "left" #(st/emit! (dwt/move-selected :left false)) - "i" #(st/emit! (mdc/picker-for-selected-shape ))}) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 6e8e66715a..c36c702c54 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -43,10 +43,11 @@ ptk/EffectEvent (effect [_ state stream] (let [stoper (rx/filter #(= ::finalize %) stream) + forcer (rx/filter #(= ::force-persist %) stream) notifier (->> stream (rx/filter (ptk/type? ::dwc/commit-changes)) (rx/debounce 2000) - (rx/merge stoper)) + (rx/merge stoper forcer)) on-dirty (fn [] diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 2ec8e2e0b3..7209d0231d 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -171,69 +171,79 @@ [:li {:on-click #(st/emit! (dw/toggle-layout-flags :rules))} [:span (if (contains? layout :rules) - (t locale "workspace.header.menu.hide-rules") - (t locale "workspace.header.menu.show-rules"))] + (tr "workspace.header.menu.hide-rules") + (tr "workspace.header.menu.show-rules"))] [:span.shortcut "Ctrl+shift+R"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :display-grid))} [:span (if (contains? layout :display-grid) - (t locale "workspace.header.menu.hide-grid") - (t locale "workspace.header.menu.show-grid"))] + (tr "workspace.header.menu.hide-grid") + (tr "workspace.header.menu.show-grid"))] [:span.shortcut "Ctrl+'"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :snap-grid))} [:span (if (contains? layout :snap-grid) - (t locale "workspace.header.menu.disable-snap-grid") - (t locale "workspace.header.menu.enable-snap-grid"))] + (tr "workspace.header.menu.disable-snap-grid") + (tr "workspace.header.menu.enable-snap-grid"))] [:span.shortcut "Ctrl+Shift+'"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :sitemap :layers))} [:span (if (or (contains? layout :sitemap) (contains? layout :layers)) - (t locale "workspace.header.menu.hide-layers") - (t locale "workspace.header.menu.show-layers"))] + (tr "workspace.header.menu.hide-layers") + (tr "workspace.header.menu.show-layers"))] [:span.shortcut "Ctrl+l"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :colorpalette))} [:span (if (contains? layout :colorpalette) - (t locale "workspace.header.menu.hide-palette") - (t locale "workspace.header.menu.show-palette"))] + (tr "workspace.header.menu.hide-palette") + (tr "workspace.header.menu.show-palette"))] [:span.shortcut "Ctrl+p"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :assets))} [:span (if (contains? layout :assets) - (t locale "workspace.header.menu.hide-assets") - (t locale "workspace.header.menu.show-assets"))] + (tr "workspace.header.menu.hide-assets") + (tr "workspace.header.menu.show-assets"))] [:span.shortcut "Ctrl+i"]] [:li {:on-click #(st/emit! (dw/toggle-layout-flags :dynamic-alignment))} [:span (if (contains? layout :dynamic-alignment) - (t locale "workspace.header.menu.disable-dynamic-alignment") - (t locale "workspace.header.menu.enable-dynamic-alignment"))] + (tr "workspace.header.menu.disable-dynamic-alignment") + (tr "workspace.header.menu.enable-dynamic-alignment"))] [:span.shortcut "Ctrl+a"]] (if (:is-shared file) [:li {:on-click on-remove-shared} - [:span (t locale "dashboard.remove-shared")]] + [:span (tr "dashboard.remove-shared")]] [:li {:on-click on-add-shared} - [:span (t locale "dashboard.add-shared")]]) + [:span (tr "dashboard.add-shared")]]) ]]])) ;; --- Header Component (mf/defc header [{:keys [file layout project page-id] :as props}] - (let [team-id (:team-id project) - go-back #(st/emit! (rt/nav :dashboard-projects {:team-id team-id})) - zoom (mf/deref refs/selected-zoom) - locale (mf/deref i18n/locale) - router (mf/deref refs/router) - view-url (rt/resolve router :viewer {:page-id page-id :file-id (:id file)} {:index 0})] + (let [team-id (:team-id project) + zoom (mf/deref refs/selected-zoom) + router (mf/deref refs/router) + params {:page-id page-id :file-id (:id file)} + view-url (rt/resolve router :viewer params {:index 0}) + + go-back + (mf/use-callback + (mf/deps project) + (st/emitf (rt/nav :dashboard-projects {:team-id team-id}))) + + go-viewer + (mf/use-callback + (mf/deps file page-id) + (st/emitf (dw/go-to-viewer params)))] + [:header.workspace-header [:div.main-icon [:a {:on-click go-back} i/logo-icon]] @@ -259,7 +269,8 @@ :on-zoom-selected #(st/emit! dw/zoom-to-selected-shape)}] [:a.btn-icon-dark.btn-small.tooltip.tooltip-bottom - {;; :target "__blank" - :alt (t locale "workspace.header.viewer") - :href (str "#" view-url)} i/play]]])) + {:alt (tr "workspace.header.viewer") + :href (str "#" view-url) + :on-click go-viewer} + i/play]]])) From 2dafbeddb0f5742e864c8b7f3bc72947c1b853e0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 12:10:34 +0100 Subject: [PATCH 038/195] :paperclip: Minor code cleaning on workspace header components. --- frontend/src/app/main/data/workspace.cljs | 1 - .../src/app/main/ui/workspace/header.cljs | 47 +++++++++---------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index ce2aa0c890..df467de3f1 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -41,7 +41,6 @@ [beicon.core :as rx] [cljs.spec.alpha :as s] [clojure.set :as set] - [clojure.set :as set] [cuerdas.core :as str] ;; [cljs.pprint :refer [pprint]] [potok.core :as ptk])) diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 7209d0231d..29cbdf18bb 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -9,23 +9,21 @@ (ns app.main.ui.workspace.header (:require - [okulary.core :as l] - [rumext.alpha :as mf] - [app.main.ui.icons :as i :include-macros true] + [app.common.math :as mth] [app.config :as cfg] - [app.main.data.history :as udh] + [app.main.data.modal :as modal] [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] - [app.main.data.modal :as modal] - [app.main.ui.workspace.presence :as presence] + [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] - [app.util.i18n :as i18n :refer [t]] - [app.util.data :refer [classnames]] + [app.main.ui.workspace.presence :refer [active-sessions]] [app.util.dom :as dom] - [app.common.math :as mth] - [app.util.router :as rt])) + [app.util.i18n :as i18n :refer [tr]] + [app.util.router :as rt] + [okulary.core :as l] + [rumext.alpha :as mf])) ;; --- Zoom Widget @@ -34,28 +32,28 @@ (mf/defc persistence-state-widget {::mf/wrap [mf/memo]} - [{:keys [locale]}] + [] (let [data (mf/deref workspace-persistence-ref)] [:div.persistence-status-widget (cond (= :pending (:status data)) [:div.pending - [:span.label (t locale "workspace.header.unsaved")]] + [:span.label (tr "workspace.header.unsaved")]] (= :saving (:status data)) [:div.saving [:span.icon i/toggle] - [:span.label (t locale "workspace.header.saving")]] + [:span.label (tr "workspace.header.saving")]] (= :saved (:status data)) [:div.saved [:span.icon i/tick] - [:span.label (t locale "workspace.header.saved")]] + [:span.label (tr "workspace.header.saved")]] (= :error (:status data)) [:div.error {:title "There was an error saving the data. Please refresh if this persists."} [:span.icon i/msg-warning] - [:span.label (t locale "workspace.header.save-error")]])])) + [:span.label (tr "workspace.header.save-error")]])])) (mf/defc zoom-widget @@ -108,10 +106,10 @@ (st/emitf (modal/show {:type :confirm :message "" - :title (t locale "modals.add-shared-confirm.message" (:name file)) - :hint (t locale "modals.add-shared-confirm.hint") + :title (tr "modals.add-shared-confirm.message" (:name file)) + :hint (tr "modals.add-shared-confirm.hint") :cancel-label :omit - :accept-label (t locale "modals.add-shared-confirm.accept") + :accept-label (tr "modals.add-shared-confirm.accept") :accept-style :primary :on-accept add-shared-fn}))) @@ -121,10 +119,10 @@ (st/emitf (modal/show {:type :confirm :message "" - :title (t locale "modals.remove-shared-confirm.message" (:name file)) - :hint (t locale "modals.remove-shared-confirm.hint") + :title (tr "modals.remove-shared-confirm.message" (:name file)) + :hint (tr "modals.remove-shared-confirm.hint") :cancel-label :omit - :accept-label (t locale "modals.remove-shared-confirm.accept") + :accept-label (tr "modals.remove-shared-confirm.accept") :on-accept del-shared-fn}))) @@ -146,7 +144,7 @@ [:div.menu-section [:div.btn-icon-dark.btn-small {:on-click #(reset! show-menu? true)} i/actions] - [:div.project-tree {:alt (t locale "workspace.sitemap")} + [:div.project-tree {:alt (tr "workspace.sitemap")} [:span.project-name {:on-click #(st/emit! (rt/navigate :dashboard-project {:team-id team-id :project-id (:project-id file)}))} @@ -254,11 +252,10 @@ :team-id team-id}] [:div.users-section - [:& presence/active-sessions]] + [:& active-sessions]] [:div.options-section - [:& persistence-state-widget - {:locale locale}] + [:& persistence-state-widget] [:& zoom-widget {:zoom zoom From 013c8661371a4cbb0c4396d5b3cd8041d384b156 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 13:52:21 +0100 Subject: [PATCH 039/195] :sparkles: Simplify users loading on dashboard and workspace. And fix some issues on teams settings page. --- backend/src/app/services/queries/files.clj | 33 ---------- backend/src/app/services/queries/teams.clj | 55 ++++++++++++++-- backend/src/app/services/queries/viewer.clj | 4 +- frontend/resources/locales.json | 13 ++++ frontend/src/app/main/data/dashboard.cljs | 21 +++---- frontend/src/app/main/data/users.cljs | 45 +++++++++---- frontend/src/app/main/data/workspace.cljs | 1 - .../main/data/workspace/notifications.cljs | 2 +- .../app/main/data/workspace/persistence.cljs | 4 +- frontend/src/app/main/refs.cljs | 6 +- .../src/app/main/ui/dashboard/comments.cljs | 11 +--- frontend/src/app/main/ui/dashboard/team.cljs | 63 ++++++++++--------- .../src/app/main/ui/workspace/comments.cljs | 4 +- 13 files changed, 151 insertions(+), 111 deletions(-) diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index 12b2764ea2..8047e37d91 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -185,39 +185,6 @@ (let [file (retrieve-file conn file-id)] (get-in file [:data :pages-index id])))) -;; --- Query: File users - -(def ^:private sql:file-users - "select pf.id, pf.fullname, pf.photo - from profile as pf - inner join file_profile_rel as fpr on (fpr.profile_id = pf.id) - where fpr.file_id = ? - union - select pf.id, pf.fullname, pf.photo - from profile as pf - inner join project_profile_rel as ppr on (ppr.profile_id = pf.id) - inner join file as f on (f.project_id = ppr.project_id) - where f.id = ? - union - select pf.id, pf.fullname, pf.photo - from profile as pf - inner join team_profile_rel as tpr on (tpr.profile_id = pf.id) - inner join project as p on (tpr.team_id = p.team_id) - inner join file as f on (p.id = f.project_id) - where f.id = ?") - -(defn retrieve-file-users - [conn id] - (db/exec! conn [sql:file-users id id id])) - -(s/def ::file-users - (s/keys :req-un [::profile-id ::id])) - -(sq/defquery ::file-users - [{:keys [profile-id id] :as params}] - (db/with-atomic [conn db/pool] - (check-edition-permissions! conn profile-id id) - (retrieve-file-users conn id))) ;; --- Query: Shared Library Files diff --git a/backend/src/app/services/queries/teams.clj b/backend/src/app/services/queries/teams.clj index 594ba5633b..e5191bca3f 100644 --- a/backend/src/app/services/queries/teams.clj +++ b/backend/src/app/services/queries/teams.clj @@ -131,8 +131,29 @@ [conn team-id] (db/exec! conn [sql:team-members team-id])) + ;; --- Query: Team Users +(declare retrieve-users) +(declare retrieve-team-for-file) + +(s/def ::file-id ::us/uuid) +(s/def ::team-users + (s/and (s/keys :req-un [::profile-id] + :opt-un [::team-id ::file-id]) + #(or (:team-id %) (:file-id %)))) + +(sq/defquery ::team-users + [{:keys [profile-id team-id file-id]}] + (with-open [conn (db/open)] + (if team-id + (do + (check-edition-permissions! conn profile-id team-id) + (retrieve-users conn team-id)) + (let [{team-id :id} (retrieve-team-for-file conn file-id)] + (check-edition-permissions! conn profile-id team-id) + (retrieve-users conn team-id))))) + ;; This is a similar query to team members but can contain more data ;; because some user can be explicitly added to project or file (not ;; implemented in UI) @@ -156,12 +177,38 @@ inner join project as p on (f.project_id = p.id) where p.team_id = ?") -(s/def ::team-users +(def sql:team-by-file + "select p.team_id as id + from project as p + join file as f on (p.id = f.project_id) + where f.id = ?") + +(defn retrieve-users + [conn team-id] + (db/exec! conn [sql:team-users team-id team-id team-id])) + +(defn retrieve-team-for-file + [conn file-id] + (->> [sql:team-by-file file-id] + (db/exec-one! conn))) + +;; --- Query: Team Stats + +(declare retrieve-team-stats) + +(s/def ::team-stats (s/keys :req-un [::profile-id ::team-id])) -(sq/defquery ::team-users +(sq/defquery ::team-stats [{:keys [profile-id team-id]}] (with-open [conn (db/open)] - (check-edition-permissions! conn profile-id team-id) - (db/exec! conn [sql:team-users team-id team-id team-id]))) + (check-read-permissions! conn profile-id team-id) + (retrieve-team-stats conn team-id))) +(def sql:team-stats + "select (select count(*) from project where team_id = ?) as projects, + (select count(*) from file as f join project as p on (p.id = f.project_id) where p.team_id = ?) as files") + +(defn retrieve-team-stats + [conn team-id] + (db/exec-one! conn [sql:team-stats team-id team-id])) diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index 0174f5b12d..38cd87221e 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -14,6 +14,7 @@ [app.db :as db] [app.services.queries :as sq] [app.services.queries.files :as files] + [app.services.queries.teams :as teams] [clojure.spec.alpha :as s])) ;; --- Query: Viewer Bundle (by Page ID) @@ -50,13 +51,14 @@ file (merge (dissoc file :data) (select-keys (:data file) [:colors :media :typographies])) libs (files/retrieve-file-libraries conn false file-id) - users (files/retrieve-file-users conn file-id) + users (teams/retrieve-users conn (:team-id project)) bundle {:file file :page page :users users :project project :libraries libs}] + (if (string? token) (do (check-shared-token! conn file-id page-id token) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 30e1542718..1954e34091 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -460,6 +460,19 @@ "es" : "+ Nuevo proyecto" } }, + + "labels.num-of-projects" : { + "translations" : { + "en" : ["1 project", "%s projects"] + } + }, + + "labels.num-of-files" : { + "translations" : { + "en" : ["1 file", "%s files"] + } + }, + "dashboard.no-matches-for" : { "used-in" : [ "src/app/main/ui/dashboard/search.cljs:48" ], "translations" : { diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 862a90ba77..395503836f 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -11,6 +11,7 @@ [app.common.spec :as us] [app.common.uuid :as uuid] [app.main.repo :as rp] + [app.main.data.users :as du] [app.util.router :as rt] [app.util.time :as dt] [app.util.timers :as ts] @@ -89,18 +90,14 @@ (->> (rp/query :team-members {:team-id id}) (rx/map #(partial fetched %))))))) - -(defn fetch-team-users - [{:keys [id] :as params}] +(defn fetch-team-stats + [{:keys [id] :as team}] (us/assert ::us/uuid id) - (letfn [(fetched [users state] - (->> (map #(avatars/assoc-avatar % :fullname) users) - (d/index-by :id) - (assoc-in state [:team-users id])))] - (ptk/reify ::fetch-team-users - ptk/WatchEvent - (watch [_ state stream] - (->> (rp/query :team-users {:team-id id}) + (ptk/reify ::fetch-team-members + ptk/WatchEvent + (watch [_ state stream] + (let [fetched #(assoc-in %2 [:team-stats id] %1)] + (->> (rp/query :team-stats {:team-id id}) (rx/map #(partial fetched %))))))) ;; --- Fetch Projects @@ -125,7 +122,7 @@ (let [profile (:profile state)] (->> (rx/merge (ptk/watch (fetch-team params) state stream) (ptk/watch (fetch-projects {:team-id id}) state stream) - (ptk/watch (fetch-team-users params) state stream)) + (ptk/watch (du/fetch-users {:team-id id}) state stream)) (rx/catch (fn [{:keys [type code] :as error}] (cond (and (= :not-found type) diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs index 56b624ae98..31da7e8a38 100644 --- a/frontend/src/app/main/data/users.cljs +++ b/frontend/src/app/main/data/users.cljs @@ -2,25 +2,29 @@ ;; 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) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.data.users (:require + [app.config :as cfg] + [app.common.data :as d] + [app.common.spec :as us] + [app.main.data.media :as di] + [app.main.data.messages :as dm] + [app.main.repo :as rp] + [app.main.store :as st] + [app.util.avatars :as avatars] + [app.util.i18n :as i18n :refer [tr]] + [app.util.router :as rt] + [app.util.storage :refer [storage]] + [app.util.theme :as theme] [beicon.core :as rx] [cljs.spec.alpha :as s] [cuerdas.core :as str] - [potok.core :as ptk] - [app.common.spec :as us] - [app.config :as cfg] - [app.main.store :as st] - [app.main.repo :as rp] - [app.main.data.messages :as dm] - [app.main.data.media :as di] - [app.util.router :as rt] - [app.util.i18n :as i18n :refer [tr]] - [app.util.storage :refer [storage]] - [app.util.avatars :as avatars] - [app.util.theme :as theme])) + [potok.core :as ptk])) ;; --- Common Specs @@ -179,3 +183,18 @@ (rx/map (constantly fetch-profile)) (rx/catch on-error)))))) + +(defn fetch-users + [{:keys [team-id] :as params}] + (us/assert ::us/uuid team-id) + (letfn [(fetched [users state] + (->> (map #(avatars/assoc-avatar % :fullname) users) + (d/index-by :id) + (assoc state :users)))] + (ptk/reify ::fetch-team-users + ptk/WatchEvent + (watch [_ state stream] + (->> (rp/query :team-users {:team-id team-id}) + (rx/map #(partial fetched %))))))) + + diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index df467de3f1..71ee25648d 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -203,7 +203,6 @@ :workspace-file :workspace-project :workspace-media-objects - :workspace-users :workspace-persistence)) ptk/WatchEvent diff --git a/frontend/src/app/main/data/workspace/notifications.cljs b/frontend/src/app/main/data/workspace/notifications.cljs index a0ae74a6b5..28008bdfc5 100644 --- a/frontend/src/app/main/data/workspace/notifications.cljs +++ b/frontend/src/app/main/data/workspace/notifications.cljs @@ -163,7 +163,7 @@ (ptk/reify ::handle-presence ptk/UpdateEvent (update [_ state] - (let [profiles (:workspace-users state)] + (let [profiles (:users state)] (update state :workspace-presence update-sessions profiles)))))) (defn handle-pointer-update diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index c36c702c54..098464d405 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -207,7 +207,7 @@ ptk/WatchEvent (watch [_ state stream] (->> (rx/zip (rp/query :file {:id file-id}) - (rp/query :file-users {:id file-id}) + (rp/query :team-users {:file-id file-id}) (rp/query :project {:id project-id}) (rp/query :file-libraries {:file-id file-id})) (rx/first) @@ -238,11 +238,11 @@ (update [_ state] (let [users (map avatars/assoc-profile-avatar users)] (assoc state + :users (d/index-by :id users) :workspace-undo {} :workspace-project project :workspace-file file :workspace-data (:data file) - :workspace-users (d/index-by :id users) :workspace-libraries (d/index-by :id libraries)))))) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 58fa20a6ed..124235bbbd 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -122,9 +122,6 @@ (def workspace-libraries (l/derived :workspace-libraries st/state)) -(def workspace-users - (l/derived :workspace-users st/state)) - (def workspace-presence (l/derived :workspace-presence st/state)) @@ -214,3 +211,6 @@ (def comments-local (l/derived :comments-local st/state)) +(def users + (l/derived :users st/state)) + diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index 3febd79e1d..81aeb1c1c5 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -35,14 +35,8 @@ [cuerdas.core :as str] [rumext.alpha :as mf])) - -(defn team-members-ref - [{:keys [id] :as team}] - (l/derived (l/in [:team-users id]) st/state)) - (mf/defc comments-section [{:keys [profile team]}] - (mf/use-effect (mf/deps team) (st/emitf (dcm/retrieve-unread-comment-threads (:id team)))) @@ -51,9 +45,7 @@ show-dropdown (mf/use-fn #(reset! show-dropdown? true)) hide-dropdown (mf/use-fn #(reset! show-dropdown? false)) threads-map (mf/deref refs/comment-threads) - - users-ref (mf/use-memo (mf/deps team) #(team-members-ref team)) - users (mf/deref users-ref) + users (mf/deref refs/users) tgroups (->> (vals threads-map) (sort-by :modified-at) @@ -61,7 +53,6 @@ (dcm/apply-filters {} profile) (dcm/group-threads-by-file-and-page)) - on-navigate (mf/use-callback (fn [thread] diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 02cee28008..407a3d239c 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -25,7 +25,7 @@ [app.main.ui.dashboard.team-form] [app.main.ui.icons :as i] [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [t tr]] + [app.util.i18n :as i18n :refer [tr]] [app.util.router :as rt] [app.util.time :as dt] [cljs.spec.alpha :as s] @@ -34,7 +34,7 @@ (mf/defc header {::mf/wrap [mf/memo]} - [{:keys [section locale team] :as props}] + [{:keys [section team] :as props}] (let [go-members (mf/use-callback (mf/deps team) @@ -57,19 +57,19 @@ [:header.dashboard-header [:div.dashboard-title [:h1 (cond - members-section? (t locale "labels.members") - settings-section? (t locale "labels.settings") + members-section? (tr "labels.members") + settings-section? (tr "labels.settings") nil)]] [:nav [:ul [:li {:class (when members-section? "active")} - [:a {:on-click go-members} (t locale "labels.members")]] + [:a {:on-click go-members} (tr "labels.members")]] [:li {:class (when settings-section? "active")} - [:a {:on-click go-settings} (t locale "labels.settings")]]]] + [:a {:on-click go-settings} (tr "labels.settings")]]]] (if members-section? [:a.btn-secondary.btn-small {:on-click invite-member} - (t locale "dashboard.invite-profile")] + (tr "dashboard.invite-profile")] [:div])])) (s/def ::email ::us/email) @@ -220,13 +220,12 @@ [:& team-member {:member item :team team :profile profile :key (:id item)}])]])) (defn- members-ref - [team-id] - (l/derived (l/in [:team-members team-id]) st/state)) + [{:keys [id] :as team}] + (l/derived (l/in [:team-members id]) st/state)) (mf/defc team-members-page [{:keys [team profile] :as props}] - (let [locale (mf/deref i18n/locale) - members-ref (mf/use-memo (mf/deps team) #(members-ref (:id team))) + (let [members-ref (mf/use-memo (mf/deps team) #(members-ref team)) members-map (mf/deref members-ref)] (mf/use-effect @@ -234,24 +233,30 @@ (st/emitf (dd/fetch-team-members team))) [:* - [:& header {:locale locale - :section :dashboard-team-members + [:& header {:section :dashboard-team-members :team team}] [:section.dashboard-container.dashboard-team-members - [:& team-members {:locale locale - :profile profile + [:& team-members {:profile profile :team team :members-map members-map}]]])) +(defn- stats-ref + [{:keys [id] :as team}] + (l/derived (l/in [:team-stats id]) st/state)) (mf/defc team-settings-page [{:keys [team profile] :as props}] - (let [locale (mf/deref i18n/locale) - finput (mf/use-ref) + (let [finput (mf/use-ref) - members-ref (mf/use-memo (mf/deps team) #(members-ref (:id team))) + members-ref (mf/use-memo (mf/deps team) #(members-ref team)) members-map (mf/deref members-ref) + owner (->> (vals members-map) + (d/seek :is-owner)) + + stats-ref (mf/use-memo (mf/deps team) #(stats-ref team)) + stats (mf/deref stats-ref) + on-image-click (mf/use-callback #(dom/click (mf/ref-val finput))) @@ -264,17 +269,17 @@ (mf/use-effect (mf/deps team) - (st/emitf (dd/fetch-team-members team))) + (st/emitf (dd/fetch-team-members team) + (dd/fetch-team-stats team))) [:* - [:& header {:locale locale - :section :dashboard-team-settings + [:& header {:section :dashboard-team-settings :team team}] [:section.dashboard-container.dashboard-team-settings [:div.team-settings [:div.horizontal-blocks [:div.block.info-block - [:div.label (t locale "dashboard.team-info")] + [:div.label (tr "dashboard.team-info")] [:div.name (:name team)] [:div.icon [:span.update-overlay {:on-click on-image-click} i/exit] @@ -285,19 +290,19 @@ :on-selected on-file-selected}]]] [:div.block.owner-block - [:div.label (t locale "dashboard.team-members")] + [:div.label (tr "dashboard.team-members")] [:div.owner - [:span.icon [:img {:src (cfg/resolve-media-path (:photo-uri profile))}]] - [:span.text (str (:fullname profile) " (" (t locale "labels.owner") ")") ]] + [:span.icon [:img {:src (cfg/resolve-media-path (:photo owner))}]] + [:span.text (str (:name owner) " (" (tr "labels.owner") ")") ]] [:div.summary [:span.icon i/user] - [:span.text (t locale "dashboard.num-of-members" (count members-map))]]] + [:span.text (tr "dashboard.num-of-members" (count members-map))]]] [:div.block.stats-block - [:div.label (t locale "dashboard.team-projects")] + [:div.label (tr "dashboard.team-projects")] [:div.projects [:span.icon i/folder] - [:span.text "4 projects"]] + [:span.text (tr "labels.num-of-projects" (i18n/c (:projects stats)))]] [:div.files [:span.icon i/file-html] - [:span.text "4 files"]]]]]]])) + [:span.text (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]])) diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index a753f60ae4..f7cc52b524 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -36,7 +36,7 @@ pos-y (* (- (:y vbox)) zoom) profile (mf/deref refs/profile) - users (mf/deref refs/workspace-users) + users (mf/deref refs/users) local (mf/deref refs/comments-local) threads-map (mf/deref threads-ref) @@ -132,7 +132,7 @@ [] (let [threads-map (mf/deref threads-ref) profile (mf/deref refs/profile) - users (mf/deref refs/workspace-users) + users (mf/deref refs/users) local (mf/deref refs/comments-local) options? (mf/use-state false) From 061fdcd5bd6c61957d5ef921dc362af0670db210 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 15:06:49 +0100 Subject: [PATCH 040/195] :bug: Fix many issues relted to comments on viewer. --- backend/src/app/services/queries/viewer.clj | 2 +- .../styles/main/partials/comments.scss | 1 + frontend/src/app/main/data/viewer.cljs | 47 +++++++++++-------- frontend/src/app/main/ui/comments.cljs | 2 +- frontend/src/app/main/ui/viewer.cljs | 8 ++-- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index 38cd87221e..27d52a88ab 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -24,7 +24,7 @@ (def ^:private sql:project - "select p.id, p.name + "select p.id, p.name, p.team_id from project as p where p.id = ? and p.deleted_at is null") diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss index b15588d898..59e46351d8 100644 --- a/frontend/resources/styles/main/partials/comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -45,6 +45,7 @@ .comments { max-height: 320px; + min-height: 105px; overflow-y: auto; } diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 3aa7058f50..635c155690 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -9,19 +9,21 @@ (ns app.main.data.viewer (:require - [cljs.spec.alpha :as s] - [beicon.core :as rx] - [potok.core :as ptk] + [app.common.data :as d] + [app.common.exceptions :as ex] + [app.common.pages :as cp] + [app.common.pages-helpers :as cph] + [app.common.spec :as us] + [app.common.uuid :as uuid] [app.main.constants :as c] [app.main.repo :as rp] [app.main.store :as st] - [app.common.spec :as us] - [app.common.pages :as cp] - [app.common.data :as d] - [app.common.exceptions :as ex] + [app.main.data.comments :as dcm] + [app.util.avatars :as avatars] [app.util.router :as rt] - [app.common.uuid :as uuid] - [app.common.pages-helpers :as cph])) + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [potok.core :as ptk])) ;; --- General Specs @@ -149,7 +151,8 @@ ptk/UpdateEvent (update [_ state] (let [objects (:objects page) - frames (extract-frames objects)] + frames (extract-frames objects) + users (map #(avatars/assoc-avatar % :fullname) users)] (-> state (assoc :viewer-libraries (d/index-by :id libraries) :viewer-data {:project project @@ -240,7 +243,9 @@ pparams (:path-params route) index (:index qparams)] (when (pos? index) - (rx/of (rt/nav screen pparams (assoc qparams :index (dec index))))))))) + (rx/of + (dcm/close-thread) + (rt/nav screen pparams (assoc qparams :index (dec index))))))))) (def select-next-frame (ptk/reify ::select-prev-frame @@ -253,7 +258,9 @@ index (:index qparams) total (count (get-in state [:viewer-data :frames]))] (when (< index (dec total)) - (rx/of (rt/nav screen pparams (assoc qparams :index (inc index))))))))) + (rx/of + (dcm/close-thread) + (rt/nav screen pparams (assoc qparams :index (inc index))))))))) (s/def ::interactions-mode #{:hide :show :show-on-click}) @@ -387,12 +394,12 @@ ;; --- Shortcuts (def shortcuts - {"+" #(st/emit! increase-zoom) - "-" #(st/emit! decrease-zoom) - "ctrl+a" #(st/emit! (select-all)) - "shift+0" #(st/emit! zoom-to-50) - "shift+1" #(st/emit! reset-zoom) - "shift+2" #(st/emit! zoom-to-200) - "left" #(st/emit! select-prev-frame) - "right" #(st/emit! select-next-frame)}) + {"+" (st/emitf increase-zoom) + "-" (st/emitf decrease-zoom) + "ctrl+a" (st/emitf (select-all)) + "shift+0" (st/emitf zoom-to-50) + "shift+1" (st/emitf reset-zoom) + "shift+2" (st/emitf zoom-to-200) + "left" (st/emitf select-prev-frame) + "right" (st/emitf select-next-frame)}) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index b09fe8f923..a16dec9e70 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -185,7 +185,7 @@ (mf/defc comment-item [{:keys [comment thread users] :as props}] (let [owner (get users (:owner-id comment)) - profile (mf/use-state refs/profile) + profile (mf/deref refs/profile) options (mf/use-state false) edition? (mf/use-state false) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 73017aaeb3..74fc8f1623 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -78,7 +78,7 @@ on-click (mf/use-callback - (mf/deps cstate data) + (mf/deps cstate data frame) (fn [event] (dom/stop-propagation event) (if (some? (:open cstate)) @@ -98,13 +98,11 @@ on-draft-submit (mf/use-callback + (mf/deps frame) (fn [draft] (let [params (update draft :position gpt/transform modifier2)] - ;; (prn "on-draft-submit" params) - (st/emit! (dcm/create-thread params) - (dcm/close-thread))))) - ] + (dcm/close-thread)))))] [:div.comments-section {:on-click on-click} [:div.viewer-comments-container From cc667d63cdd0b2c6c213548874cf4d54040915a5 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 15:10:39 +0100 Subject: [PATCH 041/195] :bug: Add autofocus on comment creation input. --- frontend/src/app/main/ui/comments.cljs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index a16dec9e70..3d989b0918 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -36,6 +36,8 @@ placeholder (obj/get props "placeholder") on-change (obj/get props "on-change") on-esc (obj/get props "on-esc") + autofocus? (obj/get props "autofocus") + ref (mf/use-ref) on-key-down @@ -62,6 +64,7 @@ [:textarea {:ref ref + :auto-focus autofocus? :on-key-down on-key-down :on-focus on-focus :on-blur on-blur @@ -150,6 +153,7 @@ [:div.reply-form [:& resizing-textarea {:placeholder (tr "labels.write-new-comment") :value (or content "") + :autofocus true :on-esc on-esc :on-change on-change}] [:div.buttons From 76df21083e369a52c4f11d8a865f0c9390f72359 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 17:33:08 +0100 Subject: [PATCH 042/195] :bug: Fix unexpected memoization on viewer header. --- frontend/src/app/main/ui/viewer/header.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 90aabdc953..36df5fca4f 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -200,6 +200,7 @@ {:page-id page-id}))) navigate (mf/use-callback + (mf/deps file-id page-id) (fn [section] (st/emit! (case section From f170c7546bd4f7fd53ed302a4f976a7963272d69 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 23 Nov 2020 17:36:47 +0100 Subject: [PATCH 043/195] :bug: Fix other unexpected memoization on viewer header. --- frontend/src/app/main/ui/viewer/header.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 36df5fca4f..3f23bd07c4 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -194,6 +194,7 @@ on-edit (mf/use-callback + (mf/deps project-id file-id page-id) (st/emitf (rt/nav :workspace {:project-id project-id :file-id file-id} From d25dbfb09b77b3f0341a3572245d83beb0d45914 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 3 Nov 2020 18:25:50 +0100 Subject: [PATCH 044/195] :recycle: Refactor drawing actions --- frontend/src/app/main/data/workspace.cljs | 1 - .../src/app/main/data/workspace/drawing.cljs | 283 ++---------------- .../app/main/data/workspace/drawing/box.cljs | 91 ++++++ .../main/data/workspace/drawing/common.cljs | 56 ++++ .../main/data/workspace/drawing/curve.cljs | 51 ++++ .../app/main/data/workspace/drawing/path.cljs | 116 +++++++ .../src/app/main/ui/workspace/drawarea.cljs | 4 +- .../app/main/ui/workspace/shapes/frame.cljs | 3 +- .../app/main/ui/workspace/shapes/path.cljs | 3 + 9 files changed, 341 insertions(+), 267 deletions(-) create mode 100644 frontend/src/app/main/data/workspace/drawing/box.cljs create mode 100644 frontend/src/app/main/data/workspace/drawing/common.cljs create mode 100644 frontend/src/app/main/data/workspace/drawing/curve.cljs create mode 100644 frontend/src/app/main/data/workspace/drawing/path.cljs diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 71ee25648d..f5107acda2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1150,7 +1150,6 @@ (us/verify ::us/uuid id) (us/verify ::us/integer index) (us/verify gpt/point? delta) - (js/alert "TODO: broken") #_(ptk/reify ::update-path ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index bfe1144180..b824f72c65 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -12,24 +12,14 @@ (:require [beicon.core :as rx] [potok.core :as ptk] - [app.common.geom.point :as gpt] - [app.common.geom.shapes :as geom] [app.common.pages :as cp] [app.common.uuid :as uuid] - [app.common.pages-helpers :as cph] - [app.common.uuid :as uuid] - [app.main.data.workspace :as dw] - [app.main.data.workspace.common :as dwc] - [app.main.snap :as snap] - [app.main.streams :as ms] - [app.util.geom.path :as path])) + [app.main.data.workspace.drawing.common :as common] + [app.main.data.workspace.drawing.path :as path] + [app.main.data.workspace.drawing.curve :as curve] + [app.main.data.workspace.drawing.box :as box])) (declare handle-drawing) -(declare handle-drawing-generic) -(declare handle-drawing-path) -(declare handle-drawing-curve) -(declare handle-finish-drawing) -(declare conditional-align) ;; NOTE/TODO: when an exception is raised in some point of drawing the ;; draw lock is not released so the user need to refresh in order to @@ -38,20 +28,22 @@ (defn start-drawing [type] {:pre [(keyword? type)]} - (let [id (uuid/next)] + (let [lock-id (uuid/next)] (ptk/reify ::start-drawing ptk/UpdateEvent (update [_ state] - (update-in state [:workspace-drawing :lock] #(if (nil? %) id %))) + (update-in state [:workspace-drawing :lock] #(if (nil? %) lock-id %))) ptk/WatchEvent (watch [_ state stream] (let [lock (get-in state [:workspace-drawing :lock])] - (when (= lock id) - (rx/merge (->> (rx/filter #(= % handle-finish-drawing) stream) - (rx/take 1) - (rx/map (fn [_] #(update % :workspace-drawing dissoc :lock)))) - (rx/of (handle-drawing type))))))))) + (when (= lock lock-id) + (rx/merge + (rx/of (handle-drawing type)) + (->> stream + (rx/filter (ptk/type? ::common/handle-finish-drawing) ) + (rx/first) + (rx/map #(fn [state] (update state :workspace-drawing dissoc :lock))))))))))) (defn handle-drawing [type] @@ -63,248 +55,13 @@ ptk/WatchEvent (watch [_ state stream] - (case type - :path (rx/of handle-drawing-path) - :curve (rx/of handle-drawing-curve) - (rx/of handle-drawing-generic))))) + (rx/of (case type + :path + path/handle-drawing-path -(def handle-drawing-generic - (letfn [(resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] - (let [;; The new shape behaves like a resize on the bottom-right corner - initial (gpt/point (+ x width) (+ y height)) - shapev (gpt/point width height) - deltav (gpt/to-vec initial point-snap) - scalev (gpt/divide (gpt/add shapev deltav) shapev) - scalev (if lock? - (let [v (max (:x scalev) (:y scalev))] - (gpt/point v v)) - scalev)] - (-> shape - (assoc ::click-draw? false) - (assoc-in [:modifiers :resize-vector] scalev) - (assoc-in [:modifiers :resize-origin] (gpt/point x y)) - (assoc-in [:modifiers :resize-rotation] 0)))) + :curve + curve/handle-drawing-curve - (update-drawing [state point lock? point-snap] - (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))] - - (ptk/reify ::handle-drawing-generic - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - - stoper? #(or (ms/mouse-up? %) (= % :interrupt)) - stoper (rx/filter stoper? stream) - initial @ms/mouse-position - - - page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - layout (get state :workspace-layout) - - frames (cph/select-frames objects) - fid (or (->> frames - (filter #(geom/has-point? % initial)) - first - :id) - uuid/zero) - - shape (-> state - (get-in [:workspace-drawing :object]) - (geom/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) - (assoc :frame-id fid) - (assoc ::initialized? true) - (assoc ::click-draw? true))] - (rx/concat - ;; Add shape to drawing state - (rx/of #(assoc-in state [:workspace-drawing :object] shape)) - - ;; Initial SNAP - (->> (snap/closest-snap-point page-id [shape] layout initial) - (rx/map (fn [{:keys [x y]}] - #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) - - (->> ms/mouse-position - (rx/filter #(> (gpt/distance % initial) 2)) - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/switch-map - (fn [[point :as current]] - (->> (snap/closest-snap-point page-id [shape] layout point) - (rx/map #(conj current %))))) - (rx/map - (fn [[pt ctrl? point-snap]] - #(update-drawing % pt ctrl? point-snap))) - - (rx/take-until stoper)) - (rx/of handle-finish-drawing))))))) - -(def handle-drawing-path - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (or (= event :path/end-path-drawing) - (= event :interrupt) - (and (ms/mouse-event? event) - (or (= type :double-click) - (= type :context-menu))) - (and (ms/keyboard-event? event) - (= type :down) - (= 13 (:key event))))) - - (initialize-drawing [state point] - (-> state - (assoc-in [:workspace-drawing :object :segments] [point point]) - (assoc-in [:workspace-drawing :object ::initialized?] true))) - - (insert-point-segment [state point] - (-> state - (update-in [:workspace-drawing :object :segments] (fnil conj []) point))) - - (update-point-segment [state index point] - (let [segments (count (get-in state [:workspace-drawing :object :segments])) - exists? (< -1 index segments)] - (cond-> state - exists? (assoc-in [:workspace-drawing :object :segments index] point)))) - - (finish-drawing-path [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] (-> shape - (update :segments #(vec (butlast %))) - (geom/update-path-selrect)))))] - - (ptk/reify ::handle-drawing-path - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - - last-point (volatile! @ms/mouse-position) - - stoper (->> (rx/filter stoper-event? stream) - (rx/share)) - - mouse (rx/sample 10 ms/mouse-position) - - points (->> stream - (rx/filter ms/mouse-click?) - (rx/filter #(false? (:shift %))) - (rx/with-latest vector mouse) - (rx/map second)) - - counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) - - stream' (->> mouse - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/with-latest vector counter) - (rx/map flatten)) - - imm-transform #(vector (- % 7) (+ % 7) %) - immanted-zones (vec (concat - (map imm-transform (range 0 181 15)) - (map (comp imm-transform -) (range 0 181 15)))) - - align-position (fn [angle pos] - (reduce (fn [pos [a1 a2 v]] - (if (< a1 angle a2) - (reduced (gpt/update-angle pos v)) - pos)) - pos - immanted-zones))] - - (rx/merge - (rx/of #(initialize-drawing % @last-point)) - - (->> points - (rx/take-until stoper) - (rx/map (fn [pt] #(insert-point-segment % pt)))) - - (rx/concat - (->> stream' - (rx/take-until stoper) - (rx/map (fn [[point ctrl? index :as xxx]] - (let [point (if ctrl? - (as-> point $ - (gpt/subtract $ @last-point) - (align-position (gpt/angle $) $) - (gpt/add $ @last-point)) - point)] - #(update-point-segment % index point))))) - (rx/of finish-drawing-path - handle-finish-drawing)))))))) - -(def simplify-tolerance 0.3) - -(def handle-drawing-curve - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (ms/mouse-event? event) (= type :up)) - - (initialize-drawing [state] - (assoc-in state [:workspace-drawing :object ::initialized?] true)) - - (insert-point-segment [state point] - (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) - - (finish-drawing-curve [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] - (-> shape - (update :segments #(path/simplify % simplify-tolerance)) - (geom/update-path-selrect)))))] - - (ptk/reify ::handle-drawing-curve - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - stoper (rx/filter stoper-event? stream) - mouse (rx/sample 10 ms/mouse-position)] - (rx/concat - (rx/of initialize-drawing) - (->> mouse - (rx/map (fn [pt] #(insert-point-segment % pt))) - (rx/take-until stoper)) - (rx/of finish-drawing-curve - handle-finish-drawing))))))) - -(def handle-finish-drawing - (ptk/reify ::handle-finish-drawing - ptk/WatchEvent - (watch [_ state stream] - (let [shape (get-in state [:workspace-drawing :object])] - (rx/concat - (rx/of dw/clear-drawing) - (when (::initialized? shape) - (let [shape-click-width (case (:type shape) - :text 3 - 20) - shape-click-height (case (:type shape) - :text 16 - 20) - shape (if (::click-draw? shape) - (-> shape - (assoc-in [:modifiers :resize-vector] - (gpt/point shape-click-width shape-click-height)) - (assoc-in [:modifiers :resize-origin] - (gpt/point (:x shape) (:y shape)))) - shape) - - shape (cond-> shape - (= (:type shape) :text) (assoc :grow-type - (if (::click-draw? shape) :auto-width :fixed))) - - shape (-> shape - geom/transform-shape - (dissoc ::initialized? ::click-draw?))] - ;; Add & select the created shape to the workspace - (rx/concat - (if (= :text (:type shape)) - (rx/of dwc/start-undo-transaction) - (rx/empty)) - - (rx/of (dw/deselect-all) - (dw/add-shape shape)))))))))) - -(def close-drawing-path - (ptk/reify ::close-drawing-path - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:workspace-drawing :object :close?] true)))) + ;; default + box/handle-drawing-box))))) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs new file mode 100644 index 0000000000..74810d9b7a --- /dev/null +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -0,0 +1,91 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.data.workspace.drawing.box + (:require + [beicon.core :as rx] + [potok.core :as ptk] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.common.uuid :as uuid] + [app.common.pages-helpers :as cph] + [app.main.data.workspace.common :as dwc] + [app.main.snap :as snap] + [app.main.streams :as ms] + [app.main.data.workspace.drawing.common :as common])) + +(def handle-drawing-box + (letfn [(resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] + (let [;; The new shape behaves like a resize on the bottom-right corner + initial (gpt/point (+ x width) (+ y height)) + shapev (gpt/point width height) + deltav (gpt/to-vec initial point-snap) + scalev (gpt/divide (gpt/add shapev deltav) shapev) + scalev (if lock? + (let [v (max (:x scalev) (:y scalev))] + (gpt/point v v)) + scalev)] + (-> shape + (assoc :click-draw? false) + (assoc-in [:modifiers :resize-vector] scalev) + (assoc-in [:modifiers :resize-origin] (gpt/point x y)) + (assoc-in [:modifiers :resize-rotation] 0)))) + + (update-drawing [state point lock? point-snap] + (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))] + + (ptk/reify ::handle-drawing-box + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) + + stoper? #(or (ms/mouse-up? %) (= % :interrupt)) + stoper (rx/filter stoper? stream) + initial @ms/mouse-position + + + page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + layout (get state :workspace-layout) + + frames (cph/select-frames objects) + fid (or (->> frames + (filter #(gsh/has-point? % initial)) + first + :id) + uuid/zero) + + shape (-> state + (get-in [:workspace-drawing :object]) + (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) + (assoc :frame-id fid) + (assoc :initialized? true) + (assoc :click-draw? true))] + (rx/concat + ;; Add shape to drawing state + (rx/of #(assoc-in state [:workspace-drawing :object] shape)) + + ;; Initial SNAP + (->> (snap/closest-snap-point page-id [shape] layout initial) + (rx/map (fn [{:keys [x y]}] + #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) + + (->> ms/mouse-position + (rx/filter #(> (gpt/distance % initial) 2)) + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/switch-map + (fn [[point :as current]] + (->> (snap/closest-snap-point page-id [shape] layout point) + (rx/map #(conj current %))))) + (rx/map + (fn [[pt ctrl? point-snap]] + #(update-drawing % pt ctrl? point-snap))) + + (rx/take-until stoper)) + (rx/of common/handle-finish-drawing))))))) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs new file mode 100644 index 0000000000..a4d7938fe2 --- /dev/null +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -0,0 +1,56 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.data.workspace.drawing.common + (:require + [beicon.core :as rx] + [potok.core :as ptk] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.main.data.workspace :as dw] + [app.main.data.workspace.common :as dwc] + [app.main.streams :as ms])) + +(def handle-finish-drawing + (ptk/reify ::handle-finish-drawing + ptk/WatchEvent + (watch [_ state stream] + (let [shape (get-in state [:workspace-drawing :object])] + (rx/concat + (rx/of dw/clear-drawing) + (when (:initialized? shape) + (let [shape-click-width (case (:type shape) + :text 3 + 20) + shape-click-height (case (:type shape) + :text 16 + 20) + shape (if (:click-draw? shape) + (-> shape + (assoc-in [:modifiers :resize-vector] + (gpt/point shape-click-width shape-click-height)) + (assoc-in [:modifiers :resize-origin] + (gpt/point (:x shape) (:y shape)))) + shape) + + shape (cond-> shape + (= (:type shape) :text) (assoc :grow-type + (if (:click-draw? shape) :auto-width :fixed))) + + shape (-> shape + gsh/transform-shape + (dissoc :initialized? :click-draw?))] + ;; Add & select the created shape to the workspace + (rx/concat + (if (= :text (:type shape)) + (rx/of dwc/start-undo-transaction) + (rx/empty)) + + (rx/of (dw/deselect-all) + (dw/add-shape shape)))))))))) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs new file mode 100644 index 0000000000..c0685383b7 --- /dev/null +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -0,0 +1,51 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.data.workspace.drawing.curve + (:require + [beicon.core :as rx] + [potok.core :as ptk] + [app.common.geom.shapes :as gsh] + [app.main.streams :as ms] + [app.util.geom.path :as path] + [app.main.data.workspace.drawing.common :as common])) + +(def simplify-tolerance 0.3) + +(def handle-drawing-curve + (letfn [(stoper-event? [{:keys [type shift] :as event}] + (ms/mouse-event? event) (= type :up)) + + (initialize-drawing [state] + (assoc-in state [:workspace-drawing :object :initialized?] true)) + + (insert-point-segment [state point] + (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) + + (finish-drawing-curve [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] + (-> shape + (update :segments #(path/simplify % simplify-tolerance)) + (gsh/update-path-selrect)))))] + + (ptk/reify ::handle-drawing-curve + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) + stoper (rx/filter stoper-event? stream) + mouse (rx/sample 10 ms/mouse-position)] + (rx/concat + (rx/of initialize-drawing) + (->> mouse + (rx/map (fn [pt] #(insert-point-segment % pt))) + (rx/take-until stoper)) + (rx/of finish-drawing-curve + common/handle-finish-drawing))))))) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs new file mode 100644 index 0000000000..071b774fe2 --- /dev/null +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -0,0 +1,116 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.data.workspace.drawing.path + (:require + [beicon.core :as rx] + [potok.core :as ptk] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.main.streams :as ms] + [app.util.geom.path :as path] + [app.main.data.workspace.drawing.common :as common])) + +(def handle-drawing-path + (letfn [(stoper-event? [{:keys [type shift] :as event}] + (or (= event :path/end-path-drawing) + (= event :interrupt) + (and (ms/mouse-event? event) + (or (= type :double-click) + (= type :context-menu))) + (and (ms/keyboard-event? event) + (= type :down) + (= 13 (:key event))))) + + (initialize-drawing [state point] + (-> state + (assoc-in [:workspace-drawing :object :segments] [point point]) + (assoc-in [:workspace-drawing :object :initialized?] true))) + + (insert-point-segment [state point] + (-> state + (update-in [:workspace-drawing :object :segments] (fnil conj []) point))) + + (update-point-segment [state index point] + (let [segments (count (get-in state [:workspace-drawing :object :segments])) + exists? (< -1 index segments)] + (cond-> state + exists? (assoc-in [:workspace-drawing :object :segments index] point)))) + + (finish-drawing-path [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] (-> shape + (update :segments #(vec (butlast %))) + (gsh/update-path-selrect)))))] + + (ptk/reify ::handle-drawing-path + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) + + last-point (volatile! @ms/mouse-position) + + stoper (->> (rx/filter stoper-event? stream) + (rx/share)) + + mouse (rx/sample 10 ms/mouse-position) + + points (->> stream + (rx/filter ms/mouse-click?) + (rx/filter #(false? (:shift %))) + (rx/with-latest vector mouse) + (rx/map second)) + + counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) + + stream' (->> mouse + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/with-latest vector counter) + (rx/map flatten)) + + imm-transform #(vector (- % 7) (+ % 7) %) + immanted-zones (vec (concat + (map imm-transform (range 0 181 15)) + (map (comp imm-transform -) (range 0 181 15)))) + + align-position (fn [angle pos] + (reduce (fn [pos [a1 a2 v]] + (if (< a1 angle a2) + (reduced (gpt/update-angle pos v)) + pos)) + pos + immanted-zones))] + + (rx/merge + (rx/of #(initialize-drawing % @last-point)) + + (->> points + (rx/take-until stoper) + (rx/map (fn [pt] #(insert-point-segment % pt)))) + + (rx/concat + (->> stream' + (rx/take-until stoper) + (rx/map (fn [[point ctrl? index :as xxx]] + (let [point (if ctrl? + (as-> point $ + (gpt/subtract $ @last-point) + (align-position (gpt/angle $) $) + (gpt/add $ @last-point)) + point)] + #(update-point-segment % index point))))) + (rx/of finish-drawing-path + common/handle-finish-drawing)))))))) + +(def close-drawing-path + (ptk/reify ::close-drawing-path + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:workspace-drawing :object :close?] true)))) diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index 33143af7f8..e8d7fbab1e 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -51,8 +51,8 @@ (fn [event] (dom/stop-propagation event) (st/emit! (dw/assign-cursor-tooltip nil) - dd/close-drawing-path - :path/end-path-drawing)) + #_(dd/close-drawing-path) + #_:path/end-path-drawing)) on-mouse-enter (fn [event] diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 433b22f3f3..d1665317ba 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -110,6 +110,7 @@ (mf/use-callback (mf/deps (:id shape)) (fn [event] + (prn "?? FRAME") (dom/prevent-default event) (st/emit! (dw/deselect-all) (dw/select-shape (:id shape))))) @@ -131,7 +132,7 @@ (not (:hidden shape))) [:g {:class (when selected? "selected") :on-context-menu on-context-menu - :on-double-click on-double-click + ;; :on-double-click on-double-click :on-mouse-down on-mouse-down} [:& frame-title {:frame shape diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 81fd438163..66faed116d 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -30,15 +30,18 @@ [props] (let [shape (unchecked-get props "shape") hover? (or (mf/deref refs/current-hover) #{}) + on-mouse-down (mf/use-callback (mf/deps shape) #(common/on-mouse-down % shape)) on-context-menu (mf/use-callback (mf/deps shape) #(common/on-context-menu % shape)) + on-double-click (mf/use-callback (mf/deps shape) (fn [event] + (prn "?? PATH") (when (and (not (::dr/initialized? shape)) (hover? (:id shape))) (do (dom/stop-propagation event) From 67ed1d89ace4432c6e7130b57ff20a773a743c9a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 4 Nov 2020 22:07:49 +0100 Subject: [PATCH 045/195] :sparkles: Adds path parser --- frontend/src/app/main/data/workspace.cljs | 1 + .../src/app/main/data/workspace/drawing.cljs | 3 + .../app/main/data/workspace/drawing/path.cljs | 10 +- .../src/app/main/ui/workspace/drawarea.cljs | 3 +- frontend/src/app/util/geom/path.cljs | 185 +++++++++++++++++- 5 files changed, 196 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f5107acda2..ea2c54522b 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1757,6 +1757,7 @@ "e" #(st/emit! (select-for-drawing :circle)) "t" #(st/emit! dwtxt/start-edit-if-selected (select-for-drawing :text)) + "w" #(st/emit! (select-for-drawing :path)) "ctrl+c" #(st/emit! copy-selected) "ctrl+v" #(st/emit! paste) "ctrl+x" #(st/emit! copy-selected delete-selected) diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index b824f72c65..8aa948a429 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -65,3 +65,6 @@ ;; default box/handle-drawing-box))))) +;; Export +(def close-drawing-path path/close-drawing-path) + diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 071b774fe2..e1430b83ff 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -19,7 +19,7 @@ (def handle-drawing-path (letfn [(stoper-event? [{:keys [type shift] :as event}] - (or (= event :path/end-path-drawing) + (or (= event ::end-path-drawing) (= event :interrupt) (and (ms/mouse-event? event) (or (= type :double-click) @@ -109,8 +109,12 @@ (rx/of finish-drawing-path common/handle-finish-drawing)))))))) -(def close-drawing-path +(defn close-drawing-path [] (ptk/reify ::close-drawing-path ptk/UpdateEvent (update [_ state] - (assoc-in state [:workspace-drawing :object :close?] true)))) + (assoc-in state [:workspace-drawing :object :close?] true)) + + ptk/WatchEvent + (watch [_ state stream] + (rx/of ::end-path-drawing)))) diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index e8d7fbab1e..ae3f9cbb61 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -51,8 +51,7 @@ (fn [event] (dom/stop-propagation event) (st/emit! (dw/assign-cursor-tooltip nil) - #_(dd/close-drawing-path) - #_:path/end-path-drawing)) + (dd/close-drawing-path))) on-mouse-enter (fn [event] diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index 0ef6901919..c50a7ec78b 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -8,7 +8,10 @@ ;; Copyright (c) 2016-2017 Andrey Antukh (ns app.util.geom.path - (:require [app.util.geom.path-impl-simplify :as impl-simplify])) + (:require + [cuerdas.core :as str] + [app.common.data :as d] + [app.util.geom.path-impl-simplify :as impl-simplify])) (defn simplify ([points] @@ -16,3 +19,183 @@ ([points tolerance] (let [points (into-array points)] (into [] (impl-simplify/simplify points tolerance true))))) + +;; +(def commands-regex #"(?i)[a-z][^a-z]*") + +;; 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 #"([+-]?(([1-9]\d*(\.\d+)?)|(\.\d+)|0|1))") + + +(defn coord-n [size] + (re-pattern (str "(?i)[a-z]\\s*" + (->> (range size) + (map #(identity num-regex)) + (str/join "\\s+"))))) + + +(defn parse-params [cmd-str num-params] + (let [fix-starting-dot (fn [arg] (str/replace arg #"([^\d]|^)\." "$10."))] + (->> (re-seq num-regex cmd-str) + (map first) + (map fix-starting-dot) + (map d/read-string) + (partition num-params)))) + +(defn command->param-list [{:keys [command params]}] + (case command + (:move-to :line-to :smooth-quadratic-bezier-curve-to) + (let [{:keys [x y]} params] [x y]) + + :close-path + [] + + (:line-to-horizontal :line-to-vertical) + (let [{:keys [value]} params] [value]) + + :curve-to + (let [{:keys [c1x c1y c2x c2y x y]} params] [c1x c1y c2x c2y x y]) + + (:smooth-curve-to :quadratic-bezier-curve-to) + (let [{:keys [cx cy x y]} params] [cx cy x y]) + + :elliptical-arc + (let [{:keys [rx ry x-axis-rotation large-arc-flag sweep-flag x y]} params] + [rx ry x-axis-rotation large-arc-flag sweep-flag x y]))) + +;; 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") + params (parse-params cmd 2)] + (for [[x y] params] + {:command :move-to + :relative relative + :params {:x x :y y}}))) + +(defmethod parse-command "Z" [cmd] + [{:command :close-path}]) + +(defmethod parse-command "L" [cmd] + (let [relative (str/starts-with? cmd "l") + params (parse-params cmd 2)] + (for [[x y] params] + {:command :line-to + :relative relative + :params {:x x :y y}}))) + +(defmethod parse-command "H" [cmd] + (let [relative (str/starts-with? cmd "h") + params (parse-params cmd 1)] + (for [[value] params] + {:command :line-to-horizontal + :relative relative + :params {:value value}}))) + +(defmethod parse-command "V" [cmd] + (let [relative (str/starts-with? cmd "v") + params (parse-params cmd 1)] + (for [[value] params] + {:command :line-to-vertical + :relative relative + :params {:value value}}))) + +(defmethod parse-command "C" [cmd] + (let [relative (str/starts-with? cmd "c") + params (parse-params cmd 6)] + (for [[c1x c1y c2x c2y x y] params] + {:command :curve-to + :relative relative + :params {:c1x c1x + :c1y c1y + :c2x c2x + :c2y c2y + :x x + :y y}}))) + +(defmethod parse-command "S" [cmd] + (let [relative (str/starts-with? cmd "s") + params (parse-params cmd 4)] + (for [[cx cy x y] params] + {:command :smooth-curve-to + :relative relative + :params {:cx cx + :cy cy + :x x + :y y}}))) + +(defmethod parse-command "Q" [cmd] + (let [relative (str/starts-with? cmd "s") + params (parse-params cmd 4)] + (for [[cx cy x y] params] + {:command :quadratic-bezier-curve-to + :relative relative + :params {:cx cx + :cy cy + :x x + :y y}}))) + +(defmethod parse-command "T" [cmd] + (let [relative (str/starts-with? cmd "t") + params (parse-params cmd (coord-n 2))] + (for [[cx cy x y] params] + {:command :smooth-quadratic-bezier-curve-to + :relative relative + :params {:x x + :y y}}))) + +(defmethod parse-command "A" [cmd] + (let [relative (str/starts-with? cmd "a") + params (parse-params cmd 7)] + (for [[rx ry x-axis-rotation large-arc-flag sweep-flag x y] params] + {:command :elliptical-arc + :relative relative + :params {:rx rx + :ry ry + :x-axis-rotation x-axis-rotation + :large-arc-flag large-arc-flag + :sweep-flag sweep-flag + :x x + :y y}}))) + +(defn command->string [{:keys [command relative params] :as entry}] + (let [command-str (case command + :move-to "M" + :close-path "Z" + :line-to "L" + :line-to-horizontal "H" + :line-to-vertical "V" + :curve-to "C" + :smooth-curve-to "S" + :quadratic-bezier-curve-to "Q" + :smooth-quadratic-bezier-curve-to "T" + :elliptical-arc "A") + command-str (if relative (str/lower command-str) command-str) + param-list (command->param-list entry)] + (str/fmt "%s%s" command-str (str/join " " param-list)))) + +(defn path->content [string] + (let [clean-string (-> string + (str/trim) + ;; Change "commas" for spaces + (str/replace #"," " ") + ;; Remove all consecutive spaces + (str/replace #"\s+" " ")) + commands (re-seq commands-regex clean-string)] + (mapcat parse-command commands))) + +(defn content->path [content] + (->> content + (map command->string) + (str/join ""))) + +#_(let [path "M.343 15.974a.514.514 0 01-.317-.321c-.023-.07-.026-.23-.026-1.43 0-1.468-.001-1.445.09-1.586.02-.032 1.703-1.724 3.74-3.759a596.805 596.805 0 003.7-3.716c0-.009-.367-.384-.816-.833a29.9 29.9 0 01-.817-.833c0-.01.474-.49 1.054-1.07l1.053-1.053.948.946.947.947 1.417-1.413C12.366.806 12.765.418 12.856.357c.238-.161.52-.28.792-.334.17-.034.586-.03.76.008.801.173 1.41.794 1.57 1.603.03.15.03.569 0 .718a2.227 2.227 0 01-.334.793c-.061.09-.45.49-1.496 1.54L12.734 6.1l.947.948.947.947-1.053 1.054c-.58.58-1.061 1.054-1.07 1.054-.01 0-.384-.368-.833-.817-.45-.45-.824-.817-.834-.817-.009 0-1.68 1.666-3.716 3.701a493.093 493.093 0 01-3.759 3.74c-.14.091-.117.09-1.59.089-1.187 0-1.366-.004-1.43-.027zm6.024-4.633a592.723 592.723 0 003.663-3.68c0-.02-1.67-1.69-1.69-1.69-.01 0-1.666 1.648-3.68 3.663L.996 13.297v.834c0 .627.005.839.02.854.015.014.227.02.854.02h.833l3.664-3.664z" + content (path->content path) + new-path (content->path content) + ] + (prn "path" path) + (.log js/console "?? 1" (clj->js content)) + (prn "?? 2" (= path new-path) new-path)) From 10a24d68c94ee2f3bb5901e03d21206c7975978d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 5 Nov 2020 10:09:02 +0100 Subject: [PATCH 046/195] :recycle: Refactor drawing effects --- .../src/app/main/data/workspace/drawing.cljs | 6 +- .../app/main/data/workspace/drawing/box.cljs | 118 ++++++------ .../main/data/workspace/drawing/curve.cljs | 54 +++--- .../app/main/data/workspace/drawing/path.cljs | 168 ++++++++++-------- frontend/src/app/main/streams.cljs | 5 + 5 files changed, 187 insertions(+), 164 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index 8aa948a429..aeff2af30d 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -57,13 +57,13 @@ (watch [_ state stream] (rx/of (case type :path - path/handle-drawing-path + (path/handle-drawing-path) :curve - curve/handle-drawing-curve + (curve/handle-drawing-curve) ;; default - box/handle-drawing-box))))) + (box/handle-drawing-box)))))) ;; Export (def close-drawing-path path/close-drawing-path) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 74810d9b7a..35e84e2789 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -20,72 +20,72 @@ [app.main.streams :as ms] [app.main.data.workspace.drawing.common :as common])) -(def handle-drawing-box - (letfn [(resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] - (let [;; The new shape behaves like a resize on the bottom-right corner - initial (gpt/point (+ x width) (+ y height)) - shapev (gpt/point width height) - deltav (gpt/to-vec initial point-snap) - scalev (gpt/divide (gpt/add shapev deltav) shapev) - scalev (if lock? - (let [v (max (:x scalev) (:y scalev))] - (gpt/point v v)) - scalev)] - (-> shape - (assoc :click-draw? false) - (assoc-in [:modifiers :resize-vector] scalev) - (assoc-in [:modifiers :resize-origin] (gpt/point x y)) - (assoc-in [:modifiers :resize-rotation] 0)))) +(defn resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] + (let [;; The new shape behaves like a resize on the bottom-right corner + initial (gpt/point (+ x width) (+ y height)) + shapev (gpt/point width height) + deltav (gpt/to-vec initial point-snap) + scalev (gpt/divide (gpt/add shapev deltav) shapev) + scalev (if lock? + (let [v (max (:x scalev) (:y scalev))] + (gpt/point v v)) + scalev)] + (-> shape + (assoc :click-draw? false) + (assoc-in [:modifiers :resize-vector] scalev) + (assoc-in [:modifiers :resize-origin] (gpt/point x y)) + (assoc-in [:modifiers :resize-rotation] 0)))) - (update-drawing [state point lock? point-snap] - (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))] +(defn update-drawing [state point lock? point-snap] + (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap)) - (ptk/reify ::handle-drawing-box - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) +(defn handle-drawing-box [] + (ptk/reify ::handle-drawing-box + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) - stoper? #(or (ms/mouse-up? %) (= % :interrupt)) - stoper (rx/filter stoper? stream) - initial @ms/mouse-position + stoper? #(or (ms/mouse-up? %) (= % :interrupt)) + stoper (rx/filter stoper? stream) + initial @ms/mouse-position - page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - layout (get state :workspace-layout) + page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + layout (get state :workspace-layout) - frames (cph/select-frames objects) - fid (or (->> frames - (filter #(gsh/has-point? % initial)) - first - :id) - uuid/zero) + frames (cph/select-frames objects) + fid (or (->> frames + (filter #(gsh/has-point? % initial)) + first + :id) + uuid/zero) - shape (-> state - (get-in [:workspace-drawing :object]) - (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) - (assoc :frame-id fid) - (assoc :initialized? true) - (assoc :click-draw? true))] - (rx/concat - ;; Add shape to drawing state - (rx/of #(assoc-in state [:workspace-drawing :object] shape)) + shape (-> state + (get-in [:workspace-drawing :object]) + (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) + (assoc :frame-id fid) + (assoc :initialized? true) + (assoc :click-draw? true))] + (rx/concat + ;; Add shape to drawing state + (rx/of #(assoc-in state [:workspace-drawing :object] shape)) - ;; Initial SNAP - (->> (snap/closest-snap-point page-id [shape] layout initial) - (rx/map (fn [{:keys [x y]}] - #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) + ;; Initial SNAP + (->> (snap/closest-snap-point page-id [shape] layout initial) + (rx/map (fn [{:keys [x y]}] + #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) - (->> ms/mouse-position - (rx/filter #(> (gpt/distance % initial) 2)) - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/switch-map - (fn [[point :as current]] - (->> (snap/closest-snap-point page-id [shape] layout point) - (rx/map #(conj current %))))) - (rx/map - (fn [[pt ctrl? point-snap]] - #(update-drawing % pt ctrl? point-snap))) + (->> ms/mouse-position + (rx/filter #(> (gpt/distance % initial) 2)) + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/switch-map + (fn [[point :as current]] + (->> (snap/closest-snap-point page-id [shape] layout point) + (rx/map #(conj current %))))) + (rx/map + (fn [[pt ctrl? point-snap]] + #(update-drawing % pt ctrl? point-snap))) - (rx/take-until stoper)) - (rx/of common/handle-finish-drawing))))))) + (rx/take-until stoper)) + (rx/of common/handle-finish-drawing)))))) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index c0685383b7..5053d79fd5 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -18,34 +18,34 @@ (def simplify-tolerance 0.3) -(def handle-drawing-curve - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (ms/mouse-event? event) (= type :up)) +(defn stoper-event? [{:keys [type shift] :as event}] + (ms/mouse-event? event) (= type :up)) - (initialize-drawing [state] - (assoc-in state [:workspace-drawing :object :initialized?] true)) +(defn initialize-drawing [state] + (assoc-in state [:workspace-drawing :object :initialized?] true)) - (insert-point-segment [state point] - (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) +(defn insert-point-segment [state point] + (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) - (finish-drawing-curve [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] - (-> shape - (update :segments #(path/simplify % simplify-tolerance)) - (gsh/update-path-selrect)))))] +(defn finish-drawing-curve [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] + (-> shape + (update :segments #(path/simplify % simplify-tolerance)) + (gsh/update-path-selrect))))) - (ptk/reify ::handle-drawing-curve - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - stoper (rx/filter stoper-event? stream) - mouse (rx/sample 10 ms/mouse-position)] - (rx/concat - (rx/of initialize-drawing) - (->> mouse - (rx/map (fn [pt] #(insert-point-segment % pt))) - (rx/take-until stoper)) - (rx/of finish-drawing-curve - common/handle-finish-drawing))))))) +(defn handle-drawing-curve [] + (ptk/reify ::handle-drawing-curve + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) + stoper (rx/filter stoper-event? stream) + mouse (rx/sample 10 ms/mouse-position)] + (rx/concat + (rx/of initialize-drawing) + (->> mouse + (rx/map (fn [pt] #(insert-point-segment % pt))) + (rx/take-until stoper)) + (rx/of finish-drawing-curve + common/handle-finish-drawing)))))) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index e1430b83ff..3d92288fca 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -17,97 +17,115 @@ [app.util.geom.path :as path] [app.main.data.workspace.drawing.common :as common])) -(def handle-drawing-path - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (or (= event ::end-path-drawing) - (= event :interrupt) - (and (ms/mouse-event? event) - (or (= type :double-click) - (= type :context-menu))) - (and (ms/keyboard-event? event) - (= type :down) - (= 13 (:key event))))) +(defn stoper-event? [{:keys [type shift] :as event}] + (or (= event ::end-path-drawing) + (= event :interrupt) + (and (ms/mouse-event? event) + (or (= type :double-click) + (= type :context-menu))) + (and (ms/keyboard-event? event) + (= type :down) + (= 13 (:key event))))) - (initialize-drawing [state point] - (-> state - (assoc-in [:workspace-drawing :object :segments] [point point]) - (assoc-in [:workspace-drawing :object :initialized?] true))) +(defn init-path [] + (fn [state] + (update-in state [:workspace-drawing :object] + assoc :content [] + :initialized? true))) - (insert-point-segment [state point] - (-> state - (update-in [:workspace-drawing :object :segments] (fnil conj []) point))) +(defn add-path-command [command] + (fn [state] + (update-in state [:workspace-drawing :object :content] conj command))) - (update-point-segment [state index point] - (let [segments (count (get-in state [:workspace-drawing :object :segments])) - exists? (< -1 index segments)] - (cond-> state - exists? (assoc-in [:workspace-drawing :object :segments index] point)))) +#_(defn update-point-segment [state index point] + (let [segments (count (get-in state [:workspace-drawing :object :segments])) + exists? (< -1 index segments)] + (cond-> state + exists? (assoc-in [:workspace-drawing :object :segments index] point)))) - (finish-drawing-path [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] (-> shape - (update :segments #(vec (butlast %))) - (gsh/update-path-selrect)))))] +(defn finish-drawing-path [] + (fn [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] (-> shape + (update :segments #(vec (butlast %))) + (gsh/update-path-selrect)))))) - (ptk/reify ::handle-drawing-path - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - last-point (volatile! @ms/mouse-position) +(defn handle-drawing-path [] - stoper (->> (rx/filter stoper-event? stream) - (rx/share)) + (ptk/reify ::handle-drawing-path + ptk/WatchEvent + (watch [_ state stream] - mouse (rx/sample 10 ms/mouse-position) + ;; clicks stream<[MouseEvent, Position]> + clicks (->> stream + (rx/filter ms/mouse-click?) + (rx/with-latest vector ms/mouse-position)) - points (->> stream - (rx/filter ms/mouse-click?) - (rx/filter #(false? (:shift %))) - (rx/with-latest vector mouse) - (rx/map second)) + - counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) + ))) - stream' (->> mouse - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/with-latest vector counter) - (rx/map flatten)) +#_(def handle-drawing-path + (ptk/reify ::handle-drawing-path + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) - imm-transform #(vector (- % 7) (+ % 7) %) - immanted-zones (vec (concat - (map imm-transform (range 0 181 15)) - (map (comp imm-transform -) (range 0 181 15)))) + last-point (volatile! @ms/mouse-position) - align-position (fn [angle pos] - (reduce (fn [pos [a1 a2 v]] - (if (< a1 angle a2) - (reduced (gpt/update-angle pos v)) - pos)) - pos - immanted-zones))] + stoper (->> (rx/filter stoper-event? stream) + (rx/share)) - (rx/merge - (rx/of #(initialize-drawing % @last-point)) + mouse (rx/sample 10 ms/mouse-position) - (->> points - (rx/take-until stoper) - (rx/map (fn [pt] #(insert-point-segment % pt)))) + points (->> stream + (rx/filter ms/mouse-click?) + (rx/filter #(false? (:shift %))) + (rx/with-latest vector mouse) + (rx/map second)) - (rx/concat - (->> stream' - (rx/take-until stoper) - (rx/map (fn [[point ctrl? index :as xxx]] - (let [point (if ctrl? - (as-> point $ - (gpt/subtract $ @last-point) - (align-position (gpt/angle $) $) - (gpt/add $ @last-point)) - point)] - #(update-point-segment % index point))))) - (rx/of finish-drawing-path - common/handle-finish-drawing)))))))) + counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) + + stream' (->> mouse + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/with-latest vector counter) + (rx/map flatten)) + + imm-transform #(vector (- % 7) (+ % 7) %) + immanted-zones (vec (concat + (map imm-transform (range 0 181 15)) + (map (comp imm-transform -) (range 0 181 15)))) + + align-position (fn [angle pos] + (reduce (fn [pos [a1 a2 v]] + (if (< a1 angle a2) + (reduced (gpt/update-angle pos v)) + pos)) + pos + immanted-zones))] + + (rx/merge + (rx/of #(initialize-drawing % @last-point)) + + (->> points + (rx/take-until stoper) + (rx/map (fn [pt] #(insert-point-segment % pt)))) + + (rx/concat + (->> stream' + (rx/take-until stoper) + (rx/map (fn [[point ctrl? index :as xxx]] + (let [point (if ctrl? + (as-> point $ + (gpt/subtract $ @last-point) + (align-position (gpt/angle $) $) + (gpt/add $ @last-point)) + point)] + #(update-point-segment % index point))))) + (rx/of finish-drawing-path + common/handle-finish-drawing))))))) (defn close-drawing-path [] (ptk/reify ::close-drawing-path diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index cc5c720c93..af90f2b936 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -26,6 +26,11 @@ [v] (instance? MouseEvent v)) +(defn mouse-down? + [v] + (and (mouse-event? v) + (= :down (:type v)))) + (defn mouse-up? [v] (and (mouse-event? v) From 2c50bb16dc846ed671095623feda2c5a4f31bbdf Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 6 Nov 2020 11:39:32 +0100 Subject: [PATCH 047/195] :recycle: Refactor geom/shapes.cljc --- common/app/common/attrs.cljc | 71 ++ common/app/common/geom/align.cljc | 141 ++++ common/app/common/geom/shapes.cljc | 625 +----------------- common/app/common/geom/shapes/common.cljc | 52 ++ common/app/common/geom/shapes/path.cljc | 21 + common/app/common/geom/shapes/rect.cljc | 83 +++ common/app/common/geom/shapes/transforms.cljc | 342 ++++++++++ frontend/src/app/main/data/workspace.cljs | 21 +- .../main/data/workspace/drawing/common.cljs | 2 +- .../src/app/main/data/workspace/texts.cljs | 3 +- frontend/src/app/main/exports.cljs | 14 +- frontend/src/app/main/streams.cljs | 5 + frontend/src/app/main/ui/handoff/render.cljs | 3 +- frontend/src/app/main/ui/viewer/shapes.cljs | 3 +- .../src/app/main/ui/workspace/shapes.cljs | 3 +- .../ui/workspace/sidebar/options/group.cljs | 21 +- .../workspace/sidebar/options/multiple.cljs | 5 +- 17 files changed, 781 insertions(+), 634 deletions(-) create mode 100644 common/app/common/attrs.cljc create mode 100644 common/app/common/geom/align.cljc create mode 100644 common/app/common/geom/shapes/common.cljc create mode 100644 common/app/common/geom/shapes/path.cljc create mode 100644 common/app/common/geom/shapes/rect.cljc create mode 100644 common/app/common/geom/shapes/transforms.cljc diff --git a/common/app/common/attrs.cljc b/common/app/common/attrs.cljc new file mode 100644 index 0000000000..9008c9ae1b --- /dev/null +++ b/common/app/common/attrs.cljc @@ -0,0 +1,71 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.attrs) + +(defn get-attrs-multi + [shapes attrs] + ;; Extract some attributes of a list of shapes. + ;; For each attribute, if the value is the same in all shapes, + ;; wll take this value. If there is any shape that is different, + ;; the value of the attribute will be the keyword :multiple. + ;; + ;; If some shape has the value nil in any attribute, it's + ;; considered a different value. If the shape does not contain + ;; the attribute, it's ignored in the final result. + ;; + ;; Example: + ;; (def shapes [{:stroke-color "#ff0000" + ;; :stroke-width 3 + ;; :fill-color "#0000ff" + ;; :x 1000 :y 2000 :rx nil} + ;; {:stroke-width "#ff0000" + ;; :stroke-width 5 + ;; :x 1500 :y 2000}]) + ;; + ;; (get-attrs-multi shapes [:stroke-color + ;; :stroke-width + ;; :fill-color + ;; :rx + ;; :ry]) + ;; >>> {:stroke-color "#ff0000" + ;; :stroke-width :multiple + ;; :fill-color "#0000ff" + ;; :rx nil + ;; :ry nil} + ;; + (let [defined-shapes (filter some? shapes) + + combine-value (fn [v1 v2] (cond + (= v1 v2) v1 + (= v1 :undefined) v2 + (= v2 :undefined) v1 + :else :multiple)) + + combine-values (fn [attrs shape values] + (map #(combine-value (get shape % :undefined) + (get values % :undefined)) attrs)) + + select-attrs (fn [shape attrs] + (zipmap attrs (map #(get shape % :undefined) attrs))) + + reducer (fn [result shape] + (zipmap attrs (combine-values attrs shape result))) + + combined (reduce reducer + (select-attrs (first defined-shapes) attrs) + (rest defined-shapes)) + + cleanup-value (fn [value] + (if (= value :undefined) nil value)) + + cleanup (fn [result] + (zipmap attrs (map #(cleanup-value (get result %)) attrs)))] + + (cleanup combined))) diff --git a/common/app/common/geom/align.cljc b/common/app/common/geom/align.cljc new file mode 100644 index 0000000000..64089b70c6 --- /dev/null +++ b/common/app/common/geom/align.cljc @@ -0,0 +1,141 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.align + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.shapes :as gsh] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.math :as mth] + [app.common.data :as d])) + +;; --- Alignment + +(s/def ::align-axis #{:hleft :hcenter :hright :vtop :vcenter :vbottom}) + +(declare calc-align-pos) + +(defn align-to-rect + "Move the shape so that it is aligned with the given rectangle + in the given axis. Take account the form of the shape and the + possible rotation. What is aligned is the rectangle that wraps + the shape with the given rectangle. If the shape is a group, + move also all of its recursive children." + [shape rect axis objects] + (let [wrapper-rect (gsh/selection-rect [shape]) + align-pos (calc-align-pos wrapper-rect rect axis) + delta {:x (- (:x align-pos) (:x wrapper-rect)) + :y (- (:y align-pos) (:y wrapper-rect))}] + (gsh/recursive-move shape delta objects))) + +(defn calc-align-pos + [wrapper-rect rect axis] + (case axis + :hleft (let [left (:x rect)] + {:x left + :y (:y wrapper-rect)}) + + :hcenter (let [center (+ (:x rect) (/ (:width rect) 2))] + {:x (- center (/ (:width wrapper-rect) 2)) + :y (:y wrapper-rect)}) + + :hright (let [right (+ (:x rect) (:width rect))] + {:x (- right (:width wrapper-rect)) + :y (:y wrapper-rect)}) + + :vtop (let [top (:y rect)] + {:x (:x wrapper-rect) + :y top}) + + :vcenter (let [center (+ (:y rect) (/ (:height rect) 2))] + {:x (:x wrapper-rect) + :y (- center (/ (:height wrapper-rect) 2))}) + + :vbottom (let [bottom (+ (:y rect) (:height rect))] + {:x (:x wrapper-rect) + :y (- bottom (:height wrapper-rect))}))) + +;; --- Distribute + +(s/def ::dist-axis #{:horizontal :vertical}) + +(defn distribute-space + "Distribute equally the space between shapes in the given axis. If + there is no space enough, it does nothing. It takes into account + the form of the shape and the rotation, what is distributed is + the wrapping recangles of the shapes. If any shape is a group, + move also all of its recursive children." + [shapes axis objects] + (let [coord (if (= axis :horizontal) :x :y) + other-coord (if (= axis :horizontal) :y :x) + size (if (= axis :horizontal) :width :height) + ; The rectangle that wraps the whole selection + wrapper-rect (gsh/selection-rect shapes) + ; Sort shapes by the center point in the given axis + sorted-shapes (sort-by #(coord (gsh/center %)) shapes) + ; Each shape wrapped in its own rectangle + wrapped-shapes (map #(gsh/selection-rect [%]) sorted-shapes) + ; The total space between shapes + space (reduce - (size wrapper-rect) (map size wrapped-shapes))] + + (if (<= space 0) + shapes + (let [unit-space (/ space (- (count wrapped-shapes) 1)) + ; Calculate the distance we need to move each shape. + ; The new position of each one is the position of the + ; previous one plus its size plus the unit space. + deltas (loop [shapes' wrapped-shapes + start-pos (coord wrapper-rect) + deltas []] + + (let [first-shape (first shapes') + delta (- start-pos (coord first-shape)) + new-pos (+ start-pos (size first-shape) unit-space)] + + (if (= (count shapes') 1) + (conj deltas delta) + (recur (rest shapes') + new-pos + (conj deltas delta)))))] + + (mapcat #(gsh/recursive-move %1 {coord %2 other-coord 0} objects) + sorted-shapes deltas))))) + +;; Adjusto to viewport + +(defn adjust-to-viewport + ([viewport srect] (adjust-to-viewport viewport srect nil)) + ([viewport srect {:keys [padding] :or {padding 0}}] + (let [gprop (/ (:width viewport) (:height viewport)) + srect (-> srect + (update :x #(- % padding)) + (update :y #(- % padding)) + (update :width #(+ % padding padding)) + (update :height #(+ % padding padding))) + width (:width srect) + height (:height srect) + lprop (/ width height)] + (cond + (> gprop lprop) + (let [width' (* (/ width lprop) gprop) + padding (/ (- width' width) 2)] + (-> srect + (update :x #(- % padding)) + (assoc :width width'))) + + (< gprop lprop) + (let [height' (/ (* height lprop) gprop) + padding (/ (- height' height) 2)] + (-> srect + (update :y #(- % padding)) + (assoc :height height'))) + + :else srect)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index b191ed5bf9..0bb89d5cfd 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -13,6 +13,9 @@ [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] + [app.common.geom.shapes.common :as gco] + [app.common.geom.shapes.transforms :as gtr] + [app.common.geom.shapes.rect :as gpr] [app.common.math :as mth] [app.common.data :as d])) @@ -90,39 +93,6 @@ dy (if y (- (-chk y) (-chk (:y shape))) 0)] (move shape (gpt/point dx dy)))) -;; --- Center - -(declare center-rect) -(declare center-path) - -(defn center - "Calculate the center of the shape." - [shape] - (case (:type shape) - :curve (center-path shape) - :path (center-path shape) - (center-rect shape))) - -(defn- center-rect - [{:keys [x y width height] :as shape}] - (gpt/point (+ x (/ width 2)) (+ y (/ height 2)))) - -(defn- center-path - [{:keys [segments] :as shape}] - (let [minx (apply min (map :x segments)) - miny (apply min (map :y segments)) - maxx (apply max (map :x segments)) - maxy (apply max (map :y segments))] - (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) - -(defn center->rect - "Creates a rect given a center and a width and height" - [center width height] - {:x (- (:x center) (/ width 2)) - :y (- (:y center) (/ height 2)) - :width width - :height height}) - ;; --- Proportions (declare assign-proportions-path) @@ -219,9 +189,6 @@ :image (setup-image shape props) (setup-rect shape props))) -(declare shape->points) -(declare points->selrect) - (defn- setup-rect "A specialized function for setup rect-like shapes." [shape {:keys [x y width height]}] @@ -230,8 +197,8 @@ :y y :width width :height height) - (assoc $ :points (shape->points $)) - (assoc $ :selrect (points->selrect (:points $))))) + (assoc $ :points (gtr/shape->points $)) + (assoc $ :selrect (gpr/points->selrect (:points $))))) (defn- setup-image [{:keys [metadata] :as shape} {:keys [x y width height] :as props}] @@ -241,91 +208,6 @@ (:height metadata)) :proportion-lock true))) -;; --- Coerce to Rect-like shape. - -(declare path->rect-shape) -(declare group->rect-shape) -(declare rect->rect-shape) - -;; TODO: completly remove - -(defn shape->rect-shape - "Coerce shape to rect like shape." - - [{:keys [type] :as shape}] - (case type - (:curve :path) (path->rect-shape shape) - (rect->rect-shape shape))) - -;; -- Points - -(declare transform-shape-point) - -(defn shape->points [shape] - (let [points (case (:type shape) - (:curve :path) (:segments shape) - (let [{:keys [x y width height]} shape] - [(gpt/point x y) - (gpt/point (+ x width) y) - (gpt/point (+ x width) (+ y height)) - (gpt/point x (+ y height))]))] - (->> points - (map #(transform-shape-point % shape (:transform shape (gmt/matrix)))) - (map gpt/round) - (vec)))) - -(defn points->selrect [points] - (let [minx (transduce (map :x) min ##Inf points) - miny (transduce (map :y) min ##Inf points) - maxx (transduce (map :x) max ##-Inf points) - maxy (transduce (map :y) max ##-Inf points)] - {:x1 minx - :y1 miny - :x2 maxx - :y2 maxy - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny) - :type :rect})) - -;; Shape->PATH - -(declare rect->path) - -(defn shape->path - [shape] - (case (:type shape) - (:curve :path) shape - (rect->path shape))) - -(defn rect->path - [{:keys [x y width height] :as shape}] - - (let [points [(gpt/point x y) - (gpt/point (+ x width) y) - (gpt/point (+ x width) (+ y height)) - (gpt/point x (+ y height)) - (gpt/point x y)]] - (-> shape - (assoc :type :path) - (assoc :segments points)))) - -;; --- SHAPE -> RECT - -(defn- rect->rect-shape - [{:keys [x y width height] :as shape}] - (assoc shape - :x1 x - :y1 y - :x2 (+ x width) - :y2 (+ y height))) - -(defn- path->rect-shape - [{:keys [segments] :as shape}] - (merge shape - {:type :rect} - (:selrect shape))) ;; --- Resolve Shape @@ -347,51 +229,6 @@ (translate-from-frame shape pobj) (recur (get objects (:parent pobj)))))) -;; --- Transform Shape - -(declare transform-rect) -(declare transform-path) - -(defn transform - "Apply the matrix transformation to shape." - [{:keys [type] :as shape} xfmt] - (if (gmt/matrix? xfmt) - (case type - :path (transform-path shape xfmt) - :curve (transform-path shape xfmt) - (transform-rect shape xfmt)) - shape)) - -(defn center-transform [shape matrix] - (let [shape-center (center shape)] - (-> shape - (transform - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply matrix) - (gmt/translate (gpt/negate shape-center))))))) - -(defn- transform-rect - [{:keys [x y width height] :as shape} mx] - (let [tl (gpt/transform (gpt/point x y) mx) - tr (gpt/transform (gpt/point (+ x width) y) mx) - bl (gpt/transform (gpt/point x (+ y height)) mx) - br (gpt/transform (gpt/point (+ x width) (+ y height)) mx) - ;; TODO: replace apply with transduce (performance) - minx (apply min (map :x [tl tr bl br])) - maxx (apply max (map :x [tl tr bl br])) - miny (apply min (map :y [tl tr bl br])) - maxy (apply max (map :y [tl tr bl br]))] - (assoc shape - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny)))) - -(defn- transform-path - [{:keys [segments] :as shape} xfmt] - (let [segments (mapv #(gpt/transform % xfmt) segments)] - (assoc shape :segments segments))) ;; --- Outer Rect @@ -426,107 +263,14 @@ [shape {:keys [x y] :as frame}] (move shape (gpt/point x y))) -;; --- Alignment - -(s/def ::align-axis #{:hleft :hcenter :hright :vtop :vcenter :vbottom}) - -(declare calc-align-pos) - -(defn align-to-rect - "Move the shape so that it is aligned with the given rectangle - in the given axis. Take account the form of the shape and the - possible rotation. What is aligned is the rectangle that wraps - the shape with the given rectangle. If the shape is a group, - move also all of its recursive children." - [shape rect axis objects] - (let [wrapper-rect (selection-rect [shape]) - align-pos (calc-align-pos wrapper-rect rect axis) - delta {:x (- (:x align-pos) (:x wrapper-rect)) - :y (- (:y align-pos) (:y wrapper-rect))}] - (recursive-move shape delta objects))) - -(defn calc-align-pos - [wrapper-rect rect axis] - (case axis - :hleft (let [left (:x rect)] - {:x left - :y (:y wrapper-rect)}) - - :hcenter (let [center (+ (:x rect) (/ (:width rect) 2))] - {:x (- center (/ (:width wrapper-rect) 2)) - :y (:y wrapper-rect)}) - - :hright (let [right (+ (:x rect) (:width rect))] - {:x (- right (:width wrapper-rect)) - :y (:y wrapper-rect)}) - - :vtop (let [top (:y rect)] - {:x (:x wrapper-rect) - :y top}) - - :vcenter (let [center (+ (:y rect) (/ (:height rect) 2))] - {:x (:x wrapper-rect) - :y (- center (/ (:height wrapper-rect) 2))}) - - :vbottom (let [bottom (+ (:y rect) (:height rect))] - {:x (:x wrapper-rect) - :y (- bottom (:height wrapper-rect))}))) - -;; --- Distribute - -(s/def ::dist-axis #{:horizontal :vertical}) - -(defn distribute-space - "Distribute equally the space between shapes in the given axis. If - there is no space enough, it does nothing. It takes into account - the form of the shape and the rotation, what is distributed is - the wrapping recangles of the shapes. If any shape is a group, - move also all of its recursive children." - [shapes axis objects] - (let [coord (if (= axis :horizontal) :x :y) - other-coord (if (= axis :horizontal) :y :x) - size (if (= axis :horizontal) :width :height) - ; The rectangle that wraps the whole selection - wrapper-rect (selection-rect shapes) - ; Sort shapes by the center point in the given axis - sorted-shapes (sort-by #(coord (center %)) shapes) - ; Each shape wrapped in its own rectangle - wrapped-shapes (map #(selection-rect [%]) sorted-shapes) - ; The total space between shapes - space (reduce - (size wrapper-rect) (map size wrapped-shapes))] - - (if (<= space 0) - shapes - (let [unit-space (/ space (- (count wrapped-shapes) 1)) - ; Calculate the distance we need to move each shape. - ; The new position of each one is the position of the - ; previous one plus its size plus the unit space. - deltas (loop [shapes' wrapped-shapes - start-pos (coord wrapper-rect) - deltas []] - - (let [first-shape (first shapes') - delta (- start-pos (coord first-shape)) - new-pos (+ start-pos (size first-shape) unit-space)] - - (if (= (count shapes') 1) - (conj deltas delta) - (recur (rest shapes') - new-pos - (conj deltas delta)))))] - - (mapcat #(recursive-move %1 {coord %2 other-coord 0} objects) - sorted-shapes deltas))))) - - ;; --- Helpers (defn contained-in? "Check if a shape is contained in the provided selection rect." [shape selrect] - (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (shape->rect-shape selrect) - {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (shape->rect-shape shape)] + (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (gpr/shape->rect-shape selrect) + {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (gpr/shape->rect-shape shape)] (and (neg? (- sy1 ry1)) (neg? (- sx1 rx1)) (pos? (- sy2 ry2)) @@ -535,8 +279,8 @@ (defn overlaps? "Check if a shape overlaps with provided selection rect." [shape selrect] - (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (shape->rect-shape selrect) - {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (shape->rect-shape shape)] + (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (gpr/shape->rect-shape selrect) + {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (gpr/shape->rect-shape shape)] (and (< rx1 sx2) (> rx2 sx1) (< ry1 sy2) @@ -564,43 +308,6 @@ :type :rect}] (overlaps? shape selrect))) -(defn calculate-rec-path-skew-angle - [path-shape] - (let [p1 (get-in path-shape [:segments 2]) - p2 (get-in path-shape [:segments 3]) - p3 (get-in path-shape [:segments 4]) - v1 (gpt/to-vec p1 p2) - v2 (gpt/to-vec p2 p3)] - (- 90 (gpt/angle-with-other v1 v2)))) - -(defn calculate-rec-path-height - "Calculates the height of a paralelogram given by the path" - [path-shape] - (let [p1 (get-in path-shape [:segments 2]) - p2 (get-in path-shape [:segments 3]) - p3 (get-in path-shape [:segments 4]) - v1 (gpt/to-vec p1 p2) - v2 (gpt/to-vec p2 p3) - angle (gpt/angle-with-other v1 v2)] - (* (gpt/length v2) (mth/sin (mth/radians angle))))) - -(defn calculate-rec-path-rotation - [path-shape1 path-shape2 resize-vector] - - (let [idx-1 0 - idx-2 (cond (and (neg? (:x resize-vector)) (pos? (:y resize-vector))) 1 - (and (neg? (:x resize-vector)) (neg? (:y resize-vector))) 2 - (and (pos? (:x resize-vector)) (neg? (:y resize-vector))) 3 - :else 0) - p1 (get-in path-shape1 [:segments idx-1]) - p2 (get-in path-shape2 [:segments idx-2]) - v1 (gpt/to-vec (center path-shape1) p1) - v2 (gpt/to-vec (center path-shape2) p2) - - rot-angle (gpt/angle-with-other v1 v2) - rot-sign (if (> (* (:y v1) (:x v2)) (* (:x v1) (:y v2))) -1 1)] - (* rot-sign rot-angle))) - (defn pad-selrec ([selrect] (pad-selrec selrect 1)) ([selrect size] @@ -658,305 +365,6 @@ (and (>= s1c1 s2c1) (<= s1c1 s2c2)) (and (>= s1c2 s2c1) (<= s1c2 s2c2))))) -(defn transform-shape-point - "Transform a point around the shape center" - [point shape transform] - (let [shape-center (center shape)] - (gpt/transform - point - (-> (gmt/multiply - (gmt/translate-matrix shape-center) - transform - (gmt/translate-matrix (gpt/negate shape-center))))))) - -(defn transform-apply-modifiers - [shape] - (let [modifiers (:modifiers shape) - ds-modifier (:displacement modifiers (gmt/matrix)) - {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) - - ;; Normalize x/y vector coordinates because scale by 0 is infinite - res-x (cond - (and (< res-x 0) (> res-x -0.01)) -0.01 - (and (>= res-x 0) (< res-x 0.01)) 0.01 - :else res-x) - - res-y (cond - (and (< res-y 0) (> res-y -0.01)) -0.01 - (and (>= res-y 0) (< res-y 0.01)) 0.01 - :else res-y) - - resize (gpt/point res-x res-y) - - origin (:resize-origin modifiers (gpt/point 0 0)) - - resize-transform (:resize-transform modifiers (gmt/matrix)) - resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) - rt-modif (or (:rotation modifiers) 0) - - shape (-> shape - (transform ds-modifier)) - - shape-center (center shape)] - - (-> (shape->path shape) - (transform (-> (gmt/matrix) - - ;; Applies the current resize transformation - (gmt/translate origin) - (gmt/multiply resize-transform) - (gmt/scale resize) - (gmt/multiply resize-transform-inverse) - (gmt/translate (gpt/negate origin)) - - ;; Applies the stacked transformations - (gmt/translate shape-center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - (gmt/multiply (:transform shape (gmt/matrix))) - (gmt/translate (gpt/negate shape-center))))))) - -(defn rect-path-dimensions [rect-path] - (let [seg (:segments rect-path) - [width height] (mapv (fn [[c1 c2]] (gpt/distance c1 c2)) (take 2 (d/zip seg (rest seg))))] - {:width width - :height height})) - -(defn calculate-stretch [shape-path transform-inverse] - (let [shape-center (center shape-path) - shape-path-temp (transform - shape-path - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply transform-inverse) - (gmt/translate (gpt/negate shape-center)))) - - shape-path-temp-rec (shape->rect-shape shape-path-temp) - shape-path-temp-dim (rect-path-dimensions shape-path-temp)] - (gpt/divide (gpt/point (:width shape-path-temp-rec) (:height shape-path-temp-rec)) - (gpt/point (:width shape-path-temp-dim) (:height shape-path-temp-dim))))) - -(defn fix-invalid-rect-values - [rect-shape] - (letfn [(check [num] - (if (or (nil? num) (mth/nan? num) (= ##Inf num) (= ##-Inf num)) 0 num)) - (to-positive [num] (if (< num 1) 1 num))] - (-> rect-shape - (update :x check) - (update :y check) - (update :width (comp to-positive check)) - (update :height (comp to-positive check))))) - -(defn transform-rect-shape - [shape] - (let [;; Apply modifiers to the rect as a path so we have the end shape expected - shape-path (transform-apply-modifiers shape) - shape-center (center shape-path) - resize-vector (-> (get-in shape [:modifiers :resize-vector] (gpt/point 1 1)) - (update :x #(if (zero? %) 1 %)) - (update :y #(if (zero? %) 1 %))) - - ;; Reverse the current transformation stack to get the base rectangle - shape-path-temp (center-transform shape-path (:transform-inverse shape (gmt/matrix))) - shape-path-temp-dim (rect-path-dimensions shape-path-temp) - shape-path-temp-rec (shape->rect-shape shape-path-temp) - - ;; This rectangle is the new data for the current rectangle. We want to change our rectangle - ;; to have this width, height, x, y - rec (center->rect shape-center (:width shape-path-temp-dim) (:height shape-path-temp-dim)) - rec (fix-invalid-rect-values rec) - rec-path (rect->path rec) - - ;; The next matrix is a series of transformations we have to do to the previous rec so that - ;; after applying them the end result is the `shape-path-temp` - ;; This is compose of three transformations: skew, resize and rotation - stretch-matrix (gmt/matrix) - - skew-angle (calculate-rec-path-skew-angle shape-path-temp) - - ;; When one of the axis is flipped we have to reverse the skew - skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) - skew-angle (if (mth/nan? skew-angle) 0 skew-angle) - - - stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) - - h1 (calculate-rec-path-height shape-path-temp) - h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix)) - h3 (/ h1 h2) - h3 (if (mth/nan? h3) 1 h3) - - stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) - - rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) - shape-path-temp resize-vector) - - stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) - - ;; This is the inverse to be able to remove the transformation - stretch-matrix-inverse (-> (gmt/matrix) - (gmt/scale (gpt/point 1 h3)) - (gmt/skew (- skew-angle) 0) - (gmt/rotate (- rotation-angle))) - - - new-shape (as-> shape $ - (merge $ rec) - (update $ :x #(mth/precision % 0)) - (update $ :y #(mth/precision % 0)) - (update $ :width #(mth/precision % 0)) - (update $ :height #(mth/precision % 0)) - (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) - (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) - (assoc $ :points (shape->points $)) - (assoc $ :selrect (points->selrect (:points $))) - (update $ :selrect fix-invalid-rect-values) - (update $ :rotation #(mod (+ (or % 0) - (or (get-in $ [:modifiers :rotation]) 0)) 360)))] - new-shape)) - -(declare update-path-selrect) -(defn transform-path-shape - [shape] - (-> shape - transform-apply-modifiers - update-path-selrect) - ;; TODO: Addapt for paths is not working - #_(let [shape-path (transform-apply-modifiers shape) - shape-path-center (center shape-path) - - shape-transform-inverse' (-> (gmt/matrix) - (gmt/translate shape-path-center) - (gmt/multiply (:transform-inverse shape (gmt/matrix))) - (gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0)))) - (gmt/translate (gpt/negate shape-path-center)))] - (-> shape-path - (transform shape-transform-inverse') - (add-rotate-transform (:rotation-modifier shape 0))))) - -(defn transform-shape - "Transform the shape properties given the modifiers" - ([shape] (transform-shape nil shape)) - ([frame shape] - (let [new-shape - (if (:modifiers shape) - (-> (case (:type shape) - (:curve :path) (transform-path-shape shape) - (transform-rect-shape shape)) - (dissoc :modifiers)) - shape)] - (cond-> new-shape - frame (translate-to-frame frame))))) - - -(defn transform-matrix - "Returns a transformation matrix without changing the shape properties. - The result should be used in a `transform` attribute in svg" - ([{:keys [x y] :as shape}] - (let [shape-center (center shape)] - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply (:transform shape (gmt/matrix))) - (gmt/translate (gpt/negate shape-center)))))) - -(defn update-path-selrect [shape] - (as-> shape $ - (assoc $ :points (shape->points $)) - (assoc $ :selrect (points->selrect (:points $))) - (assoc $ :x (get-in $ [:selrect :x])) - (assoc $ :y (get-in $ [:selrect :y])) - (assoc $ :width (get-in $ [:selrect :width])) - (assoc $ :height (get-in $ [:selrect :height])))) - -(defn adjust-to-viewport - ([viewport srect] (adjust-to-viewport viewport srect nil)) - ([viewport srect {:keys [padding] :or {padding 0}}] - (let [gprop (/ (:width viewport) (:height viewport)) - srect (-> srect - (update :x #(- % padding)) - (update :y #(- % padding)) - (update :width #(+ % padding padding)) - (update :height #(+ % padding padding))) - width (:width srect) - height (:height srect) - lprop (/ width height)] - (cond - (> gprop lprop) - (let [width' (* (/ width lprop) gprop) - padding (/ (- width' width) 2)] - (-> srect - (update :x #(- % padding)) - (assoc :width width'))) - - (< gprop lprop) - (let [height' (/ (* height lprop) gprop) - padding (/ (- height' height) 2)] - (-> srect - (update :y #(- % padding)) - (assoc :height height'))) - - :else srect)))) - -(defn get-attrs-multi - [shapes attrs] - ;; Extract some attributes of a list of shapes. - ;; For each attribute, if the value is the same in all shapes, - ;; wll take this value. If there is any shape that is different, - ;; the value of the attribute will be the keyword :multiple. - ;; - ;; If some shape has the value nil in any attribute, it's - ;; considered a different value. If the shape does not contain - ;; the attribute, it's ignored in the final result. - ;; - ;; Example: - ;; (def shapes [{:stroke-color "#ff0000" - ;; :stroke-width 3 - ;; :fill-color "#0000ff" - ;; :x 1000 :y 2000 :rx nil} - ;; {:stroke-width "#ff0000" - ;; :stroke-width 5 - ;; :x 1500 :y 2000}]) - ;; - ;; (get-attrs-multi shapes [:stroke-color - ;; :stroke-width - ;; :fill-color - ;; :rx - ;; :ry]) - ;; >>> {:stroke-color "#ff0000" - ;; :stroke-width :multiple - ;; :fill-color "#0000ff" - ;; :rx nil - ;; :ry nil} - ;; - (let [defined-shapes (filter some? shapes) - - combine-value (fn [v1 v2] (cond - (= v1 v2) v1 - (= v1 :undefined) v2 - (= v2 :undefined) v1 - :else :multiple)) - - combine-values (fn [attrs shape values] - (map #(combine-value (get shape % :undefined) - (get values % :undefined)) attrs)) - - select-attrs (fn [shape attrs] - (zipmap attrs (map #(get shape % :undefined) attrs))) - - reducer (fn [result shape] - (zipmap attrs (combine-values attrs shape result))) - - combined (reduce reducer - (select-attrs (first defined-shapes) attrs) - (rest defined-shapes)) - - cleanup-value (fn [value] - (if (= value :undefined) nil value)) - - cleanup (fn [result] - (zipmap attrs (map #(cleanup-value (get result %)) attrs)))] - - (cleanup combined))) - (defn setup-selrect [{:keys [x y width height] :as shape}] (-> shape @@ -965,3 +373,18 @@ :x1 x :y1 y :x2 (+ x width) :y2 (+ y height)}))) + +;; EXPORTS +(def center gco/center) + +(def shape->rect-shape gpr/shape->rect-shape) +(def fix-invalid-rect-values gtr/fix-invalid-rect-values) +(def rect->rect-shape gpr/rect->rect-shape) +(def points->selrect gpr/points->selrect) + +(def transform-shape-point gtr/transform-shape-point) +(def update-path-selrect gtr/update-path-selrect) +(def transform gtr/transform) +(defn transform-shape [shape] (gtr/transform-shape shape)) +(def transform-matrix gtr/transform-matrix) + diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc new file mode 100644 index 0000000000..1ef8728f7e --- /dev/null +++ b/common/app/common/geom/shapes/common.cljc @@ -0,0 +1,52 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.shapes.common + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes.path :as gpa] + [app.common.math :as mth] + [app.common.data :as d])) + +;; --- Center + +(declare center-rect) +(declare center-path) + +(defn center + "Calculate the center of the shape." + [shape] + (case (:type shape) + :curve (center-path shape) + :path (center-path shape) + (center-rect shape))) + +(defn- center-rect + [{:keys [x y width height] :as shape}] + (gpt/point (+ x (/ width 2)) (+ y (/ height 2)))) + +(defn- center-path + [{:keys [segments] :as shape}] + (let [minx (apply min (map :x segments)) + miny (apply min (map :y segments)) + maxx (apply max (map :x segments)) + maxy (apply max (map :y segments))] + (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) + +(defn center->rect + "Creates a rect given a center and a width and height" + [center width height] + {:x (- (:x center) (/ width 2)) + :y (- (:y center) (/ height 2)) + :width width + :height height}) + diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc new file mode 100644 index 0000000000..60810fc7fb --- /dev/null +++ b/common/app/common/geom/shapes/path.cljc @@ -0,0 +1,21 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.shapes.path + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.math :as mth] + [app.common.data :as d])) + +(defn content->points [content] + (map #(gpt/point (-> % :param :x) (-> % :param :y)) content)) + diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc new file mode 100644 index 0000000000..8f06cae97b --- /dev/null +++ b/common/app/common/geom/shapes/rect.cljc @@ -0,0 +1,83 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.shapes.rect + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes.path :as gpa] + [app.common.geom.shapes.common :as gco] + [app.common.math :as mth] + [app.common.data :as d])) + +;; --- SHAPE -> RECT + +(defn- rect->rect-shape + [{:keys [x y width height] :as shape}] + (assoc shape + :x1 x + :y1 y + :x2 (+ x width) + :y2 (+ y height))) + +(defn- path->rect-shape + [{:keys [segments] :as shape}] + (merge shape + {:type :rect} + (:selrect shape))) + +(defn shape->rect-shape + "Coerce shape to rect like shape." + + [{:keys [type] :as shape}] + (case type + (:curve :path) (path->rect-shape shape) + (rect->rect-shape shape))) + +;; Shape->PATH + +(declare rect->path) + +(defn shape->path + [shape] + (case (:type shape) + (:curve :path) shape + (rect->path shape))) + +(defn rect->path + [{:keys [x y width height] :as shape}] + + (let [points [(gpt/point x y) + (gpt/point (+ x width) y) + (gpt/point (+ x width) (+ y height)) + (gpt/point x (+ y height)) + (gpt/point x y)]] + (-> shape + (assoc :type :path) + (assoc :segments points)))) + +;; -- Points + +(defn points->selrect [points] + (let [minx (transduce (map :x) min ##Inf points) + miny (transduce (map :y) min ##Inf points) + maxx (transduce (map :x) max ##-Inf points) + maxy (transduce (map :y) max ##-Inf points)] + {:x1 minx + :y1 miny + :x2 maxx + :y2 maxy + :x minx + :y miny + :width (- maxx minx) + :height (- maxy miny) + :type :rect})) + diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc new file mode 100644 index 0000000000..ecb2acd163 --- /dev/null +++ b/common/app/common/geom/shapes/transforms.cljc @@ -0,0 +1,342 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.shapes.transforms + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes.common :as gco] + [app.common.geom.shapes.path :as gpa] + [app.common.geom.shapes.rect :as gpr] + [app.common.math :as mth] + [app.common.data :as d])) + +;; --- Transform Shape + +(declare transform-rect) +(declare transform-path) + +(defn transform + "Apply the matrix transformation to shape." + [{:keys [type] :as shape} xfmt] + (if (gmt/matrix? xfmt) + (case type + :path (transform-path shape xfmt) + :curve (transform-path shape xfmt) + (transform-rect shape xfmt)) + shape)) + +(defn center-transform [shape matrix] + (let [shape-center (gco/center shape)] + (-> shape + (transform + (-> (gmt/matrix) + (gmt/translate shape-center) + (gmt/multiply matrix) + (gmt/translate (gpt/negate shape-center))))))) + +(defn- transform-rect + [{:keys [x y width height] :as shape} mx] + (let [tl (gpt/transform (gpt/point x y) mx) + tr (gpt/transform (gpt/point (+ x width) y) mx) + bl (gpt/transform (gpt/point x (+ y height)) mx) + br (gpt/transform (gpt/point (+ x width) (+ y height)) mx) + ;; TODO: replace apply with transduce (performance) + minx (apply min (map :x [tl tr bl br])) + maxx (apply max (map :x [tl tr bl br])) + miny (apply min (map :y [tl tr bl br])) + maxy (apply max (map :y [tl tr bl br]))] + (assoc shape + :x minx + :y miny + :width (- maxx minx) + :height (- maxy miny)))) + +(defn- transform-path + [{:keys [segments] :as shape} xfmt] + (let [segments (mapv #(gpt/transform % xfmt) segments)] + (assoc shape :segments segments))) + + +(defn transform-shape-point + "Transform a point around the shape center" + [point shape transform] + (let [shape-center (gco/center shape)] + (gpt/transform + point + (-> (gmt/multiply + (gmt/translate-matrix shape-center) + transform + (gmt/translate-matrix (gpt/negate shape-center))))))) + +(defn shape->points [shape] + (let [points (case (:type shape) + (:curve :path) (if (:content shape) + (gpa/content->points (:content shape)) + (:segments shape)) + (let [{:keys [x y width height]} shape] + [(gpt/point x y) + (gpt/point (+ x width) y) + (gpt/point (+ x width) (+ y height)) + (gpt/point x (+ y height))]))] + (->> points + (map #(transform-shape-point % shape (:transform shape (gmt/matrix)))) + (map gpt/round) + (vec)))) + +(defn rect-path-dimensions [rect-path] + (let [seg (:segments rect-path) + [width height] (mapv (fn [[c1 c2]] (gpt/distance c1 c2)) (take 2 (d/zip seg (rest seg))))] + {:width width + :height height})) + +(defn update-path-selrect [shape] + (as-> shape $ + (assoc $ :points (shape->points $)) + (assoc $ :selrect (gpr/points->selrect (:points $))) + (assoc $ :x (get-in $ [:selrect :x])) + (assoc $ :y (get-in $ [:selrect :y])) + (assoc $ :width (get-in $ [:selrect :width])) + (assoc $ :height (get-in $ [:selrect :height])))) + +(defn fix-invalid-rect-values + [rect-shape] + (letfn [(check [num] + (if (or (nil? num) (mth/nan? num) (= ##Inf num) (= ##-Inf num)) 0 num)) + (to-positive [num] (if (< num 1) 1 num))] + (-> rect-shape + (update :x check) + (update :y check) + (update :width (comp to-positive check)) + (update :height (comp to-positive check))))) + +(defn calculate-rec-path-skew-angle + [path-shape] + (let [p1 (get-in path-shape [:segments 2]) + p2 (get-in path-shape [:segments 3]) + p3 (get-in path-shape [:segments 4]) + v1 (gpt/to-vec p1 p2) + v2 (gpt/to-vec p2 p3)] + (- 90 (gpt/angle-with-other v1 v2)))) + +(defn calculate-rec-path-height + "Calculates the height of a paralelogram given by the path" + [path-shape] + (let [p1 (get-in path-shape [:segments 2]) + p2 (get-in path-shape [:segments 3]) + p3 (get-in path-shape [:segments 4]) + v1 (gpt/to-vec p1 p2) + v2 (gpt/to-vec p2 p3) + angle (gpt/angle-with-other v1 v2)] + (* (gpt/length v2) (mth/sin (mth/radians angle))))) + +(defn calculate-rec-path-rotation + [path-shape1 path-shape2 resize-vector] + + (let [idx-1 0 + idx-2 (cond (and (neg? (:x resize-vector)) (pos? (:y resize-vector))) 1 + (and (neg? (:x resize-vector)) (neg? (:y resize-vector))) 2 + (and (pos? (:x resize-vector)) (neg? (:y resize-vector))) 3 + :else 0) + p1 (get-in path-shape1 [:segments idx-1]) + p2 (get-in path-shape2 [:segments idx-2]) + v1 (gpt/to-vec (gco/center path-shape1) p1) + v2 (gpt/to-vec (gco/center path-shape2) p2) + + rot-angle (gpt/angle-with-other v1 v2) + rot-sign (if (> (* (:y v1) (:x v2)) (* (:x v1) (:y v2))) -1 1)] + (* rot-sign rot-angle))) + + +(defn transform-apply-modifiers + [shape] + (let [modifiers (:modifiers shape) + ds-modifier (:displacement modifiers (gmt/matrix)) + {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) + + ;; Normalize x/y vector coordinates because scale by 0 is infinite + res-x (cond + (and (< res-x 0) (> res-x -0.01)) -0.01 + (and (>= res-x 0) (< res-x 0.01)) 0.01 + :else res-x) + + res-y (cond + (and (< res-y 0) (> res-y -0.01)) -0.01 + (and (>= res-y 0) (< res-y 0.01)) 0.01 + :else res-y) + + resize (gpt/point res-x res-y) + + origin (:resize-origin modifiers (gpt/point 0 0)) + + resize-transform (:resize-transform modifiers (gmt/matrix)) + resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) + rt-modif (or (:rotation modifiers) 0) + + shape (-> shape + (transform ds-modifier)) + + shape-center (gco/center shape)] + + (-> (gpr/shape->path shape) + (transform (-> (gmt/matrix) + + ;; Applies the current resize transformation + (gmt/translate origin) + (gmt/multiply resize-transform) + (gmt/scale resize) + (gmt/multiply resize-transform-inverse) + (gmt/translate (gpt/negate origin)) + + ;; Applies the stacked transformations + (gmt/translate shape-center) + (gmt/multiply (gmt/rotate-matrix rt-modif)) + (gmt/multiply (:transform shape (gmt/matrix))) + (gmt/translate (gpt/negate shape-center))))))) + +(defn transform-path-shape + [shape] + (-> shape + transform-apply-modifiers + update-path-selrect) + ;; TODO: Addapt for paths is not working + #_(let [shape-path (transform-apply-modifiers shape) + shape-path-center (center shape-path) + + shape-transform-inverse' (-> (gmt/matrix) + (gmt/translate shape-path-center) + (gmt/multiply (:transform-inverse shape (gmt/matrix))) + (gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0)))) + (gmt/translate (gpt/negate shape-path-center)))] + (-> shape-path + (transform shape-transform-inverse') + (add-rotate-transform (:rotation-modifier shape 0))))) + +(defn transform-rect-shape + [shape] + (let [;; Apply modifiers to the rect as a path so we have the end shape expected + shape-path (transform-apply-modifiers shape) + shape-center (gco/center shape-path) + resize-vector (-> (get-in shape [:modifiers :resize-vector] (gpt/point 1 1)) + (update :x #(if (zero? %) 1 %)) + (update :y #(if (zero? %) 1 %))) + + ;; Reverse the current transformation stack to get the base rectangle + shape-path-temp (center-transform shape-path (:transform-inverse shape (gmt/matrix))) + shape-path-temp-dim (rect-path-dimensions shape-path-temp) + shape-path-temp-rec (gpr/shape->rect-shape shape-path-temp) + + ;; This rectangle is the new data for the current rectangle. We want to change our rectangle + ;; to have this width, height, x, y + rec (gco/center->rect shape-center (:width shape-path-temp-dim) (:height shape-path-temp-dim)) + rec (fix-invalid-rect-values rec) + rec-path (gpr/rect->path rec) + + ;; The next matrix is a series of transformations we have to do to the previous rec so that + ;; after applying them the end result is the `shape-path-temp` + ;; This is compose of three transformations: skew, resize and rotation + stretch-matrix (gmt/matrix) + + skew-angle (calculate-rec-path-skew-angle shape-path-temp) + + ;; When one of the axis is flipped we have to reverse the skew + skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) + skew-angle (if (mth/nan? skew-angle) 0 skew-angle) + + + stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) + + h1 (calculate-rec-path-height shape-path-temp) + h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix)) + h3 (/ h1 h2) + h3 (if (mth/nan? h3) 1 h3) + + stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) + + rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) + shape-path-temp resize-vector) + + stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) + + ;; This is the inverse to be able to remove the transformation + stretch-matrix-inverse (-> (gmt/matrix) + (gmt/scale (gpt/point 1 h3)) + (gmt/skew (- skew-angle) 0) + (gmt/rotate (- rotation-angle))) + + new-shape (as-> shape $ + (merge $ rec) + (update $ :x #(mth/precision % 0)) + (update $ :y #(mth/precision % 0)) + (update $ :width #(mth/precision % 0)) + (update $ :height #(mth/precision % 0)) + (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) + (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) + (assoc $ :points (shape->points $)) + (assoc $ :selrect (gpr/points->selrect (:points $))) + (update $ :selrect fix-invalid-rect-values) + (update $ :rotation #(mod (+ (or % 0) + (or (get-in $ [:modifiers :rotation]) 0)) 360)))] + new-shape)) + +(defn transform-shape + "Transform the shape properties given the modifiers" + ([shape] + + (letfn [(transform-by-type [shape] + (case (:type shape) + (:curve :path) + (transform-path-shape shape) + + #_:default + (transform-rect-shape shape)))] + + (cond-> shape + (:modifiers shape) (transform-by-type) + :always (dissoc :modifiers))) + + #_(cond-> shape + (and (:modifiers shape) (#{:curve :path} (:type shape))) + (transform-path-shape shape) + + (and (:modifiers shape) (not (#{:curve :path} (:type shape)))) + (transform-rect-shape shape) + + true + (dissoc :modifiers) + )) + #_([frame shape kk] + + + + + #_(if (:modifiers shape) + (-> (case (:type shape) + (:curve :path) (transform-path-shape shape) + (transform-rect-shape shape)) + (dissoc :modifiers)) + shape) + #_(let [new-shape + ] + + #_(cond-> new-shape + frame (translate-to-frame frame))))) + + +(defn transform-matrix + "Returns a transformation matrix without changing the shape properties. + The result should be used in a `transform` attribute in svg" + ([{:keys [x y] :as shape}] + (let [shape-center (gco/center shape)] + (-> (gmt/matrix) + (gmt/translate shape-center) + (gmt/multiply (:transform shape (gmt/matrix))) + (gmt/translate (gpt/negate shape-center)))))) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index ea2c54522b..ea4755fcc6 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -13,7 +13,8 @@ [app.common.exceptions :as ex] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] + [app.common.geom.align :as gal] [app.common.math :as mth] [app.common.pages :as cp] [app.common.pages-helpers :as cph] @@ -339,7 +340,7 @@ (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) shapes (cph/select-toplevel-shapes objects {:include-frames? true}) - srect (geom/selection-rect shapes) + srect (gsh/selection-rect shapes) local (assoc local :vport size :zoom 1)] (cond (or (not (mth/finite? (:width srect))) @@ -348,7 +349,7 @@ (or (> (:width srect) width) (> (:height srect) height)) - (let [srect (geom/adjust-to-viewport size srect {:padding 40}) + (let [srect (gal/adjust-to-viewport size srect {:padding 40}) zoom (/ (:width size) (:width srect))] (-> local (assoc :zoom zoom) @@ -471,10 +472,10 @@ (let [vbox (update vbox :x + (:left-offset vbox)) new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom) old-zoom (:zoom local) - center (if center center (geom/center vbox)) + center (if center center (gsh/center vbox)) scale (/ old-zoom new-zoom) mtx (gmt/scale-matrix (gpt/point scale) center) - vbox' (geom/transform vbox mtx) + vbox' (gsh/transform vbox mtx) vbox' (update vbox' :x - (:left-offset vbox))] (-> local (assoc :zoom new-zoom) @@ -510,14 +511,14 @@ (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) shapes (cph/select-toplevel-shapes objects {:include-frames? true}) - srect (geom/selection-rect shapes)] + srect (gsh/selection-rect shapes)] (if (or (mth/nan? (:width srect)) (mth/nan? (:height srect))) state (update state :workspace-local (fn [{:keys [vbox vport] :as local}] - (let [srect (geom/adjust-to-viewport vport srect {:padding 40}) + (let [srect (gal/adjust-to-viewport vport srect {:padding 40}) zoom (/ (:width vport) (:width srect))] (-> local (assoc :zoom zoom) @@ -534,10 +535,10 @@ objects (dwc/lookup-page-objects state page-id) srect (->> selected (map #(get objects %)) - (geom/selection-rect))] + (gsh/selection-rect))] (update state :workspace-local (fn [{:keys [vbox vport] :as local}] - (let [srect (geom/adjust-to-viewport vport srect {:padding 40}) + (let [srect (gal/adjust-to-viewport vport srect {:padding 40}) zoom (/ (:width vport) (:width srect))] (-> local (assoc :zoom zoom) @@ -614,8 +615,8 @@ (merge data) (merge {:x x :y y}) (assoc :frame-id frame-id) - (geom/setup-selrect))] (rx/of (add-shape shape)))))) + (gsh/setup-selrect))] ;; --- Update Shape Attrs diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index a4d7938fe2..24ffb0d65e 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -44,7 +44,7 @@ (if (:click-draw? shape) :auto-width :fixed))) shape (-> shape - gsh/transform-shape + (gsh/transform-shape) (dissoc :initialized? :click-draw?))] ;; Add & select the created shape to the workspace (rx/concat diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 34616e94c4..c13a6dda23 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -17,6 +17,7 @@ [goog.object :as gobj] [potok.core :as ptk] [app.common.geom.shapes :as geom] + [app.common.attrs :as attrs] [app.main.data.workspace.common :as dwc] [app.main.fonts :as fonts] [app.util.object :as obj] @@ -125,7 +126,7 @@ (map #(if (is-text-node? %) (merge ut/default-text-attrs %) %)))] - (geom/get-attrs-multi nodes attrs))) + (attrs/get-attrs-multi nodes attrs))) (defn current-text-values [{:keys [editor default attrs shape]}] diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index cf8a129dd1..6629597a8b 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -15,7 +15,8 @@ [app.common.pages :as cp] [app.common.pages-helpers :as cph] [app.common.math :as mth] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] + [app.common.geom.align :as gal] [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] [app.main.ui.shapes.filters :as filters] @@ -42,9 +43,9 @@ (defn- calculate-dimensions [{:keys [objects] :as data} vport] (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})] - (->> (geom/selection-rect shapes) - (geom/adjust-to-viewport vport) - (geom/fix-invalid-rect-values)))) + (->> (gsh/selection-rect shapes) + (gal/adjust-to-viewport vport) + (gsh/fix-invalid-rect-values)))) (declare shape-wrapper-factory) @@ -55,7 +56,7 @@ (mf/fnc frame-wrapper [{:keys [shape] :as props}] (let [childs (mapv #(get objects %) (:shapes shape)) - shape (geom/transform-shape shape)] + shape (gsh/transform-shape shape)] [:> shape-container {:shape shape} [:& frame-shape {:shape shape :childs childs}]])))) @@ -78,7 +79,8 @@ (let [group-wrapper (mf/use-memo (mf/deps objects) #(group-wrapper-factory objects)) frame-wrapper (mf/use-memo (mf/deps objects) #(frame-wrapper-factory objects))] (when (and shape (not (:hidden shape))) - (let [shape (geom/transform-shape frame shape) + (let [shape (-> (gsh/transform-shape shape) + (gsh/translate-to-frame frame)) opts #js {:shape shape}] [:> shape-container {:shape shape} (case (:type shape) diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index af90f2b936..597f89223a 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -41,6 +41,11 @@ (and (mouse-event? v) (= :click (:type v)))) +(defn mouse-double-click? + [v] + (and (mouse-event? v) + (= :double-click (:type v)))) + (defrecord PointerEvent [source pt ctrl shift alt]) (defn pointer-event? diff --git a/frontend/src/app/main/ui/handoff/render.cljs b/frontend/src/app/main/ui/handoff/render.cljs index 26e0c8d5d0..d1893c0aef 100644 --- a/frontend/src/app/main/ui/handoff/render.cljs +++ b/frontend/src/app/main/ui/handoff/render.cljs @@ -122,7 +122,8 @@ (mf/deps objects) #(group-container-factory objects))] (when (and shape (not (:hidden shape))) - (let [shape (geom/transform-shape frame shape) + (let [shape (-> (geom/transform-shape shape) + (geom/translate-to-frame frame)) opts #js {:shape shape :frame frame}] (case (:type shape) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 8cca3ce1e6..a17bd9f313 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -149,7 +149,8 @@ shape (unchecked-get props "shape") frame (unchecked-get props "frame")] (when (and shape (not (:hidden shape))) - (let [shape (geom/transform-shape frame shape) + (let [shape (-> (geom/transform-shape shape) + (geom/translate-to-frame frame)) opts #js {:shape shape}] (case (:type shape) :curve [:> path-wrapper opts] diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index f0b8bc2b55..cd9dd7521c 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -82,7 +82,8 @@ (let [shape (unchecked-get props "shape") frame (unchecked-get props "frame") ghost? (unchecked-get props "ghost?") - shape (geom/transform-shape frame shape) + shape (-> (geom/transform-shape shape) + (geom/translate-to-frame frame)) opts #js {:shape shape :frame frame} alt? (mf/use-state false) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs index 43711deb7f..4dac6c4d80 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs @@ -11,6 +11,7 @@ (ns app.main.ui.workspace.sidebar.options.group (:require [rumext.alpha :as mf] + [app.common.attrs :as attrs] [app.common.geom.shapes :as geom] [app.common.pages-helpers :as cph] [app.main.refs :as refs] @@ -43,7 +44,7 @@ (merge ;; All values extracted from the group shape, except ;; border radius, that needs to be looked up from children - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % measure-attrs nil @@ -51,7 +52,7 @@ nil) [shape]) measure-attrs) - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % [:rx :ry] nil @@ -64,10 +65,10 @@ (select-keys shape component-attrs) fill-values - (geom/get-attrs-multi shape-with-children fill-attrs) + (attrs/get-attrs-multi shape-with-children fill-attrs) stroke-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % stroke-attrs nil @@ -77,7 +78,7 @@ stroke-attrs) font-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-font-attrs @@ -87,7 +88,7 @@ text-font-attrs) align-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-align-attrs @@ -97,7 +98,7 @@ text-align-attrs) spacing-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-spacing-attrs @@ -107,7 +108,7 @@ text-spacing-attrs) valign-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-valign-attrs @@ -117,7 +118,7 @@ text-valign-attrs) decoration-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-decoration-attrs @@ -127,7 +128,7 @@ text-decoration-attrs) transform-values - (geom/get-attrs-multi (map #(get-shape-attrs + (attrs/get-attrs-multi (map #(get-shape-attrs % nil text-transform-attrs diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/multiple.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/multiple.cljs index b13a69acbf..03f45783b7 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/multiple.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/multiple.cljs @@ -11,6 +11,7 @@ (:require [rumext.alpha :as mf] [app.common.geom.shapes :as geom] + [app.common.attrs :as attrs] [app.main.data.workspace.texts :as dwt] [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] @@ -48,9 +49,9 @@ text-attrs convert-attrs extract-fn))] - (geom/get-attrs-multi (map mapfn shapes) (or attrs text-attrs)))) + (attrs/get-attrs-multi (map mapfn shapes) (or attrs text-attrs)))) - measure-values (geom/get-attrs-multi shapes measure-attrs) + measure-values (attrs/get-attrs-multi shapes measure-attrs) fill-values (extract {:attrs fill-attrs :text-attrs ot/text-fill-attrs From af68c26aeabba467d3c4c6bbb377665426dabe11 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 10 Nov 2020 17:52:23 +0100 Subject: [PATCH 048/195] :recycle: Refactor transforms --- common/app/common/data.cljc | 32 +- common/app/common/geom/align.cljc | 24 +- common/app/common/geom/matrix.cljc | 10 + common/app/common/geom/proportions.cljc | 62 ++ common/app/common/geom/shapes.cljc | 227 ++---- common/app/common/geom/shapes/common.cljc | 65 +- common/app/common/geom/shapes/path.cljc | 4 +- common/app/common/geom/shapes/rect.cljc | 141 ++-- common/app/common/geom/shapes/transforms.cljc | 685 +++++++++++------- common/app/common/pages.cljc | 10 +- frontend/src/app/main/data/workspace.cljs | 159 +--- .../src/app/main/data/workspace/common.cljs | 92 ++- .../src/app/main/data/workspace/drawing.cljs | 34 + .../app/main/data/workspace/drawing/box.cljs | 3 +- .../main/data/workspace/drawing/common.cljs | 14 +- .../main/data/workspace/drawing/curve.cljs | 8 +- .../app/main/data/workspace/drawing/path.cljs | 110 ++- .../app/main/data/workspace/libraries.cljs | 4 +- .../app/main/data/workspace/transforms.cljs | 15 +- frontend/src/app/main/exports.cljs | 2 +- frontend/src/app/main/snap.cljs | 2 +- frontend/src/app/main/store.cljs | 14 +- .../src/app/main/ui/shapes/custom_stroke.cljs | 3 +- frontend/src/app/main/ui/shapes/path.cljs | 12 +- .../src/app/main/ui/workspace/selection.cljs | 6 +- .../ui/workspace/shapes/bounding_box.cljs | 2 +- .../app/main/ui/workspace/snap_distances.cljs | 5 +- .../src/app/main/ui/workspace/viewport.cljs | 3 +- frontend/src/app/main/worker.cljs | 4 +- frontend/src/app/util/geom/snap_points.cljs | 4 +- frontend/src/app/util/worker.cljs | 6 +- frontend/src/app/worker/selection.cljs | 8 +- 32 files changed, 1085 insertions(+), 685 deletions(-) create mode 100644 common/app/common/geom/proportions.cljc diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index 3034e369b5..18cfe35dc4 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,12 +7,14 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) - (:require [clojure.set :as set] - [linked.set :as lks] - #?(:cljs [cljs.reader :as r] - :clj [clojure.edn :as r]) - #?(:cljs [cljs.core :as core] - :clj [clojure.core :as core])) + (:require + [clojure.set :as set] + [linked.set :as lks] + [app.common.math :as mth] + #?(:cljs [cljs.reader :as r] + :clj [clojure.edn :as r]) + #?(:cljs [cljs.core :as core] + :clj [clojure.core :as core])) #?(:clj (:import linked.set.LinkedSet))) @@ -261,3 +263,21 @@ (defn coalesce [val default] (or val default)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Data Parsing / Conversion +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defn nilf + "Returns a new function that if you pass nil as any argument will + return nil" + [f] + (fn [& args] + (if (some nil? args) + nil + (apply f args)))) + +(defn check-num + "Function that checks if a number is nil or nan. Will return 0 when not + valid and the number otherwise." + [v] + (if (or (not v) (mth/nan? v)) 0 v)) diff --git a/common/app/common/geom/align.cljc b/common/app/common/geom/align.cljc index 64089b70c6..4cec0fdf54 100644 --- a/common/app/common/geom/align.cljc +++ b/common/app/common/geom/align.cljc @@ -10,11 +10,7 @@ (ns app.common.geom.align (:require [clojure.spec.alpha :as s] - [app.common.spec :as us] [app.common.geom.shapes :as gsh] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.math :as mth] [app.common.data :as d])) ;; --- Alignment @@ -23,6 +19,20 @@ (declare calc-align-pos) +;; Duplicated from pages-helpers to remove cyclic dependencies +(defn- get-children [id objects] + (let [shapes (vec (get-in objects [id :shapes]))] + (if shapes + (d/concat shapes (mapcat #(get-children % objects) shapes)) + []))) + +(defn- recursive-move + "Move the shape and all its recursive children." + [shape dpoint objects] + (let [children-ids (get-children (:id shape) objects) + children (map #(get objects %) children-ids)] + (map #(gsh/move % dpoint) (cons shape children)))) + (defn align-to-rect "Move the shape so that it is aligned with the given rectangle in the given axis. Take account the form of the shape and the @@ -34,7 +44,7 @@ align-pos (calc-align-pos wrapper-rect rect axis) delta {:x (- (:x align-pos) (:x wrapper-rect)) :y (- (:y align-pos) (:y wrapper-rect))}] - (gsh/recursive-move shape delta objects))) + (recursive-move shape delta objects))) (defn calc-align-pos [wrapper-rect rect axis] @@ -80,7 +90,7 @@ ; The rectangle that wraps the whole selection wrapper-rect (gsh/selection-rect shapes) ; Sort shapes by the center point in the given axis - sorted-shapes (sort-by #(coord (gsh/center %)) shapes) + sorted-shapes (sort-by #(coord (gsh/center-shape %)) shapes) ; Each shape wrapped in its own rectangle wrapped-shapes (map #(gsh/selection-rect [%]) sorted-shapes) ; The total space between shapes @@ -106,7 +116,7 @@ new-pos (conj deltas delta)))))] - (mapcat #(gsh/recursive-move %1 {coord %2 other-coord 0} objects) + (mapcat #(recursive-move %1 {coord %2 other-coord 0} objects) sorted-shapes deltas))))) ;; Adjusto to viewport diff --git a/common/app/common/geom/matrix.cljc b/common/app/common/geom/matrix.cljc index f3b9a00074..185197f168 100644 --- a/common/app/common/geom/matrix.cljc +++ b/common/app/common/geom/matrix.cljc @@ -121,3 +121,13 @@ ([m angle-x angle-y p] (multiply m (skew-matrix angle-x angle-y p)))) +(defn m-equal [m1 m2 threshold] + (let [th-eq (fn [a b] (<= (mth/abs (- a b)) threshold)) + {m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f} m1 + {m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f} m2] + (and (th-eq m1a m2a) + (th-eq m1b m2b) + (th-eq m1c m2c) + (th-eq m1d m2d) + (th-eq m1e m2e) + (th-eq m1f m2f)))) diff --git a/common/app/common/geom/proportions.cljc b/common/app/common/geom/proportions.cljc new file mode 100644 index 0000000000..e70a9b3b5f --- /dev/null +++ b/common/app/common/geom/proportions.cljc @@ -0,0 +1,62 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.geom.proportions + (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes.common :as gco] + [app.common.geom.shapes.transforms :as gtr] + [app.common.geom.shapes.rect :as gpr] + [app.common.math :as mth] + [app.common.data :as d])) + +;; --- Proportions + +(declare assign-proportions-path) +(declare assign-proportions-rect) + +(defn assign-proportions + [{:keys [type] :as shape}] + (case type + :path (assign-proportions-path shape) + (assign-proportions-rect shape))) + +(defn- assign-proportions-rect + [{:keys [width height] :as shape}] + (assoc shape :proportion (/ width height))) + + +;; --- Setup Proportions + +(declare setup-proportions-const) +(declare setup-proportions-image) + +(defn setup-proportions + [shape] + (case (:type shape) + :icon (setup-proportions-image shape) + :image (setup-proportions-image shape) + :text shape + (setup-proportions-const shape))) + +(defn setup-proportions-image + [{:keys [metadata] :as shape}] + (let [{:keys [width height]} metadata] + (assoc shape + :proportion (/ width height) + :proportion-lock false))) + +(defn setup-proportions-const + [shape] + (assoc shape + :proportion 1 + :proportion-lock false)) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 0bb89d5cfd..8cf6073156 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -19,31 +19,19 @@ [app.common.math :as mth] [app.common.data :as d])) -(defn- nilf - "Returns a new function that if you pass nil as any argument will - return nil" - [f] - (fn [& args] - (if (some nil? args) - nil - (apply f args)))) - ;; --- Relative Movement -(declare move-rect) -(declare move-path) - -(defn -chk - "Function that checks if a number is nil or nan. Will return 0 when not - valid and the number otherwise." - [v] - (if (or (not v) (mth/nan? v)) 0 v)) - (defn move "Move the shape relativelly to its current position applying the provided delta." [shape {dx :x dy :y}] - (let [inc-x (nilf (fn [x] (+ (-chk x) (-chk dx)))) + (let [dx (d/check-num dx) + dy (d/check-num dy)] + (-> shape + (assoc-in [:modifiers :displacement] (gmt/translate-matrix (gpt/point dx dy))) + (gtr/transform-shape))) + + #_(let [inc-x (nilf (fn [x] (+ (-chk x) (-chk dx)))) inc-y (nilf (fn [y] (+ (-chk y) (-chk dy)))) inc-point (nilf (fn [p] (-> p (update :x inc-x) @@ -60,57 +48,20 @@ (update :points #(mapv inc-point %)) (update :segments #(mapv inc-point %))))) -;; Duplicated from pages-helpers to remove cyclic dependencies -(defn get-children [id objects] - (let [shapes (vec (get-in objects [id :shapes]))] - (if shapes - (d/concat shapes (mapcat #(get-children % objects) shapes)) - []))) - -(defn recursive-move - "Move the shape and all its recursive children." - [shape dpoint objects] - (let [children-ids (get-children (:id shape) objects) - children (map #(get objects %) children-ids)] - (map #(move % dpoint) (cons shape children)))) - ;; --- Absolute Movement (declare absolute-move-rect) (defn absolute-move "Move the shape to the exactly specified position." - [shape position] - (case (:type shape) - (:curve :path) shape - (absolute-move-rect shape position))) - -(defn- absolute-move-rect - "A specialized function for absolute moviment - for rect-like shapes." - [shape {:keys [x y] :as pos}] - (let [dx (if x (- (-chk x) (-chk (:x shape))) 0) - dy (if y (- (-chk y) (-chk (:y shape))) 0)] + [shape {:keys [x y]}] + (let [dx (- (d/check-num x) (-> shape :selrect :x)) + dy (- (d/check-num y) (-> shape :selrect :y))] (move shape (gpt/point dx dy)))) -;; --- Proportions - -(declare assign-proportions-path) -(declare assign-proportions-rect) - -(defn assign-proportions - [{:keys [type] :as shape}] - (case type - :path (assign-proportions-path shape) - (assign-proportions-rect shape))) - -(defn- assign-proportions-rect - [{:keys [width height] :as shape}] - (assoc shape :proportion (/ width height))) - ;; --- Paths -(defn update-path-point +#_(defn update-path-point "Update a concrete point in the path. The point should exists before, this function @@ -118,34 +69,9 @@ [shape index point] (assoc-in shape [:segments index] point)) -;; --- Setup Proportions - -(declare setup-proportions-const) -(declare setup-proportions-image) - -(defn setup-proportions - [shape] - (case (:type shape) - :icon (setup-proportions-image shape) - :image (setup-proportions-image shape) - :text shape - (setup-proportions-const shape))) - -(defn setup-proportions-image - [{:keys [metadata] :as shape}] - (let [{:keys [width height]} metadata] - (assoc shape - :proportion (/ width height) - :proportion-lock false))) - -(defn setup-proportions-const - [shape] - (assoc shape - :proportion 1 - :proportion-lock false)) ;; --- Resize (Dimensions) - +;;; TODO: CHANGE TO USE THE MODIFIERS (defn resize [shape width height] (us/assert map? shape) @@ -177,28 +103,21 @@ (resize shape (:width new-size) (:height new-size)))) ;; --- Setup (Initialize) - -(declare setup-rect) -(declare setup-image) - -(defn setup - "A function that initializes the first coordinates for - the shape. Used mainly for draw operations." - [shape props] - (case (:type shape) - :image (setup-image shape props) - (setup-rect shape props))) +;; FIXME: Is this the correct place for these functions? (defn- setup-rect "A specialized function for setup rect-like shapes." [shape {:keys [x y width height]}] - (as-> shape $ - (assoc $ :x x - :y y - :width width - :height height) - (assoc $ :points (gtr/shape->points $)) - (assoc $ :selrect (gpr/points->selrect (:points $))))) + (let [rect {:x x :y y :width width :height height} + points (gpr/rect->points rect) + selrect (gpr/points->selrect points)] + (assoc shape + :x x + :y y + :width width + :height height + :points points + :selrect selrect))) (defn- setup-image [{:keys [metadata] :as shape} {:keys [x y width height] :as props}] @@ -208,26 +127,26 @@ (:height metadata)) :proportion-lock true))) +(defn setup + "A function that initializes the first coordinates for + the shape. Used mainly for draw operations." + [shape props] + (case (:type shape) + :image (setup-image shape props) + (setup-rect shape props))) ;; --- Resolve Shape -(declare resolve-rect-shape) -(declare translate-from-frame) -(declare translate-to-frame) - -(defn resolve-shape - [objects shape] - (case (:type shape) - :rect (resolve-rect-shape objects shape) - :group (resolve-rect-shape objects shape) - :frame (resolve-rect-shape objects shape))) - -(defn- resolve-rect-shape - [objects {:keys [parent] :as shape}] - (loop [pobj (get objects parent)] - (if (= :frame (:type pobj)) - (translate-from-frame shape pobj) - (recur (get objects (:parent pobj)))))) +;; (declare resolve-rect-shape) +;; (declare translate-from-frame) +;; (declare translate-to-frame) +;; +;; (defn resolve-shape +;; [objects shape] +;; (loop [pobj (get objects parent)] +;; (if (= :frame (:type pobj)) +;; (translate-from-frame shape pobj) +;; (recur (get objects (:parent pobj)))))) ;; --- Outer Rect @@ -236,24 +155,8 @@ "Returns a rect that contains all the shapes and is aware of the rotation of each shape. Mainly used for multiple selection." [shapes] - (let [shapes (map :selrect shapes) - minx (transduce (map :x1) min ##Inf shapes) - miny (transduce (map :y1) min ##Inf shapes) - maxx (transduce (map :x2) max ##-Inf shapes) - maxy (transduce (map :y2) max ##-Inf shapes)] - {:x1 minx - :y1 miny - :x2 maxx - :y2 maxy - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny) - :points [(gpt/point minx miny) - (gpt/point maxx miny) - (gpt/point maxx maxy) - (gpt/point minx maxy)] - :type :rect})) + (let [points (->> shapes (mapcat :points))] + (gpr/points->selrect points))) (defn translate-to-frame [shape {:keys [x y] :as frame}] @@ -269,18 +172,20 @@ "Check if a shape is contained in the provided selection rect." [shape selrect] - (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (gpr/shape->rect-shape selrect) - {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (gpr/shape->rect-shape shape)] + (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} selrect + {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (:selrect shape)] (and (neg? (- sy1 ry1)) (neg? (- sx1 rx1)) (pos? (- sy2 ry2)) (pos? (- sx2 rx2))))) +;; TODO: This not will work for rotated shapes (defn overlaps? "Check if a shape overlaps with provided selection rect." - [shape selrect] - (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (gpr/shape->rect-shape selrect) - {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (gpr/shape->rect-shape shape)] + [shape rect] + (let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (gpr/rect->selrect rect) + {rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (gpr/points->selrect (:points shape))] + (and (< rx1 sx2) (> rx2 sx1) (< ry1 sy2) @@ -368,23 +273,29 @@ (defn setup-selrect [{:keys [x y width height] :as shape}] (-> shape - (assoc :selrect {:x x :y y - :width width :height height - :x1 x :y1 y - :x2 (+ x width) :y2 (+ y height)}))) + (assoc :selrect + {:x x :y y + :width width :height height + :x1 x :y1 y + :x2 (+ x width) :y2 (+ y height)}))) ;; EXPORTS -(def center gco/center) +(defn center-shape [shape] (gco/center-shape shape)) +(defn center-selrect [selrect] (gco/center-selrect selrect)) +(defn center-rect [rect] (gco/center-rect rect)) -(def shape->rect-shape gpr/shape->rect-shape) -(def fix-invalid-rect-values gtr/fix-invalid-rect-values) -(def rect->rect-shape gpr/rect->rect-shape) -(def points->selrect gpr/points->selrect) +(defn rect->selrect [rect] (gpr/rect->selrect rect)) -(def transform-shape-point gtr/transform-shape-point) -(def update-path-selrect gtr/update-path-selrect) -(def transform gtr/transform) +#_(def shape->rect-shape gpr/shape->rect-shape) +#_(def fix-invalid-rect-values gtr/fix-invalid-rect-values) +#_(def rect->rect-shape gpr/rect->rect-shape) +(defn points->selrect [points] (gpr/points->selrect points)) + +#_(def transform-shape-point gtr/transform-shape-point) +#_(def update-path-selrect gtr/update-path-selrect) +#_(def transform gtr/transform) (defn transform-shape [shape] (gtr/transform-shape shape)) -(def transform-matrix gtr/transform-matrix) - +(defn transform-matrix [shape] (gtr/transform-matrix shape)) +(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) +(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index 1ef8728f7e..f69a7d3ea6 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -17,32 +17,30 @@ [app.common.math :as mth] [app.common.data :as d])) -;; --- Center +(defn center-rect + [{:keys [x y width height]}] + (gpt/point (+ x (/ width 2)) + (+ y (/ height 2)))) -(declare center-rect) -(declare center-path) +(defn center-selrect + "Calculate the center of the shape." + [selrect] + (center-rect selrect)) -(defn center +(defn center-shape "Calculate the center of the shape." [shape] - (case (:type shape) - :curve (center-path shape) - :path (center-path shape) - (center-rect shape))) + (center-rect (:selrect shape))) -(defn- center-rect - [{:keys [x y width height] :as shape}] - (gpt/point (+ x (/ width 2)) (+ y (/ height 2)))) +(defn center-points [points] + (let [minx (transduce (map :x) min ##Inf points) + miny (transduce (map :y) min ##Inf points) + maxx (transduce (map :x) max ##-Inf points) + maxy (transduce (map :y) max ##-Inf points)] + (gpt/point (/ (+ minx maxx) 2) + (/ (+ miny maxy) 2)))) -(defn- center-path - [{:keys [segments] :as shape}] - (let [minx (apply min (map :x segments)) - miny (apply min (map :y segments)) - maxx (apply max (map :x segments)) - maxy (apply max (map :y segments))] - (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) - -(defn center->rect +(defn make-centered-rect "Creates a rect given a center and a width and height" [center width height] {:x (- (:x center) (/ width 2)) @@ -50,3 +48,30 @@ :width width :height height}) +;; --- Center +#_( + (declare center-rect) + (declare center-path) + + + + + + (defn- center-path + [{:keys [segments] :as shape}] + (let [minx (apply min (map :x segments)) + miny (apply min (map :y segments)) + maxx (apply max (map :x segments)) + maxy (apply max (map :y segments))] + (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) + + (defn center->rect + "Creates a rect given a center and a width and height" + [center width height] + {:x (- (:x center) (/ width 2)) + :y (- (:y center) (/ height 2)) + :width width + :height height}) + + + ) diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index 60810fc7fb..10b6fa0e44 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -16,6 +16,8 @@ [app.common.math :as mth] [app.common.data :as d])) +(defn segments->points [segments] + segments) + (defn content->points [content] (map #(gpt/point (-> % :param :x) (-> % :param :y)) content)) - diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index 8f06cae97b..e5204a5e9c 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -18,66 +18,97 @@ [app.common.math :as mth] [app.common.data :as d])) -;; --- SHAPE -> RECT +(defn rect->points [{:keys [x y width height]}] + [(gpt/point x y) + (gpt/point (+ x width) y) + (gpt/point (+ x width) (+ y height)) + (gpt/point x (+ y height))]) -(defn- rect->rect-shape - [{:keys [x y width height] :as shape}] - (assoc shape - :x1 x - :y1 y - :x2 (+ x width) - :y2 (+ y height))) - -(defn- path->rect-shape - [{:keys [segments] :as shape}] - (merge shape - {:type :rect} - (:selrect shape))) - -(defn shape->rect-shape - "Coerce shape to rect like shape." - - [{:keys [type] :as shape}] - (case type - (:curve :path) (path->rect-shape shape) - (rect->rect-shape shape))) - -;; Shape->PATH - -(declare rect->path) - -(defn shape->path - [shape] - (case (:type shape) - (:curve :path) shape - (rect->path shape))) - -(defn rect->path - [{:keys [x y width height] :as shape}] - - (let [points [(gpt/point x y) - (gpt/point (+ x width) y) - (gpt/point (+ x width) (+ y height)) - (gpt/point x (+ y height)) - (gpt/point x y)]] - (-> shape - (assoc :type :path) - (assoc :segments points)))) - -;; -- Points - -(defn points->selrect [points] +(defn points->rect [points] (let [minx (transduce (map :x) min ##Inf points) miny (transduce (map :y) min ##Inf points) maxx (transduce (map :x) max ##-Inf points) maxy (transduce (map :y) max ##-Inf points)] - {:x1 minx - :y1 miny - :x2 maxx - :y2 maxy - :x minx + {:x minx :y miny :width (- maxx minx) - :height (- maxy miny) - :type :rect})) + :height (- maxy miny)})) +(defn points->selrect [points] + (let [{:keys [x y width height] :as rect} (points->rect points)] + (assoc rect + :x1 x + :x2 (+ x width) + :y1 y + :y2 (+ y height)))) + +(defn rect->selrect [rect] + (-> rect rect->points points->selrect)) + +;; --- SHAPE -> RECT +#_( + (defn- rect->rect-shape + [{:keys [x y width height] :as shape}] + (assoc shape + :x1 x + :y1 y + :x2 (+ x width) + :y2 (+ y height))) + + (defn- path->rect-shape + [{:keys [segments] :as shape}] + (merge shape + {:type :rect} + (:selrect shape))) + + (defn shape->rect-shape + "Coerce shape to rect like shape." + + [{:keys [type] :as shape}] + (case type + (:curve :path) (path->rect-shape shape) + (rect->rect-shape shape))) + + ;; Shape->PATH + + (declare rect->path) + + (defn shape->path + [shape] + (case (:type shape) + (:curve :path) shape + (rect->path shape))) + + (defn rect->path + [{:keys [x y width height] :as shape}] + + (let [points [(gpt/point x y) + (gpt/point (+ x width) y) + (gpt/point (+ x width) (+ y height)) + (gpt/point x (+ y height)) + (gpt/point x y)]] + (-> shape + (assoc :type :path) + (assoc :segments points)))) + + ;; -- Points + + (defn points->selrect [points] + (let [minx (transduce (map :x) min ##Inf points) + miny (transduce (map :y) min ##Inf points) + maxx (transduce (map :x) max ##-Inf points) + maxy (transduce (map :y) max ##-Inf points)] + {:x1 minx + :y1 miny + :x2 maxx + :y2 maxy + :x minx + :y miny + :width (- maxx minx) + :height (- maxy miny) + :type :rect})) + + + + + ) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index ecb2acd163..94771bbf7f 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -19,160 +19,82 @@ [app.common.math :as mth] [app.common.data :as d])) -;; --- Transform Shape +(defn transform-matrix + "Returns a transformation matrix without changing the shape properties. + The result should be used in a `transform` attribute in svg" + ([{:keys [x y] :as shape}] + (let [shape-center (gco/center-shape shape)] + (-> (gmt/matrix) + (gmt/translate shape-center) + (gmt/multiply (:transform shape (gmt/matrix))) + (gmt/translate (gpt/negate shape-center)))))) -(declare transform-rect) -(declare transform-path) - -(defn transform - "Apply the matrix transformation to shape." - [{:keys [type] :as shape} xfmt] - (if (gmt/matrix? xfmt) - (case type - :path (transform-path shape xfmt) - :curve (transform-path shape xfmt) - (transform-rect shape xfmt)) - shape)) - -(defn center-transform [shape matrix] - (let [shape-center (gco/center shape)] - (-> shape - (transform - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply matrix) - (gmt/translate (gpt/negate shape-center))))))) - -(defn- transform-rect - [{:keys [x y width height] :as shape} mx] - (let [tl (gpt/transform (gpt/point x y) mx) - tr (gpt/transform (gpt/point (+ x width) y) mx) - bl (gpt/transform (gpt/point x (+ y height)) mx) - br (gpt/transform (gpt/point (+ x width) (+ y height)) mx) - ;; TODO: replace apply with transduce (performance) - minx (apply min (map :x [tl tr bl br])) - maxx (apply max (map :x [tl tr bl br])) - miny (apply min (map :y [tl tr bl br])) - maxy (apply max (map :y [tl tr bl br]))] - (assoc shape - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny)))) - -(defn- transform-path - [{:keys [segments] :as shape} xfmt] - (let [segments (mapv #(gpt/transform % xfmt) segments)] - (assoc shape :segments segments))) - - -(defn transform-shape-point +(defn transform-point-center "Transform a point around the shape center" - [point shape transform] - (let [shape-center (gco/center shape)] - (gpt/transform - point - (-> (gmt/multiply - (gmt/translate-matrix shape-center) - transform - (gmt/translate-matrix (gpt/negate shape-center))))))) + [point center matrix] + (gpt/transform + point + (gmt/multiply (gmt/translate-matrix center) + matrix + (gmt/translate-matrix (gpt/negate center))))) -(defn shape->points [shape] - (let [points (case (:type shape) - (:curve :path) (if (:content shape) - (gpa/content->points (:content shape)) - (:segments shape)) - (let [{:keys [x y width height]} shape] - [(gpt/point x y) - (gpt/point (+ x width) y) - (gpt/point (+ x width) (+ y height)) - (gpt/point x (+ y height))]))] - (->> points - (map #(transform-shape-point % shape (:transform shape (gmt/matrix)))) - (map gpt/round) - (vec)))) +(defn transform-points + ([points matrix] + (transform-points points nil matrix)) -(defn rect-path-dimensions [rect-path] - (let [seg (:segments rect-path) - [width height] (mapv (fn [[c1 c2]] (gpt/distance c1 c2)) (take 2 (d/zip seg (rest seg))))] - {:width width - :height height})) + ([points center matrix] -(defn update-path-selrect [shape] - (as-> shape $ - (assoc $ :points (shape->points $)) - (assoc $ :selrect (gpr/points->selrect (:points $))) - (assoc $ :x (get-in $ [:selrect :x])) - (assoc $ :y (get-in $ [:selrect :y])) - (assoc $ :width (get-in $ [:selrect :width])) - (assoc $ :height (get-in $ [:selrect :height])))) + (let [prev (if center (gmt/translate-matrix center) (gmt/matrix)) + post (if center (gmt/translate-matrix (gpt/negate center)) (gmt/matrix)) -(defn fix-invalid-rect-values - [rect-shape] - (letfn [(check [num] - (if (or (nil? num) (mth/nan? num) (= ##Inf num) (= ##-Inf num)) 0 num)) - (to-positive [num] (if (< num 1) 1 num))] - (-> rect-shape - (update :x check) - (update :y check) - (update :width (comp to-positive check)) - (update :height (comp to-positive check))))) + tr-point (fn [point] + (gpt/transform point (gmt/multiply prev matrix post)))] + (mapv tr-point points)))) -(defn calculate-rec-path-skew-angle - [path-shape] - (let [p1 (get-in path-shape [:segments 2]) - p2 (get-in path-shape [:segments 3]) - p3 (get-in path-shape [:segments 4]) - v1 (gpt/to-vec p1 p2) - v2 (gpt/to-vec p2 p3)] - (- 90 (gpt/angle-with-other v1 v2)))) +(defn transform-rect + "Transform a rectangles and changes its attributes" + [{:keys [x y width height] :as rect} matrix] -(defn calculate-rec-path-height - "Calculates the height of a paralelogram given by the path" - [path-shape] - (let [p1 (get-in path-shape [:segments 2]) - p2 (get-in path-shape [:segments 3]) - p3 (get-in path-shape [:segments 4]) - v1 (gpt/to-vec p1 p2) - v2 (gpt/to-vec p2 p3) - angle (gpt/angle-with-other v1 v2)] - (* (gpt/length v2) (mth/sin (mth/radians angle))))) - -(defn calculate-rec-path-rotation - [path-shape1 path-shape2 resize-vector] - - (let [idx-1 0 - idx-2 (cond (and (neg? (:x resize-vector)) (pos? (:y resize-vector))) 1 - (and (neg? (:x resize-vector)) (neg? (:y resize-vector))) 2 - (and (pos? (:x resize-vector)) (neg? (:y resize-vector))) 3 - :else 0) - p1 (get-in path-shape1 [:segments idx-1]) - p2 (get-in path-shape2 [:segments idx-2]) - v1 (gpt/to-vec (gco/center path-shape1) p1) - v2 (gpt/to-vec (gco/center path-shape2) p2) - - rot-angle (gpt/angle-with-other v1 v2) - rot-sign (if (> (* (:y v1) (:x v2)) (* (:x v1) (:y v2))) -1 1)] - (* rot-sign rot-angle))) + (let [points (-> (gpr/rect->points rect) + (transform-points matrix))] + (gpr/points->rect points))) -(defn transform-apply-modifiers - [shape] - (let [modifiers (:modifiers shape) - ds-modifier (:displacement modifiers (gmt/matrix)) +(defn- shape->points [shape] + (let [transform-point + (fn [point] + (-> point + (transform-point-center (gco/center-shape shape) + (:transform shape (gmt/matrix))) + (gpt/round))) + + points (cond + (and (= :path (:type shape)) (:content shape)) + (gpa/content->points (:content shape)) + + (seq (:segments shape)) + (gpa/segments->points (:content shape)) + + :else + (gpr/rect->points shape))] + (mapv transform-point points))) + +(defn normalize-scale + "We normalize the scale so it's not too close to 0" + [scale] + (cond + (and (< scale 0) (> scale -0.01)) -0.01 + (and (>= scale 0) (< scale 0.01)) 0.01 + :else scale)) + + +(defn modifiers->transform [current-transform center modifiers] + (let [ds-modifier (:displacement modifiers (gmt/matrix)) {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) ;; Normalize x/y vector coordinates because scale by 0 is infinite - res-x (cond - (and (< res-x 0) (> res-x -0.01)) -0.01 - (and (>= res-x 0) (< res-x 0.01)) 0.01 - :else res-x) - - res-y (cond - (and (< res-y 0) (> res-y -0.01)) -0.01 - (and (>= res-y 0) (< res-y 0.01)) 0.01 - :else res-y) - + res-x (normalize-scale res-x) + res-y (normalize-scale res-y) resize (gpt/point res-x res-y) origin (:resize-origin modifiers (gpt/point 0 0)) @@ -181,162 +103,423 @@ resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) rt-modif (or (:rotation modifiers) 0) - shape (-> shape - (transform ds-modifier)) + transform (-> (gmt/matrix) - shape-center (gco/center shape)] + ;; Applies the current resize transformation + (gmt/translate origin) + (gmt/multiply resize-transform) + (gmt/scale resize) + (gmt/multiply resize-transform-inverse) + (gmt/translate (gpt/negate origin)) - (-> (gpr/shape->path shape) - (transform (-> (gmt/matrix) + ;; Applies the stacked transformations + (gmt/translate center) + (gmt/multiply (gmt/rotate-matrix rt-modif)) + #_(gmt/multiply current-transform) + (gmt/translate (gpt/negate center)) - ;; Applies the current resize transformation - (gmt/translate origin) - (gmt/multiply resize-transform) - (gmt/scale resize) - (gmt/multiply resize-transform-inverse) - (gmt/translate (gpt/negate origin)) + ;; Displacement + (gmt/multiply ds-modifier))] + transform)) - ;; Applies the stacked transformations - (gmt/translate shape-center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - (gmt/multiply (:transform shape (gmt/matrix))) - (gmt/translate (gpt/negate shape-center))))))) +(defn- calculate-skew-angle + "Calculates the skew angle of the paralelogram given by the points" + [[p1 p2 p3 p4]] + (let [v1 (gpt/to-vec p3 p4) + v2 (gpt/to-vec p4 p1)] + (- 90 (gpt/angle-with-other v1 v2)))) -(defn transform-path-shape - [shape] - (-> shape - transform-apply-modifiers - update-path-selrect) - ;; TODO: Addapt for paths is not working - #_(let [shape-path (transform-apply-modifiers shape) - shape-path-center (center shape-path) +(defn- calculate-height + "Calculates the height of a paralelogram given by the points" + [[p1 p2 p3 p4]] + (let [v1 (gpt/to-vec p3 p4) + v2 (gpt/to-vec p4 p1) + angle (gpt/angle-with-other v1 v2)] + (* (gpt/length v2) (mth/sin (mth/radians angle))))) - shape-transform-inverse' (-> (gmt/matrix) - (gmt/translate shape-path-center) - (gmt/multiply (:transform-inverse shape (gmt/matrix))) - (gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0)))) - (gmt/translate (gpt/negate shape-path-center)))] - (-> shape-path - (transform shape-transform-inverse') - (add-rotate-transform (:rotation-modifier shape 0))))) +(defn- calculate-rotation + "Calculates the rotation between two shapes given the resize vector direction" + [points-shape1 points-shape2 flip-x flip-y] -(defn transform-rect-shape - [shape] - (let [;; Apply modifiers to the rect as a path so we have the end shape expected - shape-path (transform-apply-modifiers shape) - shape-center (gco/center shape-path) - resize-vector (-> (get-in shape [:modifiers :resize-vector] (gpt/point 1 1)) - (update :x #(if (zero? %) 1 %)) - (update :y #(if (zero? %) 1 %))) + (let [idx-1 0 + idx-2 (cond (and flip-x (not flip-y)) 1 + (and flip-x flip-y) 2 + (and (not flip-x) flip-y) 3 + :else 0) + p1 (nth points-shape1 idx-1) + p2 (nth points-shape2 idx-2) + v1 (gpt/to-vec (gco/center-points points-shape1) p1) + v2 (gpt/to-vec (gco/center-points points-shape2) p2) - ;; Reverse the current transformation stack to get the base rectangle - shape-path-temp (center-transform shape-path (:transform-inverse shape (gmt/matrix))) - shape-path-temp-dim (rect-path-dimensions shape-path-temp) - shape-path-temp-rec (gpr/shape->rect-shape shape-path-temp) + rot-angle (gpt/angle-with-other v1 v2) + rot-sign (if (> (* (:y v1) (:x v2)) (* (:x v1) (:y v2))) -1 1)] + (* rot-sign rot-angle))) - ;; This rectangle is the new data for the current rectangle. We want to change our rectangle - ;; to have this width, height, x, y - rec (gco/center->rect shape-center (:width shape-path-temp-dim) (:height shape-path-temp-dim)) - rec (fix-invalid-rect-values rec) - rec-path (gpr/rect->path rec) +(defn- calculate-dimensions + [[p1 p2 p3 p4]] + (let [width (gpt/distance p1 p2) + height (gpt/distance p2 p3)] + {:width width :height height})) + +(defn calculate-adjust-matrix + "Calculates a matrix that is a series of transformations we have to do to the transformed rectangle so that + after applying them the end result is the `shape-pathn-temp`. + This is compose of three transformations: skew, resize and rotation" + [points-temp points-rec flip-x flip-y] + (let [center (gco/center-points points-temp) - ;; The next matrix is a series of transformations we have to do to the previous rec so that - ;; after applying them the end result is the `shape-path-temp` - ;; This is compose of three transformations: skew, resize and rotation stretch-matrix (gmt/matrix) - skew-angle (calculate-rec-path-skew-angle shape-path-temp) + skew-angle (calculate-skew-angle points-temp) ;; When one of the axis is flipped we have to reverse the skew - skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) + ;; skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) + skew-angle (if (and (or flip-x flip-y) + (not (and flip-x flip-y))) (- skew-angle) skew-angle ) skew-angle (if (mth/nan? skew-angle) 0 skew-angle) - stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) - h1 (calculate-rec-path-height shape-path-temp) - h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix)) + h1 (calculate-height points-temp) + h2 (calculate-height (transform-points points-temp center stretch-matrix)) h3 (/ h1 h2) h3 (if (mth/nan? h3) 1 h3) stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) - rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) - shape-path-temp resize-vector) + rotation-angle (calculate-rotation + (transform-points points-rec (gco/center-points points-rec) stretch-matrix) + points-temp + flip-x + flip-y) stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) + stretch-matrix (-> (gmt/matrix) + (gmt/rotate rotation-angle) + (gmt/skew skew-angle 0) + (gmt/scale (gpt/point 1 h3))) + + ;; This is the inverse to be able to remove the transformation stretch-matrix-inverse (-> (gmt/matrix) (gmt/scale (gpt/point 1 h3)) (gmt/skew (- skew-angle) 0) - (gmt/rotate (- rotation-angle))) + (gmt/rotate (- rotation-angle)))] + [stretch-matrix stretch-matrix-inverse])) + + +(defn set-points-path + [shape points] + (let [shape (reduce (fn [acc [idx {:keys [x y]}]] + (-> acc + (assoc-in [:content idx :params :x] x) + (assoc-in [:content idx :params :y] y))) shape (d/enumerate points)) + + shape (assoc shape + :points points + :selrect (gpr/points->selrect points))] + shape)) + +(defn set-points-curve + [shape points] + shape) + +(defn set-points-rect + "Given a new set of points transformed, set up the rectangle so it keeps + its properties. We adjust de x,y,width,height and create a custom transform" + [shape points] + ;; + (let [center (gco/center-points points) + + ;; Reverse the current transformation stack to get the base rectangle + tr-inverse (:transform-inverse shape (gmt/matrix)) + modifiers (:modifiers shape) + + points-temp (transform-points points center tr-inverse) + points-temp-dim (calculate-dimensions points-temp) + + ;; This rectangle is the new data for the current rectangle. We want to change our rectangle + ;; to have this width, height, x, y + rect-shape (gco/make-centered-rect center + (:width points-temp-dim) + (:height points-temp-dim)) + rect-points (gpr/rect->points rect-shape) + + [matrix matrix-inverse] (calculate-adjust-matrix points-temp rect-points (:flip-x shape) (:flip-y shape)) + ;;[matrix matrix-inverse] [(gmt/matrix) (gmt/matrix)] new-shape (as-> shape $ - (merge $ rec) + (merge $ rect-shape) (update $ :x #(mth/precision % 0)) (update $ :y #(mth/precision % 0)) (update $ :width #(mth/precision % 0)) (update $ :height #(mth/precision % 0)) - (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) - (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) - (assoc $ :points (shape->points $)) - (assoc $ :selrect (gpr/points->selrect (:points $))) - (update $ :selrect fix-invalid-rect-values) + (update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix)) + (update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix)))) + (assoc $ :points (into [] points)) + (assoc $ :selrect (gpr/rect->selrect rect-shape) #_(gpr/points->selrect points)) (update $ :rotation #(mod (+ (or % 0) (or (get-in $ [:modifiers :rotation]) 0)) 360)))] new-shape)) -(defn transform-shape - "Transform the shape properties given the modifiers" - ([shape] - - (letfn [(transform-by-type [shape] - (case (:type shape) - (:curve :path) - (transform-path-shape shape) +(defn set-points [shape points] + (let [set-points-fn + (case (:type shape) + :path set-points-path + :curve set-points-curve + set-points-rect)] + (set-points-fn shape points))) - #_:default - (transform-rect-shape shape)))] - - (cond-> shape - (:modifiers shape) (transform-by-type) - :always (dissoc :modifiers))) +(defn set-flip [shape modifiers] + (cond-> shape + (< (get-in modifiers [:resize-vector :x]) 0) (update :flip-x not) + (< (get-in modifiers [:resize-vector :y]) 0) (update :flip-y not))) - #_(cond-> shape - (and (:modifiers shape) (#{:curve :path} (:type shape))) - (transform-path-shape shape) - - (and (:modifiers shape) (not (#{:curve :path} (:type shape)))) - (transform-rect-shape shape) +(defn transform-shape [shape] + (if (:modifiers shape) + (let [points (:points shape (shape->points shape)) + center (gco/center-points points) + transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape)) + tr-points (transform-points points transform)] + (-> shape + (set-flip (:modifiers shape)) + (set-points tr-points) + (dissoc :modifiers))) + shape)) - true - (dissoc :modifiers) - )) - #_([frame shape kk] +#_(defn transform-shape + "Transform the shape properties given the modifiers" + ([shape] + (letfn [(transform-by-type [shape] + (case (:type shape) + (:curve :path) + (transform-path-shape shape) + + #_:default + (transform-rect-shape shape)))] + + (cond-> shape + (:modifiers shape) (transform-by-type) + :always (dissoc :modifiers))))) + +;; --- Transform Shape + +#_( + (declare transform-rect) + (declare transform-path) + (declare transform) + + (defn center-transform [shape matrix] + (let [shape-center (gco/center shape)] + (-> shape + (transform + (-> (gmt/matrix) + (gmt/translate shape-center) + (gmt/multiply matrix) + (gmt/translate (gpt/negate shape-center))))))) + + (defn- transform-rect + [{:keys [x y width height] :as shape} mx] + (let [tl (gpt/transform (gpt/point x y) mx) + tr (gpt/transform (gpt/point (+ x width) y) mx) + bl (gpt/transform (gpt/point x (+ y height)) mx) + br (gpt/transform (gpt/point (+ x width) (+ y height)) mx) + ;; TODO: replace apply with transduce (performance) + minx (apply min (map :x [tl tr bl br])) + maxx (apply max (map :x [tl tr bl br])) + miny (apply min (map :y [tl tr bl br])) + maxy (apply max (map :y [tl tr bl br]))] + (assoc shape + :x minx + :y miny + :width (- maxx minx) + :height (- maxy miny)))) + + (defn- transform-path + [{:keys [segments] :as shape} xfmt] + (let [segments (mapv #(gpt/transform % xfmt) segments)] + (assoc shape :segments segments))) - #_(if (:modifiers shape) - (-> (case (:type shape) - (:curve :path) (transform-path-shape shape) - (transform-rect-shape shape)) - (dissoc :modifiers)) - shape) - #_(let [new-shape - ] - - #_(cond-> new-shape - frame (translate-to-frame frame))))) + + (defn update-path-selrect [shape] + (as-> shape $ + (assoc $ :points (shape->points $)) + (assoc $ :selrect (gpr/points->selrect (:points $))) + (assoc $ :x (get-in $ [:selrect :x])) + (assoc $ :y (get-in $ [:selrect :y])) + (assoc $ :width (get-in $ [:selrect :width])) + (assoc $ :height (get-in $ [:selrect :height])))) + + (defn fix-invalid-rect-values + [rect-shape] + (letfn [(check [num] + (if (or (nil? num) (mth/nan? num) (= ##Inf num) (= ##-Inf num)) 0 num)) + (to-positive [num] (if (< num 1) 1 num))] + (-> rect-shape + (update :x check) + (update :y check) + (update :width (comp to-positive check)) + (update :height (comp to-positive check))))) + + + + + + + (declare transform-points) + + (defn apply-modifiers + [transform-stack modifiers points] + (let [ds-modifier (:displacement modifiers (gmt/matrix)) + {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) + + ;; Normalize x/y vector coordinates because scale by 0 is infinite + res-x (normalize-scale res-x) + res-y (normalize-scale res-y) + resize (gpt/point res-x res-y) + + origin (:resize-origin modifiers (gpt/point 0 0)) + + resize-transform (:resize-transform modifiers (gmt/matrix)) + resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) + rt-modif (or (:rotation modifiers) 0) + + points (transform-points ds-modifier) + center (gco/center-points points)] + + (-> points + (transform-points + (-> (gmt/matrix) + + ;; Applies the current resize transformation + (gmt/translate origin) + (gmt/multiply resize-transform) + (gmt/scale resize) + (gmt/multiply resize-transform-inverse) + (gmt/translate (gpt/negate origin)) + + ;; Applies the stacked transformations + (gmt/translate center) + (gmt/multiply (gmt/rotate-matrix rt-modif)) + (gmt/multiply transform-stack) + (gmt/translate (gpt/negate center))))))) + + (defn transform-path-shape + [shape] + shape + #_(-> shape + transform-apply-modifiers + update-path-selrect) + ;; TODO: Addapt for paths is not working + #_(let [shape-path (transform-apply-modifiers shape) + shape-path-center (center shape-path) + + shape-transform-inverse' (-> (gmt/matrix) + (gmt/translate shape-path-center) + (gmt/multiply (:transform-inverse shape (gmt/matrix))) + (gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0)))) + (gmt/translate (gpt/negate shape-path-center)))] + (-> shape-path + (transform shape-transform-inverse') + (add-rotate-transform (:rotation-modifier shape 0))))) + + (defn adjust-rect-transforms [shape] + ) + + (defn transform-rect-shape + [shape] + (let [points (-> (:points shape (shape->points shape)) + (apply-modifiers (:transform shape) (:modifiers shape) points)) + + center (gco/center-points points) + + resize-vector (-> (get-in shape [:modifiers :resize-vector] (gpt/point 1 1)) + (update :x #(if (zero? %) 1 %)) + (update :y #(if (zero? %) 1 %))) + + ;; Reverse the current transformation stack to get the base rectangle + tr-inverse (:transform-inverse shape (gmt/matrix)) + points-temp (transform-poins points center tr-inverse) + points-temp-dim (gpr/rect-points-dimensions points) + points-temp-rec (gpr/points->selrect points) + + ;; This rectangle is the new data for the current rectangle. We want to change our rectangle + ;; to have this width, height, x, y + rec (-> (gco/center->rect center (:width points-temp-dim) (:height points-temp-dim)) + (gpr/rect->points)) + ;;rec (fix-invalid-rect-values rec) + ;;rec-path (gpr/rect->path rec) + + ;; The next matrix is a series of transformations we have to do to the previous rec so that + ;; after applying them the end result is the `shape-path-temp` + ;; This is compose of three transformations: skew, resize and rotation + stretch-matrix (gmt/matrix) + + skew-angle (calculate-rec-path-skew-angle shape-path-temp) + + ;; When one of the axis is flipped we have to reverse the skew + skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) + skew-angle (if (mth/nan? skew-angle) 0 skew-angle) -(defn transform-matrix - "Returns a transformation matrix without changing the shape properties. - The result should be used in a `transform` attribute in svg" - ([{:keys [x y] :as shape}] - (let [shape-center (gco/center shape)] - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply (:transform shape (gmt/matrix))) - (gmt/translate (gpt/negate shape-center)))))) + stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) + + h1 (calculate-rec-path-height shape-path-temp) + h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix)) + h3 (/ h1 h2) + h3 (if (mth/nan? h3) 1 h3) + + stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) + + rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) + shape-path-temp resize-vector) + + stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) + + ;; This is the inverse to be able to remove the transformation + stretch-matrix-inverse (-> (gmt/matrix) + (gmt/scale (gpt/point 1 h3)) + (gmt/skew (- skew-angle) 0) + (gmt/rotate (- rotation-angle))) + + new-shape (as-> shape $ + (merge $ rec) + (update $ :x #(mth/precision % 0)) + (update $ :y #(mth/precision % 0)) + (update $ :width #(mth/precision % 0)) + (update $ :height #(mth/precision % 0)) + (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) + (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) + (assoc $ :points (shape->points $)) + (assoc $ :selrect (gpr/points->selrect (:points $))) + (update $ :selrect fix-invalid-rect-values) + (update $ :rotation #(mod (+ (or % 0) + (or (get-in $ [:modifiers :rotation]) 0)) 360)))] + new-shape)) + + (defn transform-points + "Apply the matrix transformation to points" + [points xfmt] + + (cond->> points + (gmt/matrix? xfmt) (map #(gpt/transform % xfmt)))) + + #_(defn transform + "Apply the matrix transformation to shape" + [{:keys [type] :as shape} xfmt] + (if (gmt/matrix? xfmt) + (case type + :path (transform-path shape xfmt) + :curve (transform-path shape xfmt) + (transform-rect shape xfmt)) + shape)) + + + + + + ) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 0feaccbfc0..ae5a919831 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -273,7 +273,9 @@ (s/every uuid? :kind vector?)) (s/def ::shape-attrs - (s/keys :opt-un [:internal.shape/blocked + (s/keys :req-un [:internal.shape/selrect + :internal.shape/points] + :opt-un [:internal.shape/blocked :internal.shape/collapsed :internal.shape/content :internal.shape/fill-color @@ -309,8 +311,6 @@ :internal.shape/width :internal.shape/height :internal.shape/interactions - :internal.shape/selrect - :internal.shape/points :internal.shape/masked-group? :internal.shape/shadow :internal.shape/blur])) @@ -764,7 +764,7 @@ (defn rotation-modifiers [center shape angle] - (let [displacement (let [shape-center (geom/center shape)] + (let [displacement (let [shape-center (geom/center-shape shape)] (-> (gmt/matrix) (gmt/rotate angle center) (gmt/rotate (- angle) shape-center)))] @@ -783,7 +783,7 @@ (distinct)) shapes))) (update-group [group objects] - (let [gcenter (geom/center group) + (let [gcenter (geom/center-shape group) gxfm (comp (map #(get objects %)) (map #(-> % diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index ea4755fcc6..70cf54a206 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -14,6 +14,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.geom.proportions :as gpr] [app.common.geom.align :as gal] [app.common.math :as mth] [app.common.pages :as cp] @@ -30,6 +31,7 @@ [app.main.data.workspace.selection :as dws] [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] + [app.main.data.workspace.drawing :as dwd] [app.main.repo :as rp] [app.main.store :as st] [app.main.streams :as ms] @@ -472,10 +474,10 @@ (let [vbox (update vbox :x + (:left-offset vbox)) new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom) old-zoom (:zoom local) - center (if center center (gsh/center vbox)) + center (if center center (gsh/center-rect vbox)) scale (/ old-zoom new-zoom) mtx (gmt/scale-matrix (gpt/point scale) center) - vbox' (gsh/transform vbox mtx) + vbox' (gsh/transform-rect vbox mtx) vbox' (update vbox' :x - (:left-offset vbox))] (-> local (assoc :zoom new-zoom) @@ -546,50 +548,6 @@ ;; --- Add shape to Workspace -(declare start-edition-mode) - -(defn add-shape - [attrs] - (us/verify ::shape-attrs attrs) - (ptk/reify ::add-shape - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - - id (uuid/next) - shape (geom/setup-proportions attrs) - - unames (dwc/retrieve-used-names objects) - name (dwc/generate-unique-name unames (:name shape)) - - frame-id (or (:frame-id attrs) - (cph/frame-id-by-position objects attrs)) - - shape (merge - (if (= :frame (:type shape)) - cp/default-frame-attrs - cp/default-shape-attrs) - (assoc shape - :id id - :name name)) - - rchange {:type :add-obj - :id id - :page-id page-id - :frame-id frame-id - :obj shape} - uchange {:type :del-obj - :page-id page-id - :id id}] - - (rx/concat - (rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true}) - (dws/select-shapes (d/ordered-set id))) - (when (= :text (:type attrs)) - (->> (rx/of (start-edition-mode id)) - (rx/observe-on :async)))))))) - (defn- viewport-center [state] (let [{:keys [x y width height]} (get-in state [:workspace-local :vbox])] @@ -615,8 +573,8 @@ (merge data) (merge {:x x :y y}) (assoc :frame-id frame-id) - (rx/of (add-shape shape)))))) (gsh/setup-selrect))] + (rx/of (dwc/add-shape shape)))))) ;; --- Update Shape Attrs @@ -954,7 +912,7 @@ (defn align-objects [axis] - (us/verify ::geom/align-axis axis) + (us/verify ::gal/align-axis axis) (ptk/reify :align-objects ptk/WatchEvent (watch [_ state stream] @@ -992,17 +950,17 @@ [objects object-id axis] (let [object (get objects object-id) frame (get objects (:frame-id object))] - (geom/align-to-rect object frame axis objects))) + (gal/align-to-rect object frame axis objects))) (defn align-objects-list [objects selected axis] (let [selected-objs (map #(get objects %) selected) - rect (geom/selection-rect selected-objs)] - (mapcat #(geom/align-to-rect % rect axis objects) selected-objs))) + rect (gsh/selection-rect selected-objs)] + (mapcat #(gal/align-to-rect % rect axis objects) selected-objs))) (defn distribute-objects [axis] - (us/verify ::geom/dist-axis axis) + (us/verify ::gal/dist-axis axis) (ptk/reify :align-objects ptk/WatchEvent (watch [_ state stream] @@ -1010,7 +968,7 @@ objects (dwc/lookup-page-objects state page-id) selected (get-in state [:workspace-local :selected]) moved (-> (map #(get objects %) selected) - (geom/distribute-space axis objects))] + (gal/distribute-space axis objects))] (loop [moved (seq moved) rchanges [] uchanges []] @@ -1035,62 +993,6 @@ :operations ops2 :id (:id curr)}))))))))) -;; --- Start shape "edition mode" - -(declare clear-edition-mode) - -(defn start-edition-mode - [id] - (us/assert ::us/uuid id) - (ptk/reify ::start-edition-mode - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:workspace-local :edition] id)) - - ptk/WatchEvent - (watch [_ state stream] - (->> stream - (rx/filter dwc/interrupt?) - (rx/take 1) - (rx/map (constantly clear-edition-mode)))))) - -(def clear-edition-mode - (ptk/reify ::clear-edition-mode - ptk/UpdateEvent - (update [_ state] - (update state :workspace-local dissoc :edition)))) - -;; --- Select for Drawing - -(def clear-drawing - (ptk/reify ::clear-drawing - ptk/UpdateEvent - (update [_ state] - (update state :workspace-drawing dissoc :tool :object)))) - -(defn select-for-drawing - ([tool] (select-for-drawing tool nil)) - ([tool data] - (ptk/reify ::select-for-drawing - ptk/UpdateEvent - (update [_ state] - (update state :workspace-drawing assoc :tool tool :object data)) - - ptk/WatchEvent - (watch [_ state stream] - (let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)] - (rx/merge - (rx/of (dws/deselect-all)) - - ;; NOTE: comments are a special case and they manage they - ;; own interrupt cycle. - (when (not= tool :comments) - (->> stream - (rx/filter dwc/interrupt?) - (rx/take 1) - (rx/map (constantly clear-drawing)) - (rx/take-until stoper))))))))) - ;; --- Update Dimensions ;; Event mainly used for handling user modification of the size of the @@ -1104,7 +1006,7 @@ (ptk/reify ::update-dimensions ptk/WatchEvent (watch [_ state stream] - (rx/of (dwc/update-shapes ids #(geom/resize-rect % attr value)))))) + (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value)))))) ;; --- Shape Proportions @@ -1118,7 +1020,7 @@ (if-not lock (assoc shape :proportion-lock false) (-> (assoc shape :proportion-lock true) - (geom/assign-proportions))))))))) + (gpr/assign-proportions))))))))) ;; --- Update Shape Position (s/def ::x number?) @@ -1157,7 +1059,7 @@ (let [page-id (:current-page-id state)] (-> state (update-in [:workspace-data page-id :objects id :segments index] gpt/add delta) - (update-in [:workspace-data page-id :objects id] geom/update-path-selrect)))))) + (update-in [:workspace-data page-id :objects id] gsh/update-path-selrect)))))) ;; --- Shape attrs (Layers Sidebar) @@ -1290,7 +1192,7 @@ ;; When the parent frame is not selected we change to relative ;; coordinates (let [frame (get objects (:frame-id shape))] - (geom/translate-to-frame shape frame)) + (gsh/translate-to-frame shape frame)) shape)) (prepare [result objects selected id] @@ -1329,7 +1231,7 @@ ptk/WatchEvent (watch [_ state stream] (let [selected-objs (map #(get objects %) selected) - wrapper (geom/selection-rect selected-objs) + wrapper (gsh/selection-rect selected-objs) orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper)) mouse-pos @ms/mouse-position @@ -1359,7 +1261,7 @@ (map #(get-in % [:obj :id])) (into (d/ordered-set)))] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes selected)))))) + (dwc/select-shapes selected)))))) (defn- image-uploaded [image] @@ -1446,7 +1348,7 @@ page-id (:current-page-id state) frame-id (-> (dwc/lookup-page-objects state page-id) (cph/frame-id-by-position @ms/mouse-position)) - shape (geom/setup-selrect + shape (gsh/setup-selrect {:id id :type :text :name "Text" @@ -1459,7 +1361,7 @@ :content (as-content text)})] (rx/of dwc/start-undo-transaction (dws/deselect-all) - (add-shape shape) + (dwc/add-shape shape) dwc/commit-undo-transaction))))) (defn update-shape-flags @@ -1490,7 +1392,7 @@ (when-not (empty? shapes) (let [[group rchanges uchanges] (dws/prepare-create-group page-id shapes "Group-" false)] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes (d/ordered-set (:id group)))))))))) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) (def ungroup-selected (ptk/reify ::ungroup-selected @@ -1568,7 +1470,7 @@ :val (:fill-color mask)}]}))] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes (d/ordered-set (:id group)))))))))) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) (def unmask-group (ptk/reify ::unmask-group @@ -1595,7 +1497,7 @@ :val (:masked-group? group)}]}]] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes (d/ordered-set (:id group)))))))))) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1718,10 +1620,14 @@ (def select-shape dws/select-shape) (def deselect-all dws/deselect-all) -(def select-shapes dws/select-shapes) +(def select-shapes dwc/select-shapes) (def duplicate-selected dws/duplicate-selected) (def handle-selection dws/handle-selection) (def select-inside-group dws/select-inside-group) +(def select-for-drawing dwd/select-for-drawing) +(def clear-edition-mode dwc/clear-edition-mode) +(def add-shape dwc/add-shape) +(def start-edition-mode dwc/start-edition-mode) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1753,12 +1659,12 @@ "ctrl+shift+z" #(st/emit! dwc/redo) "ctrl+y" #(st/emit! dwc/redo) "ctrl+q" #(st/emit! dwc/reinitialize-undo) - "a" #(st/emit! (select-for-drawing :frame)) - "b" #(st/emit! (select-for-drawing :rect)) - "e" #(st/emit! (select-for-drawing :circle)) + "a" #(st/emit! (dwd/select-for-drawing :frame)) + "b" #(st/emit! (dwd/select-for-drawing :rect)) + "e" #(st/emit! (dwd/select-for-drawing :circle)) "t" #(st/emit! dwtxt/start-edit-if-selected - (select-for-drawing :text)) - "w" #(st/emit! (select-for-drawing :path)) + (dwd/select-for-drawing :text)) + "w" #(st/emit! (dwd/select-for-drawing :path)) "ctrl+c" #(st/emit! copy-selected) "ctrl+v" #(st/emit! paste) "ctrl+x" #(st/emit! copy-selected delete-selected) @@ -1778,4 +1684,3 @@ "right" #(st/emit! (dwt/move-selected :right false)) "left" #(st/emit! (dwt/move-selected :left false)) "i" #(st/emit! (mdc/picker-for-selected-shape ))}) - diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 282efc5002..3275799b5f 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -20,8 +20,12 @@ [app.common.uuid :as uuid] [app.main.worker :as uw] [app.util.timers :as ts] - [app.common.geom.shapes :as geom])) + [app.common.geom.proportions :as gpr] + [app.common.geom.shapes :as gsh])) +(s/def ::shape-attrs ::cp/shape-attrs) +(s/def ::set-of-string (s/every string? :kind set?)) +(s/def ::ordered-set-of-uuid (s/every uuid? :kind d/ordered-set?)) ;; --- Protocols (declare setup-selection-index) @@ -158,7 +162,7 @@ (defn get-frame-at-point [objects point] (let [frames (cph/select-frames objects)] - (d/seek #(geom/has-point? % point) frames))) + (d/seek #(gsh/has-point? % point) frames))) (defn- extract-numeric-suffix @@ -171,8 +175,6 @@ [objects] (into #{} (map :name) (vals objects))) -(s/def ::set-of-string - (s/every string? :kind set?)) (defn generate-unique-name "A unique name generator" @@ -434,3 +436,85 @@ [rchanges uchanges] (impl-gen-changes objects page-id (seq ids))] (rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))) + +(defn select-shapes + [ids] + (us/verify ::ordered-set-of-uuid ids) + (ptk/reify ::select-shapes + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:workspace-local :selected] ids)) + + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (lookup-page-objects state page-id)] + (rx/of (expand-all-parents ids objects)))))) + +;; --- Start shape "edition mode" + +(declare clear-edition-mode) + +(defn start-edition-mode + [id] + (us/assert ::us/uuid id) + (ptk/reify ::start-edition-mode + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:workspace-local :edition] id)) + + ptk/WatchEvent + (watch [_ state stream] + (->> stream + (rx/filter interrupt?) + (rx/take 1) + (rx/map (constantly clear-edition-mode)))))) + +(def clear-edition-mode + (ptk/reify ::clear-edition-mode + ptk/UpdateEvent + (update [_ state] + (update state :workspace-local dissoc :edition)))) + + +(defn add-shape + [attrs] + (us/verify ::shape-attrs attrs) + (ptk/reify ::add-shape + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (lookup-page-objects state page-id) + + id (uuid/next) + shape (gpr/setup-proportions attrs) + + unames (retrieve-used-names objects) + name (generate-unique-name unames (:name shape)) + + frame-id (or (:frame-id attrs) + (cph/frame-id-by-position objects attrs)) + + shape (merge + (if (= :frame (:type shape)) + cp/default-frame-attrs + cp/default-shape-attrs) + (assoc shape + :id id + :name name)) + + rchange {:type :add-obj + :id id + :page-id page-id + :frame-id frame-id + :obj shape} + uchange {:type :del-obj + :page-id page-id + :id id}] + + (rx/concat + (rx/of (commit-changes [rchange] [uchange] {:commit-local? true}) + (select-shapes (d/ordered-set id))) + (when (= :text (:type attrs)) + (->> (rx/of (start-edition-mode id)) + (rx/observe-on :async)))))))) diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index aeff2af30d..63b0668fc3 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -12,15 +12,48 @@ (:require [beicon.core :as rx] [potok.core :as ptk] + [app.common.spec :as us] [app.common.pages :as cp] [app.common.uuid :as uuid] + [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.selection :as dws] [app.main.data.workspace.drawing.common :as common] [app.main.data.workspace.drawing.path :as path] [app.main.data.workspace.drawing.curve :as curve] [app.main.data.workspace.drawing.box :as box])) +(declare start-drawing) (declare handle-drawing) +;; --- Select for Drawing + +(defn select-for-drawing + ([tool] (select-for-drawing tool nil)) + ([tool data] + (ptk/reify ::select-for-drawing + ptk/UpdateEvent + (update [_ state] + (update state :workspace-drawing assoc :tool tool :object data)) + + ptk/WatchEvent + (watch [_ state stream] + (let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)] + (rx/merge + (rx/of (dws/deselect-all)) + + (when (= tool :path) + (rx/of (start-drawing :path))) + + ;; NOTE: comments are a special case and they manage they + ;; own interrupt cycle. + (when (not= tool :comments) + (->> stream + (rx/filter dwc/interrupt?) + (rx/take 1) + (rx/map (constantly common/clear-drawing)) + (rx/take-until stoper))))))))) + + ;; NOTE/TODO: when an exception is raised in some point of drawing the ;; draw lock is not released so the user need to refresh in order to ;; be able draw again. THIS NEED TO BE REVISITED @@ -68,3 +101,4 @@ ;; Export (def close-drawing-path path/close-drawing-path) + diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 35e84e2789..bdcdb1aeaf 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -74,7 +74,8 @@ ;; Initial SNAP (->> (snap/closest-snap-point page-id [shape] layout initial) (rx/map (fn [{:keys [x y]}] - #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) + #(update-in % [:workspace-drawing :object] gsh/absolute-move (gpt/point x y)) + ))) (->> ms/mouse-position (rx/filter #(> (gpt/distance % initial) 2)) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 24ffb0d65e..424287b3f9 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -13,17 +13,23 @@ [potok.core :as ptk] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.selection :as dws] [app.main.streams :as ms])) +(def clear-drawing + (ptk/reify ::clear-drawing + ptk/UpdateEvent + (update [_ state] + (update state :workspace-drawing dissoc :tool :object)))) + (def handle-finish-drawing (ptk/reify ::handle-finish-drawing ptk/WatchEvent (watch [_ state stream] (let [shape (get-in state [:workspace-drawing :object])] (rx/concat - (rx/of dw/clear-drawing) + (rx/of clear-drawing) (when (:initialized? shape) (let [shape-click-width (case (:type shape) :text 3 @@ -52,5 +58,5 @@ (rx/of dwc/start-undo-transaction) (rx/empty)) - (rx/of (dw/deselect-all) - (dw/add-shape shape)))))))))) + (rx/of (dws/deselect-all) + (dwc/add-shape shape)))))))))) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 5053d79fd5..108a8b5210 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -11,6 +11,7 @@ (:require [beicon.core :as rx] [potok.core :as ptk] + [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.main.streams :as ms] [app.util.geom.path :as path] @@ -27,13 +28,18 @@ (defn insert-point-segment [state point] (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) +(defn update-selrect [{:keys [segments] :as shape}] + (let [points (->> segments + (map #(apply gpt/point %)))] + (assoc shape :selrect (gsh/points->selrect points)))) + (defn finish-drawing-curve [state] (update-in state [:workspace-drawing :object] (fn [shape] (-> shape (update :segments #(path/simplify % simplify-tolerance)) - (gsh/update-path-selrect))))) + (update-selrect))))) (defn handle-drawing-curve [] (ptk/reify ::handle-drawing-curve diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 3d92288fca..e9b7382b41 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -17,23 +17,23 @@ [app.util.geom.path :as path] [app.main.data.workspace.drawing.common :as common])) -(defn stoper-event? [{:keys [type shift] :as event}] +(defn finish-event? [{:keys [type shift] :as event}] (or (= event ::end-path-drawing) (= event :interrupt) - (and (ms/mouse-event? event) + #_(and (ms/mouse-event? event) (or (= type :double-click) (= type :context-menu))) (and (ms/keyboard-event? event) (= type :down) (= 13 (:key event))))) -(defn init-path [] +#_(defn init-path [] (fn [state] (update-in state [:workspace-drawing :object] assoc :content [] :initialized? true))) -(defn add-path-command [command] +#_(defn add-path-command [command] (fn [state] (update-in state [:workspace-drawing :object :content] conj command))) @@ -43,7 +43,7 @@ (cond-> state exists? (assoc-in [:workspace-drawing :object :segments index] point)))) -(defn finish-drawing-path [] +#_(defn finish-drawing-path [] (fn [state] (update-in state [:workspace-drawing :object] @@ -52,17 +52,109 @@ (gsh/update-path-selrect)))))) -(defn handle-drawing-path [] +(defn calculate-selrect [shape] + (let [points (->> shape + :content + (mapv #(gpt/point + (-> % :params :x) + (-> % :params :y))))] + (assoc shape + :points points + :selrect (gsh/points->selrect points)))) +(defn init-path [] + (ptk/reify ::init-path + ptk/UpdateEvent + (update [_ state] + (-> state + (assoc-in [:workspace-drawing :object :initialized?] true) + (assoc-in [:workspace-drawing :object :last-point] nil))))) + +(defn finish-path [] + (ptk/reify ::finish-path + ptk/UpdateEvent + (update [_ state] + (-> state + (assoc-in [:workspace-drawing :object :last-point] nil) + (update-in [:workspace-drawing :object] calculate-selrect))))) + +(defn add-node [{:keys [x y]}] + (ptk/reify ::add-node + ptk/UpdateEvent + (update [_ state] + (let [point {:x x :y y} + last-point (get-in state [:workspace-drawing :object :last-point]) + command (if last-point + {:command :line-to + :params point} + {:command :move-to + :params point})] + (-> state + (assoc-in [:workspace-drawing :object :last-point] point) + (update-in [:workspace-drawing :object :content] (fnil conj []) command)))))) + +(defn drag-handler [{:keys [x y]}] + (ptk/reify ::drag-handler + ptk/UpdateEvent + (update [_ state] + (-> state)))) + +(defn make-click-stream + [stream down-event] + (->> stream + (rx/filter ms/mouse-click?) + (rx/debounce 200) + (rx/first) + (rx/map #(add-node down-event)))) + +(defn make-drag-stream + [stream down-event] + (let [mouse-up (->> stream (rx/filter ms/mouse-up?)) + drag-events (->> ms/mouse-position + (rx/take-until mouse-up) + (rx/map #(drag-handler %)))] + (->> (rx/timer 400) + (rx/merge-map #(rx/concat + (add-node down-event) + drag-events))))) + +(defn make-dbl-click-stream + [stream down-event] + (->> stream + (rx/filter ms/mouse-double-click?) + (rx/first) + (rx/merge-map + #(rx/of (add-node down-event) + ::end-path-drawing)))) + +(defn handle-drawing-path [] (ptk/reify ::handle-drawing-path ptk/WatchEvent (watch [_ state stream] ;; clicks stream<[MouseEvent, Position]> - clicks (->> stream - (rx/filter ms/mouse-click?) - (rx/with-latest vector ms/mouse-position)) + (let [ + + mouse-down (->> stream (rx/filter ms/mouse-down?)) + finish-events (->> stream (rx/filter finish-event?)) + events (->> mouse-down + (rx/take-until finish-events) + (rx/throttle 100) + (rx/with-latest merge ms/mouse-position) + + ;; We change to the stream that emits the first event + (rx/switch-map + #(rx/race (make-click-stream stream %) + (make-drag-stream stream %) + (make-dbl-click-stream stream %))))] + + + (rx/concat + (rx/of (init-path)) + events + (rx/of (finish-path)) + (rx/of common/handle-finish-drawing))) ))) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 9fb6ef150c..9bcf04238b 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -251,7 +251,7 @@ (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes (d/ordered-set (:id group)))))))))) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) (defn rename-component [id new-name] @@ -407,7 +407,7 @@ new-shapes)] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dws/select-shapes (d/ordered-set (:id new-shape)))))))) + (dwc/select-shapes (d/ordered-set (:id new-shape)))))))) (defn detach-component "Remove all references to components in the shape with the given id, diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 56985d95c8..331efc6282 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -80,7 +80,8 @@ (defn start-resize [handler initial ids shape] (letfn [(resize [shape initial resizing-shapes [point lock? point-snap]] - (let [{:keys [width height rotation]} shape + (let [{:keys [width height]} (:selrect shape) + {:keys [rotation]} shape shapev (-> (gpt/point width height)) rotation (if (#{:curve :path} (:type shape)) 0 rotation) @@ -101,9 +102,11 @@ shape-transform (:transform shape (gmt/matrix)) shape-transform-inverse (:transform-inverse shape (gmt/matrix)) + shape-center (gsh/center-shape shape) + ;; Resize origin point given the selected handler - origin (-> (handler-resize-origin shape handler) - (gsh/transform-shape-point shape shape-transform))] + origin (-> (handler-resize-origin (:selrect shape) handler) + (gsh/transform-point-center shape-center shape-transform))] (rx/of (set-modifiers ids {:resize-vector scalev @@ -170,7 +173,7 @@ (watch [_ state stream] (let [stoper (rx/filter ms/mouse-up? stream) group (gsh/selection-rect shapes) - group-center (gsh/center group) + group-center (gsh/center-selrect group) initial-angle (gpt/angle @ms/mouse-position group-center) calculate-angle (fn [pos ctrl?] (let [angle (- (gpt/angle pos group-center) initial-angle) @@ -403,7 +406,7 @@ #(reduce update-shape % ids-with-children))))))) (defn rotation-modifiers [center shape angle] - (let [displacement (let [shape-center (gsh/center shape)] + (let [displacement (let [shape-center (gsh/center-shape shape)] (-> (gmt/matrix) (gmt/rotate angle center) (gmt/rotate (- angle) shape-center)))] @@ -416,7 +419,7 @@ (defn set-rotation ([delta-rotation shapes] - (set-rotation delta-rotation shapes (-> shapes gsh/selection-rect gsh/center))) + (set-rotation delta-rotation shapes (-> shapes gsh/selection-rect gsh/center-selrect))) ([delta-rotation shapes center] (letfn [(rotate-shape [objects angle shape center] diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 6629597a8b..74a543dad3 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -45,7 +45,7 @@ (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})] (->> (gsh/selection-rect shapes) (gal/adjust-to-viewport vport) - (gsh/fix-invalid-rect-values)))) + #_(gsh/fix-invalid-rect-values)))) (declare shape-wrapper-factory) diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 3843021794..463da699b4 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -166,7 +166,7 @@ (rx/merge-map (fn [[frame selrect]] (let [areas (->> (gsh/selrect->areas (or (:selrect frame) - (gsh/rect->rect-shape @refs/vbox)) selrect) + (gsh/rect->selrect @refs/vbox)) selrect) (d/mapm #(select-shapes-area page-id shapes objects %2))) snap-x (search-snap-distance selrect :x (:left areas) (:right areas)) snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas))] diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index 28936dd5f7..8860679b3b 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -41,11 +41,10 @@ (when *assert* (defonce debug-subscription - (as-> stream $ - #_(rx/filter ptk/event? $) - (rx/filter (fn [s] (debug? :events)) $) - (rx/subscribe $ (fn [event] - (println "[stream]: " (repr-event event))))))) + (->> stream + (rx/filter ptk/event?) + (rx/filter (fn [s] (debug? :events))) + (rx/subs #(println "[stream]: " (repr-event %)))))) (defn emit! ([] nil) ([event] @@ -73,6 +72,11 @@ (defn ^:export dump-state [] (logjs "state" @state)) +(defn ^:export get-state [str-path] + (let [path (->> (str/split str-path " ") + (map d/read-string))] + (clj->js (get-in @state path)))) + (defn ^:export dump-objects [] (let [page-id (get @state :current-page-id)] (logjs "state" (get-in @state [:workspace-data :pages-index page-id :objects])))) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index e509150dd4..d9705dd7bf 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -23,7 +23,8 @@ (let [shape (unchecked-get props "shape") base-props (unchecked-get props "base-props") elem-name (unchecked-get props "elem-name") - {:keys [x y width height]} (geom/shape->rect-shape shape) + ;; {:keys [x y width height]} (geom/shape->rect-shape shape) + {:keys [x y width height]} (:selrect shape) mask-id (mf/use-ctx mask-id-ctx) stroke-id (mf/use-var (uuid/next)) stroke-style (:stroke-style shape :none) diff --git a/frontend/src/app/main/ui/shapes/path.cljs b/frontend/src/app/main/ui/shapes/path.cljs index 677bc1649d..ff1a0bce38 100644 --- a/frontend/src/app/main/ui/shapes/path.cljs +++ b/frontend/src/app/main/ui/shapes/path.cljs @@ -15,10 +15,12 @@ [app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]] [app.main.ui.shapes.group :refer [mask-id-ctx]] [app.common.geom.shapes :as geom] - [app.util.object :as obj])) + [app.util.object :as obj] + [app.util.geom.path :as ugp])) ;; --- Path Shape +;; LEGACY FORMAT (defn- render-path [{:keys [segments close?] :as shape}] (let [numsegs (count segments)] @@ -45,10 +47,14 @@ [props] (let [shape (unchecked-get props "shape") background? (unchecked-get props "background?") - {:keys [id x y width height]} (geom/shape->rect-shape shape) + ;; {:keys [id x y width height]} (geom/shape->rect-shape shape) + {:keys [id x y width height]} (:selrect shape) mask-id (mf/use-ctx mask-id-ctx) transform (geom/transform-matrix shape) - pdata (render-path shape) + pdata (if (:content shape) + (ugp/content->path (:content shape)) + (render-path shape)) + props (-> (attrs/extract-style-attrs shape) (obj/merge! #js {:transform transform diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 4c149c3cbb..120bcd543d 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -181,7 +181,7 @@ on-rotate (obj/get props "on-rotate") current-transform (mf/deref refs/current-transform) - selrect (geom/shape->rect-shape shape) + selrect (:selrect shape) transform (geom/transform-matrix shape) tr-shape (geom/transform-shape shape)] @@ -269,8 +269,8 @@ (mf/defc multiple-selection-handlers [{:keys [shapes selected zoom color show-distances] :as props}] - (let [shape (geom/selection-rect shapes) - shape-center (geom/center shape) + (let [shape (geom/setup {:type :rect} (geom/selection-rect shapes)) + shape-center (geom/center-shape shape) hover-id (-> (mf/deref refs/current-hover) first) hover-id (when-not (d/seek #(= hover-id (:id %)) shapes) hover-id) diff --git a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs index b6b44c91f2..2a442bb258 100644 --- a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs @@ -42,7 +42,7 @@ (let [shape (unchecked-get props "shape") frame (unchecked-get props "frame") selrect (-> shape :selrect) - shape-center (geom/center shape) + shape-center (geom/center-shape shape) line-color (rdcolor #js {:seed (str (:id shape))}) zoom (mf/deref refs/selected-zoom)] [:g.bounding-box diff --git a/frontend/src/app/main/ui/workspace/snap_distances.cljs b/frontend/src/app/main/ui/workspace/snap_distances.cljs index a2559c01b7..442131450e 100644 --- a/frontend/src/app/main/ui/workspace/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/snap_distances.cljs @@ -141,8 +141,9 @@ (fn [[selrect selected frame]] (let [lt-side (if (= coord :x) :left :top) gt-side (if (= coord :x) :right :bottom) - areas (gsh/selrect->areas (or (:selrect frame) - (gsh/rect->rect-shape @refs/vbox)) selrect) + container-selrec (or (:selrect frame) + (gsh/rect->selrect @refs/vbox)) + areas (gsh/selrect->areas container-selrec selrect) query-side (fn [side] (->> (uw/ask! {:cmd :selection/query :page-id page-id diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 402399bd68..80619fa284 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -232,8 +232,9 @@ (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) (cond (and (= 1 (.-which event))) + (if drawing-tool - (when (not= drawing-tool :comments) + (when (not (#{:comments :path} drawing-tool)) (st/emit! (dd/start-drawing drawing-tool))) (st/emit! dw/handle-selection)) diff --git a/frontend/src/app/main/worker.cljs b/frontend/src/app/main/worker.cljs index 63e4908349..b0569216aa 100644 --- a/frontend/src/app/main/worker.cljs +++ b/frontend/src/app/main/worker.cljs @@ -15,8 +15,8 @@ [app.util.worker :as uw])) (defn on-error - [instance error] - (js/console.error "Error on worker" (.-data error))) + [error] + (js/console.error "Error on worker" error)) (defonce instance (when (not= *target* "nodejs") diff --git a/frontend/src/app/util/geom/snap_points.cljs b/frontend/src/app/util/geom/snap_points.cljs index 8859a96c68..ee3a5f695c 100644 --- a/frontend/src/app/util/geom/snap_points.cljs +++ b/frontend/src/app/util/geom/snap_points.cljs @@ -27,9 +27,9 @@ (defn shape-snap-points [shape] (let [shape (gsh/transform-shape shape) - shape-center (gsh/center shape)] + shape-center (gsh/center-shape shape)] (if (= :frame (:type shape)) (-> shape - (gsh/shape->rect-shape) + :selrect (frame-snap-points)) (into #{shape-center} (:points shape))))) diff --git a/frontend/src/app/util/worker.cljs b/frontend/src/app/util/worker.cljs index 3458d18982..e3f9440113 100644 --- a/frontend/src/app/util/worker.cljs +++ b/frontend/src/app/util/worker.cljs @@ -38,10 +38,12 @@ (fn [event] (let [data (.-data event) data (t/decode data)] - (rx/push! bus data)))) + (if (:error data) + (on-error (:error data)) + (rx/push! bus data))))) (.addEventListener ins "error" (fn [error] - (on-error wrk error))) + (on-error wrk (.-data error)))) wrk)) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index 2ff9b8ce5e..c41de8a86a 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -65,8 +65,7 @@ (defn- create-index [objects] - (let [shapes (->> (cph/select-toplevel-shapes objects {:include-frames? true}) - (map #(merge % (select-keys % [:x :y :width :height])))) + (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true}) bounds (geom/selection-rect shapes) bounds #js {:x (:x bounds) :y (:y bounds) @@ -77,7 +76,8 @@ shapes))) (defn- index-object - [index {:keys [id x y width height] :as obj}] - (let [rect #js {:x x :y y :width width :height height}] + [index obj] + (let [{:keys [id x y width height]} (:selrect obj) + rect #js {:x x :y y :width width :height height}] (qdt/insert index rect obj))) From f3cce1904c41250f53a611f7c08593f14f30bc85 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 12 Nov 2020 10:42:09 +0100 Subject: [PATCH 049/195] :sparkles: First version drawing beziers --- common/app/common/geom/shapes/common.cljc | 8 +- common/app/common/geom/shapes/transforms.cljc | 3 +- common/app/common/math.cljc | 2 +- .../app/main/data/workspace/drawing/path.cljs | 133 ++++++++++++++---- .../src/app/main/ui/workspace/drawarea.cljs | 38 ++--- .../app/main/ui/workspace/shapes/path.cljs | 93 +++++++++++- frontend/src/app/util/geom/path.cljs | 34 ++++- 7 files changed, 255 insertions(+), 56 deletions(-) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index f69a7d3ea6..d4b64b481a 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -19,8 +19,12 @@ (defn center-rect [{:keys [x y width height]}] - (gpt/point (+ x (/ width 2)) - (+ y (/ height 2)))) + (when (and (mth/finite? x) + (mth/finite? y) + (mth/finite? width) + (mth/finite? height)) + (gpt/point (+ x (/ width 2)) + (+ y (/ height 2))))) (defn center-selrect "Calculate the center of the shape." diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 94771bbf7f..3253e02533 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -23,7 +23,8 @@ "Returns a transformation matrix without changing the shape properties. The result should be used in a `transform` attribute in svg" ([{:keys [x y] :as shape}] - (let [shape-center (gco/center-shape shape)] + (let [shape-center (or (gco/center-shape shape) + (gpt/point 0 0))] (-> (gmt/matrix) (gmt/translate shape-center) (gmt/multiply (:transform shape (gmt/matrix))) diff --git a/common/app/common/math.cljc b/common/app/common/math.cljc index 9125c7c351..92ba19a1a2 100644 --- a/common/app/common/math.cljc +++ b/common/app/common/math.cljc @@ -23,7 +23,7 @@ (defn finite? [v] - #?(:cljs (js/isFinite v) + #?(:cljs (and (not (nil? v)) (js/isFinite v)) :clj (Double/isFinite v))) (defn abs diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index e9b7382b41..c30441f725 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -14,15 +14,12 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.main.streams :as ms] - [app.util.geom.path :as path] + [app.util.geom.path :as ugp] [app.main.data.workspace.drawing.common :as common])) (defn finish-event? [{:keys [type shift] :as event}] (or (= event ::end-path-drawing) (= event :interrupt) - #_(and (ms/mouse-event? event) - (or (= type :double-click) - (= type :context-menu))) (and (ms/keyboard-event? event) (= type :down) (= 13 (:key event))))) @@ -78,26 +75,105 @@ (assoc-in [:workspace-drawing :object :last-point] nil) (update-in [:workspace-drawing :object] calculate-selrect))))) +(defn preview-next-point [{:keys [x y]}] + (ptk/reify ::add-node + ptk/UpdateEvent + (update [_ state] + (let [point {:x x :y y} + {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object]) + + command (cond + (and last-point (not prev-handler)) + {:command :line-to + :params point} + + (and last-point prev-handler) + {:command :curve-to + :params (ugp/make-curve-params point prev-handler)} + + :else + nil) + ] + (-> state + (assoc-in [:workspace-drawing :object :preview] command)))))) + (defn add-node [{:keys [x y]}] (ptk/reify ::add-node ptk/UpdateEvent (update [_ state] (let [point {:x x :y y} - last-point (get-in state [:workspace-drawing :object :last-point]) - command (if last-point + {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object]) + + command (cond + (and last-point (not prev-handler)) {:command :line-to :params point} + + (and last-point prev-handler) + {:command :curve-to + :params (ugp/make-curve-params point prev-handler)} + + :else {:command :move-to - :params point})] + :params point}) + ] (-> state - (assoc-in [:workspace-drawing :object :last-point] point) - (update-in [:workspace-drawing :object :content] (fnil conj []) command)))))) + (assoc-in [:workspace-drawing :object :last-point] point) + (update-in [:workspace-drawing :object] dissoc :prev-handler) + (update-in [:workspace-drawing :object :content] (fnil conj []) command) + (update-in [:workspace-drawing :object] calculate-selrect)))))) (defn drag-handler [{:keys [x y]}] (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] - (-> state)))) + (let [change-handler (fn [content] + (let [last-idx (dec (count content)) + last (get content last-idx nil) + prev (get content (dec last-idx) nil) + {last-x :x last-y :y} (:params last) + opposite (when last (ugp/opposite-handler (gpt/point last-x last-y) (gpt/point x y)))] + + (cond + (and prev (= (:command last) :line-to)) + (-> content + (assoc last-idx {:command :curve-to + :params {:x (-> last :params :x) + :y (-> last :params :y) + :c1x (-> prev :params :x) + :c1y (-> prev :params :y) + :c2x (-> last :params :x) + :c2y (-> last :params :y)}}) + (update-in + [last-idx :params] + #(-> % + (assoc :c2x (:x opposite) + :c2y (:y opposite))))) + + (= (:command last) :curve-to) + (update-in content + [last-idx :params] + #(-> % + (assoc :c2x (:x opposite) + :c2y (:y opposite)))) + :else + content)) + + + ) + handler (gpt/point x y)] + (-> state + (update-in [:workspace-drawing :object :content] change-handler) + (assoc-in [:workspace-drawing :object :drag-handler] handler)))))) + +(defn finish-drag [] + (ptk/reify ::finish-drag + ptk/UpdateEvent + (update [_ state] + (let [handler (get-in state [:workspace-drawing :object :drag-handler])] + (-> state + (update-in [:workspace-drawing :object] dissoc :drag-handler) + (assoc-in [:workspace-drawing :object :prev-handler] handler)))))) (defn make-click-stream [stream down-event] @@ -115,8 +191,9 @@ (rx/map #(drag-handler %)))] (->> (rx/timer 400) (rx/merge-map #(rx/concat - (add-node down-event) - drag-events))))) + (rx/of (add-node down-event)) + drag-events + (rx/of (finish-drag))))))) (defn make-dbl-click-stream [stream down-event] @@ -133,26 +210,32 @@ (watch [_ state stream] ;; clicks stream<[MouseEvent, Position]> - (let [ - - mouse-down (->> stream (rx/filter ms/mouse-down?)) + (let [mouse-down (->> stream (rx/filter ms/mouse-down?)) finish-events (->> stream (rx/filter finish-event?)) - events (->> mouse-down - (rx/take-until finish-events) - (rx/throttle 100) - (rx/with-latest merge ms/mouse-position) + mousemove-events + (->> ms/mouse-position + (rx/take-until finish-events) + (rx/throttle 100) + (rx/map #(preview-next-point %))) - ;; We change to the stream that emits the first event - (rx/switch-map - #(rx/race (make-click-stream stream %) - (make-drag-stream stream %) - (make-dbl-click-stream stream %))))] + mousedown-events + (->> mouse-down + (rx/take-until finish-events) + (rx/throttle 100) + (rx/with-latest merge ms/mouse-position) + + ;; We change to the stream that emits the first event + (rx/switch-map + #(rx/race (make-click-stream stream %) + (make-drag-stream stream %) + (make-dbl-click-stream stream %))))] (rx/concat (rx/of (init-path)) - events + (rx/merge mousemove-events + mousedown-events) (rx/of (finish-path)) (rx/of common/handle-finish-drawing))) diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index ae3f9cbb61..0ce96a02ca 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -12,6 +12,7 @@ [app.main.data.workspace.drawing :as dd] [app.main.store :as st] [app.main.ui.workspace.shapes :as shapes] + [app.main.ui.workspace.shapes.path :refer [path-editor]] [app.common.geom.shapes :as gsh] [app.common.data :as d] [app.util.dom :as dom] @@ -22,10 +23,13 @@ (mf/defc draw-area [{:keys [shape zoom] :as props}] - (when (:id shape) - (case (:type shape) - (:path :curve) [:& path-draw-area {:shape shape}] - [:& generic-draw-area {:shape shape :zoom zoom}]))) + + [:g.draw-area + [:& shapes/shape-wrapper {:shape shape}] + + (case (:type shape) + :path [:& path-editor {:shape shape :zoom zoom}] + #_:default [:& generic-draw-area {:shape shape :zoom zoom}])]) (mf/defc generic-draw-area [{:keys [shape zoom]}] @@ -34,19 +38,16 @@ (not (d/nan? x)) (not (d/nan? y))) - [:g - [:& shapes/shape-wrapper {:shape shape}] - [:rect.main {:x x :y y - :width width - :height height - :style {:stroke "#1FDEA7" - :fill "transparent" - :stroke-width (/ 1 zoom)}}]]))) + [:rect.main {:x x :y y + :width width + :height height + :style {:stroke "#1FDEA7" + :fill "transparent" + :stroke-width (/ 1 zoom)}}]))) -(mf/defc path-draw-area +#_(mf/defc path-draw-area [{:keys [shape] :as props}] (let [locale (i18n/use-locale) - on-click (fn [event] (dom/stop-propagation event) @@ -62,14 +63,13 @@ (fn [event] (st/emit! (dw/assign-cursor-tooltip nil)))] - (when-let [{:keys [x y] :as segment} (first (:segments shape))] - [:g - [:& shapes/shape-wrapper {:shape shape}] - (when (not= :curve (:type shape)) + [:g.drawing + [:& shapes/shape-wrapper {:shape shape}] + #_(when (not= :curve (:type shape)) [:circle.close-bezier {:cx x :cy y :r 5 :on-click on-click :on-mouse-enter on-mouse-enter - :on-mouse-leave on-mouse-leave}])]))) + :on-mouse-leave on-mouse-leave}])])) diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 66faed116d..543d6ae44b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -23,7 +23,8 @@ [app.main.ui.shapes.path :as path] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] - [app.main.ui.workspace.shapes.common :as common])) + [app.main.ui.workspace.shapes.common :as common] + [app.util.geom.path :as ugp])) (mf/defc path-wrapper {::mf/wrap-props false} @@ -56,3 +57,93 @@ [:& path/path-shape {:shape shape :background? true}]])) + +(mf/defc path-handler [{:keys [point handler zoom selected]}] + (when (and point handler) + (let [{:keys [x y]} handler] + [:g.handler + [:line + {:x1 (:x point) + :y1 (:y point) + :x2 x + :y2 y + :style {:stroke "#B1B2B5" + :stroke-width (/ 1 zoom)}}] + [:rect + {:x (- x (/ 3 zoom)) + :y (- y (/ 3 zoom)) + :width (/ 6 zoom) + :height (/ 6 zoom) + :style {:stroke-width (/ 1 zoom) + :stroke (if selected "#000000" "#1FDEA7") + :fill (if selected "#1FDEA7" "#FFFFFF")}}]]))) + +(mf/defc path-editor + [{:keys [shape zoom]}] + + (let [points (:points shape) + drag-handler (:drag-handler shape) + prev-handler (:prev-handler shape) + last-command (last (:content shape)) + selected false + last-p (last points) + handlers (ugp/extract-handlers (:content shape)) + handlers (if (and prev-handler (not drag-handler)) + (conj handlers {:point last-p :prev prev-handler}) + handlers) + ] + + [:g.path-editor + (when (and (:preview shape) (not (:drag-handler shape))) + [:* + [:path {:style {:fill "transparent" + :stroke "#DB00FF" + :stroke-width (/ 1 zoom)} + :d (ugp/content->path [{:command :move-to + :params {:x (:x last-p) + :y (:y last-p)}} + (:preview shape)])}] + [:circle + {:cx (-> shape :preview :params :x) + :cy (-> shape :preview :params :y) + :r (/ 3 zoom) + :style {:stroke-width (/ 1 zoom) + :stroke "#DB00FF" + :fill "#FFFFFF"}}]]) + + (for [{:keys [point prev next]} handlers] + [:* + [:& path-handler {:point point + :handler prev + :zoom zoom + :type :prev + :selected false}] + [:& path-handler {:point point + :handler next + :zoom zoom + :type :next + :selected false}]]) + + (when drag-handler + [:* + (when (not= :move-to (:command last-command)) + [:& path-handler {:point last-p + :handler (ugp/opposite-handler last-p drag-handler) + :zoom zoom + :type :drag-opposite + :selected false}]) + [:& path-handler {:point last-p + :handler drag-handler + :zoom zoom + :type :drag + :selected false}]]) + + (for [{:keys [x y] :as point} points] + [:circle + {:cx x + :cy y + :r (/ 3 zoom) + :style {:stroke-width (/ 1 zoom) + :stroke (if selected "#000000" "#1FDEA7") + :fill (if selected "#1FDEA7" "#FFFFFF")} + }])])) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index c50a7ec78b..1da9ce3a0e 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -11,6 +11,7 @@ (:require [cuerdas.core :as str] [app.common.data :as d] + [app.common.geom.point :as gpt] [app.util.geom.path-impl-simplify :as impl-simplify])) (defn simplify @@ -192,10 +193,29 @@ (map command->string) (str/join ""))) -#_(let [path "M.343 15.974a.514.514 0 01-.317-.321c-.023-.07-.026-.23-.026-1.43 0-1.468-.001-1.445.09-1.586.02-.032 1.703-1.724 3.74-3.759a596.805 596.805 0 003.7-3.716c0-.009-.367-.384-.816-.833a29.9 29.9 0 01-.817-.833c0-.01.474-.49 1.054-1.07l1.053-1.053.948.946.947.947 1.417-1.413C12.366.806 12.765.418 12.856.357c.238-.161.52-.28.792-.334.17-.034.586-.03.76.008.801.173 1.41.794 1.57 1.603.03.15.03.569 0 .718a2.227 2.227 0 01-.334.793c-.061.09-.45.49-1.496 1.54L12.734 6.1l.947.948.947.947-1.053 1.054c-.58.58-1.061 1.054-1.07 1.054-.01 0-.384-.368-.833-.817-.45-.45-.824-.817-.834-.817-.009 0-1.68 1.666-3.716 3.701a493.093 493.093 0 01-3.759 3.74c-.14.091-.117.09-1.59.089-1.187 0-1.366-.004-1.43-.027zm6.024-4.633a592.723 592.723 0 003.663-3.68c0-.02-1.67-1.69-1.69-1.69-.01 0-1.666 1.648-3.68 3.663L.996 13.297v.834c0 .627.005.839.02.854.015.014.227.02.854.02h.833l3.664-3.664z" - content (path->content path) - new-path (content->path content) - ] - (prn "path" path) - (.log js/console "?? 1" (clj->js content)) - (prn "?? 2" (= path new-path) new-path)) +(defn make-curve-params + ([point] + (make-curve-params point point point)) + + ([point handler] (make-curve-params point handler point)) + + ([point h1 h2] + {:x (:x point) + :y (:y point) + :c1x (:x h1) + :c1y (:y h1) + :c2x (:x h2) + :c2y (:y h2)})) + +(defn opposite-handler + [point handler] + (let [phv (gpt/to-vec point handler) + opposite (gpt/add point (gpt/negate phv))] + opposite)) + +(defn extract-handlers [content] + (let [extract (fn [{param1 :params :as cmd1} {param2 :params :as cmd2}] + {:point (gpt/point (:x param1) (:y param1)) + :prev (when (:c2x param1) (gpt/point (:c2x param1) (:c2y param1))) + :next (when (:c1x param2) (gpt/point (:c1x param2) (:c1y param2)))})] + (map extract content (d/concat [] (rest content) [nil])))) From d8ab3473bf1d495667d435bf4e60ebcf4ef5832e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 12 Nov 2020 19:50:04 +0100 Subject: [PATCH 050/195] :sparkles: Calculate selrect for bezier curves --- common/app/common/geom/point.cljc | 5 +- common/app/common/geom/shapes.cljc | 5 + common/app/common/geom/shapes/common.cljc | 1 - common/app/common/geom/shapes/path.cljc | 123 +++++++++++++++++- common/app/common/geom/shapes/rect.cljc | 1 - common/app/common/geom/shapes/transforms.cljc | 113 ++++++++-------- common/app/common/math.cljc | 3 + .../app/main/data/workspace/drawing/path.cljs | 11 +- .../app/main/ui/workspace/shapes/path.cljs | 4 +- .../src/app/main/ui/workspace/viewport.cljs | 25 ++-- 10 files changed, 212 insertions(+), 79 deletions(-) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index 65b453b561..32112f9e15 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -39,7 +39,10 @@ :else (throw (ex-info "Invalid arguments" {:v v})))) - ([x y] (Point. x y))) + ([x y] + ;;(assert (not (nil? x))) + ;;(assert (not (nil? y))) + (Point. x y))) (defn add "Returns the addition of the supplied value to both diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 8cf6073156..b45b7beed5 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -16,6 +16,7 @@ [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.transforms :as gtr] [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.path :as gsp] [app.common.math :as mth] [app.common.data :as d])) @@ -299,3 +300,7 @@ (defn transform-matrix [shape] (gtr/transform-matrix shape)) (defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) (defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) + +;; PATHS +(defn content->points [content] (gsp/content->points content)) +(defn content->selrect [content] (gsp/content->selrect content)) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index d4b64b481a..1642663729 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -13,7 +13,6 @@ [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes.path :as gpa] [app.common.math :as mth] [app.common.data :as d])) diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index 10b6fa0e44..ab77dfda60 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -13,6 +13,7 @@ [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] + [app.common.geom.shapes.rect :as gpr] [app.common.math :as mth] [app.common.data :as d])) @@ -20,4 +21,124 @@ segments) (defn content->points [content] - (map #(gpt/point (-> % :param :x) (-> % :param :y)) content)) + (mapv #(gpt/point (-> % :params :x) (-> % :params :y)) content)) + +;; https://medium.com/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf +;; https://en.wikipedia.org/wiki/Bernstein_polynomial +(defn curve-values + "Parametric equation for cubic beziers. Given a start and end and + two intermediate points returns points for values of t. + If you draw t on a plane you got the bezier cube" + [start end h1 h2 t] + + (let [t2 (* t t) ;; t square + t3 (* t2 t) ;; t cube + + start-v (+ (- t3) (* 3 t2) (* -3 t) 1) + h1-v (+ (* 3 t3) (* -6 t2) (* 3 t)) + h2-v (+ (* -3 t3) (* 3 t2)) + end-v t3 + + coord-v (fn [coord] + (+ (* (coord start) start-v) + (* (coord h1) h1-v) + (* (coord h2) h2-v) + (* (coord end) end-v)))] + + (gpt/point (coord-v :x) (coord-v :y)))) + +;; https://pomax.github.io/bezierinfo/#extremities +(defn curve-extremities + "Given a cubic bezier cube finds its roots in t. This are the extremities + if we calculate its values for x, y we can find a bounding box for the curve." + [start end h1 h2] + + (let [coords [[(:x start) (:x h1) (:x h2) (:x end)] + [(:y start) (:y h1) (:y h2) (:y end)]] + + coord->tvalue + (fn [[c0 c1 c2 c3]] + + (let [a (+ (* -3 c0) (* 9 c1) (* -9 c2) (* 3 c3)) + b (+ (* 6 c0) (* -12 c1) (* 6 c2)) + c (+ (* 3 c1) (* -3 c0)) + + sqrt-b2-4ac (mth/sqrt (- (* b b) (* 4 a c)))] + + (cond + (and (mth/almost-zero? a) + (not (mth/almost-zero? b))) + ;; When the term a is close to zero we have a linear equation + [(/ (- c) b)] + + ;; If a is not close to zero return the two roots for a cuadratic + (not (mth/almost-zero? a)) + [(/ (+ (- b) sqrt-b2-4ac) + (* 2 a)) + (/ (- (- b) sqrt-b2-4ac) + (* 2 a))] + + ;; If a and b close to zero we can't find a root for a constant term + :else + [])))] + (->> coords + (mapcat coord->tvalue) + + ;; Only values in the range [0, 1] are valid + (filter #(and (>= % 0) (<= % 1))) + + ;; Pass t-values to actual points + (map #(curve-values start end h1 h2 %))) + )) + +(defn command->point + ([command] (command->point command nil)) + ([{params :params} coord] + (let [prefix (if coord (name coord) "") + xkey (keyword (str prefix "x")) + ykey (keyword (str prefix "y")) + x (get params xkey) + y (get params ykey)] + (gpt/point x y)))) + +(defn content->selrect [content] + (let [calc-extremities + (fn [command prev] + (case (:command command) + :move-to [(command->point command)] + + ;; If it's a line we add the beginning point and endpoint + :line-to [(command->point prev) + (command->point command)] + + ;; We return the bezier extremities + :curve-to (d/concat + [(command->point prev) + (command->point command)] + (curve-extremities (command->point prev) + (command->point command) + (command->point command :c1) + (command->point command :c2))))) + + extremities (mapcat calc-extremities + content + (d/concat [nil] content))] + + (gpr/points->selrect extremities))) + +(defn transform-content [content transform] + (let [set-tr (fn [params px py] + (let [tr-point (-> (gpt/point (get params px) (get params py)) + (gpt/transform transform))] + (assoc params + px (:x tr-point) + py (:y tr-point)))) + + transform-params + (fn [{:keys [x y c1x c1y c2x c2y] :as params}] + (cond-> params + (not (nil? x)) (set-tr :x :y) + (not (nil? c1x)) (set-tr :c1x :c1y) + (not (nil? c2x)) (set-tr :c2x :c2y)))] + + (mapv #(update % :params transform-params) content))) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index e5204a5e9c..89da516a6e 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -13,7 +13,6 @@ [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes.path :as gpa] [app.common.geom.shapes.common :as gco] [app.common.math :as mth] [app.common.data :as d])) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 3253e02533..cd819cca5c 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -89,39 +89,43 @@ :else scale)) -(defn modifiers->transform [current-transform center modifiers] - (let [ds-modifier (:displacement modifiers (gmt/matrix)) - {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) +(defn modifiers->transform + ([center modifiers] + (modifiers->transform (gmt/matrix) center modifiers)) - ;; Normalize x/y vector coordinates because scale by 0 is infinite - res-x (normalize-scale res-x) - res-y (normalize-scale res-y) - resize (gpt/point res-x res-y) + ([current-transform center modifiers] + (let [ds-modifier (:displacement modifiers (gmt/matrix)) + {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) - origin (:resize-origin modifiers (gpt/point 0 0)) + ;; Normalize x/y vector coordinates because scale by 0 is infinite + res-x (normalize-scale res-x) + res-y (normalize-scale res-y) + resize (gpt/point res-x res-y) - resize-transform (:resize-transform modifiers (gmt/matrix)) - resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) - rt-modif (or (:rotation modifiers) 0) + origin (:resize-origin modifiers (gpt/point 0 0)) - transform (-> (gmt/matrix) + resize-transform (:resize-transform modifiers (gmt/matrix)) + resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) + rt-modif (or (:rotation modifiers) 0) - ;; Applies the current resize transformation - (gmt/translate origin) - (gmt/multiply resize-transform) - (gmt/scale resize) - (gmt/multiply resize-transform-inverse) - (gmt/translate (gpt/negate origin)) + transform (-> (gmt/matrix) - ;; Applies the stacked transformations - (gmt/translate center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - #_(gmt/multiply current-transform) - (gmt/translate (gpt/negate center)) + ;; Applies the current resize transformation + (gmt/translate origin) + (gmt/multiply resize-transform) + (gmt/scale resize) + (gmt/multiply resize-transform-inverse) + (gmt/translate (gpt/negate origin)) - ;; Displacement - (gmt/multiply ds-modifier))] - transform)) + ;; Applies the stacked transformations + (gmt/translate center) + (gmt/multiply (gmt/rotate-matrix rt-modif)) + #_(gmt/multiply current-transform) + (gmt/translate (gpt/negate center)) + + ;; Displacement + (gmt/multiply ds-modifier))] + transform))) (defn- calculate-skew-angle "Calculates the skew angle of the paralelogram given by the points" @@ -210,28 +214,31 @@ [stretch-matrix stretch-matrix-inverse])) -(defn set-points-path - [shape points] - (let [shape (reduce (fn [acc [idx {:keys [x y]}]] - (-> acc - (assoc-in [:content idx :params :x] x) - (assoc-in [:content idx :params :y] y))) shape (d/enumerate points)) +(defn apply-transform-path + [shape transform] + (let [content (gpa/transform-content (:content shape) transform) + points (gpa/content->points content) + rotation (mod (+ (:rotation shape 0) + (or (get-in shape [:modifiers :rotation]) 0)) + 360) + selrect (gpa/content->selrect content)] + (assoc shape + :content content + :points points + :selrect selrect + :rotation rotation))) - shape (assoc shape - :points points - :selrect (gpr/points->selrect points))] - shape)) - -(defn set-points-curve - [shape points] +(defn apply-transform-curve + [shape transform] shape) -(defn set-points-rect +(defn apply-transform-rect "Given a new set of points transformed, set up the rectangle so it keeps its properties. We adjust de x,y,width,height and create a custom transform" - [shape points] + [shape transform] ;; - (let [center (gco/center-points points) + (let [points (-> shape :points (transform-points transform)) + center (gco/center-points points) ;; Reverse the current transformation stack to get the base rectangle tr-inverse (:transform-inverse shape (gmt/matrix)) @@ -259,18 +266,18 @@ (update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix)) (update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix)))) (assoc $ :points (into [] points)) - (assoc $ :selrect (gpr/rect->selrect rect-shape) #_(gpr/points->selrect points)) + (assoc $ :selrect (gpr/rect->selrect rect-shape)) (update $ :rotation #(mod (+ (or % 0) (or (get-in $ [:modifiers :rotation]) 0)) 360)))] new-shape)) -(defn set-points [shape points] - (let [set-points-fn +(defn apply-transform [shape transform] + (let [apply-transform-fn (case (:type shape) - :path set-points-path - :curve set-points-curve - set-points-rect)] - (set-points-fn shape points))) + :path apply-transform-path + :curve apply-transform-curve + apply-transform-rect)] + (apply-transform-fn shape transform))) (defn set-flip [shape modifiers] (cond-> shape @@ -279,13 +286,11 @@ (defn transform-shape [shape] (if (:modifiers shape) - (let [points (:points shape (shape->points shape)) - center (gco/center-points points) - transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape)) - tr-points (transform-points points transform)] + (let [center (gco/center-shape shape) + transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape))] (-> shape (set-flip (:modifiers shape)) - (set-points tr-points) + (apply-transform transform) (dissoc :modifiers))) shape)) diff --git a/common/app/common/math.cljc b/common/app/common/math.cljc index 92ba19a1a2..f9baa33870 100644 --- a/common/app/common/math.cljc +++ b/common/app/common/math.cljc @@ -135,3 +135,6 @@ (if (< num from) from (if (> num to) to num))) + +(defn almost-zero? [num] + (< (abs num) 1e-8)) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index c30441f725..0fb022ba50 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -50,14 +50,9 @@ (defn calculate-selrect [shape] - (let [points (->> shape - :content - (mapv #(gpt/point - (-> % :params :x) - (-> % :params :y))))] - (assoc shape - :points points - :selrect (gsh/points->selrect points)))) + (assoc shape + :points (gsh/content->points (:content shape)) + :selrect (gsh/content->selrect (:content shape)))) (defn init-path [] (ptk/reify ::init-path diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 543d6ae44b..b844ffbdb9 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -24,7 +24,8 @@ [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.shapes.common :as common] - [app.util.geom.path :as ugp])) + [app.util.geom.path :as ugp] + [app.common.geom.shapes.path :as gsp])) (mf/defc path-wrapper {::mf/wrap-props false} @@ -53,7 +54,6 @@ :on-double-click on-double-click :on-mouse-down on-mouse-down :on-context-menu on-context-menu} - [:& path/path-shape {:shape shape :background? true}]])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 80619fa284..a2e7461ac3 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -204,11 +204,14 @@ picking-color?]} local page-id (mf/use-ctx ctx/current-page-id) - selrect-orig (->> (mf/deref refs/selected-objects) - (gsh/selection-rect)) - selrect (-> selrect-orig - (assoc :modifiers (:modifiers local)) - (gsh/transform-shape)) + + selected-objects (mf/deref refs/selected-objects) + selrect-orig (->> selected-objects + (gsh/selection-rect)) + selrect (->> selected-objects + (map #(assoc % :modifiers (:modifiers local))) + (map gsh/transform-shape) + (gsh/selection-rect)) alt? (mf/use-state false) viewport-ref (mf/use-ref nil) @@ -266,18 +269,18 @@ on-pointer-down (mf/use-callback - (fn [event] + (fn [event] (let [target (dom/get-target event)] - ; Capture mouse pointer to detect the movements even if cursor - ; leaves the viewport or the browser itself - ; https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture + ; Capture mouse pointer to detect the movements even if cursor + ; leaves the viewport or the browser itself + ; https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture (.setPointerCapture target (.-pointerId event))))) on-pointer-up (mf/use-callback - (fn [event] + (fn [event] (let [target (dom/get-target event)] - ; Release pointer on mouse up + ; Release pointer on mouse up (.releasePointerCapture target (.-pointerId event))))) on-click From 05366eac6f1573879f28e54578b20fbcd7118ccb Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 13 Nov 2020 11:37:40 +0100 Subject: [PATCH 051/195] :sparkles: Snap for beziers --- common/app/common/geom/shapes.cljc | 5 ++-- common/app/common/geom/shapes/rect.cljc | 14 +++++++++ common/app/common/geom/shapes/transforms.cljc | 16 +++++----- frontend/src/app/main/snap.cljs | 2 +- .../app/main/ui/workspace/shapes/path.cljs | 2 +- .../app/main/ui/workspace/snap_points.cljs | 2 +- frontend/src/app/util/geom/snap_points.cljs | 29 ++++++++++--------- 7 files changed, 44 insertions(+), 26 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index b45b7beed5..cfe5314022 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -156,8 +156,9 @@ "Returns a rect that contains all the shapes and is aware of the rotation of each shape. Mainly used for multiple selection." [shapes] - (let [points (->> shapes (mapcat :points))] - (gpr/points->selrect points))) + (->> shapes + (map :selrect) + (gpr/join-selrects))) (defn translate-to-frame [shape {:keys [x y] :as frame}] diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index 89da516a6e..47f6543dc9 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -44,6 +44,20 @@ (defn rect->selrect [rect] (-> rect rect->points points->selrect)) +(defn join-selrects [selrects] + (let [minx (transduce (map :x1) min ##Inf selrects) + miny (transduce (map :y1) min ##Inf selrects) + maxx (transduce (map :x2) max ##-Inf selrects) + maxy (transduce (map :y2) max ##-Inf selrects)] + {:x minx + :y miny + :x1 minx + :y1 miny + :x2 maxx + :y2 maxy + :width (- maxx minx) + :height (- maxy miny)})) + ;; --- SHAPE -> RECT #_( (defn- rect->rect-shape diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index cd819cca5c..1b79e9b02a 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -285,14 +285,14 @@ (< (get-in modifiers [:resize-vector :y]) 0) (update :flip-y not))) (defn transform-shape [shape] - (if (:modifiers shape) - (let [center (gco/center-shape shape) - transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape))] - (-> shape - (set-flip (:modifiers shape)) - (apply-transform transform) - (dissoc :modifiers))) - shape)) + (let [center (gco/center-shape shape)] + (if (and (:modifiers shape) center) + (let [transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape))] + (-> shape + (set-flip (:modifiers shape)) + (apply-transform transform) + (dissoc :modifiers))) + shape))) #_(defn transform-shape "Transform the shape properties given the modifiers" diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 463da699b4..e20db5f631 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -195,7 +195,7 @@ (or (filter-shapes id) (not (contains? layout :dynamic-alignment))))) shape (if (> (count shapes) 1) - (->> shapes (map gsh/transform-shape) gsh/selection-rect) + (->> shapes (map gsh/transform-shape) gsh/selection-rect (gsh/setup {:type :rect})) (->> shapes (first))) shapes-points (->> shape diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index b844ffbdb9..d1f761ab59 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -81,7 +81,7 @@ (mf/defc path-editor [{:keys [shape zoom]}] - (let [points (:points shape) + (let [points (gsp/content->points (:content shape)) drag-handler (:drag-handler shape) prev-handler (:prev-handler shape) last-command (last (:content shape)) diff --git a/frontend/src/app/main/ui/workspace/snap_points.cljs b/frontend/src/app/main/ui/workspace/snap_points.cljs index 480d1d57ce..1a24da9321 100644 --- a/frontend/src/app/main/ui/workspace/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/snap_points.cljs @@ -58,7 +58,7 @@ (defn get-snap [coord {:keys [shapes page-id filter-shapes local]}] (let [shape (if (> (count shapes) 1) - (->> shapes (map gsh/transform-shape) gsh/selection-rect) + (->> shapes (map gsh/transform-shape) gsh/selection-rect (gsh/setup {:type :rect})) (->> shapes (first))) shape (if (:modifiers local) diff --git a/frontend/src/app/util/geom/snap_points.cljs b/frontend/src/app/util/geom/snap_points.cljs index ee3a5f695c..d6ad0bdaac 100644 --- a/frontend/src/app/util/geom/snap_points.cljs +++ b/frontend/src/app/util/geom/snap_points.cljs @@ -14,22 +14,25 @@ [app.common.geom.shapes :as gsh] [app.common.geom.point :as gpt])) -(defn- frame-snap-points [{:keys [x y width height] :as frame}] - (into #{(gpt/point x y) - (gpt/point (+ x (/ width 2)) y) - (gpt/point (+ x width) y) +(defn- selrect-snap-points [{:keys [x y width height]}] + #{(gpt/point x y) + (gpt/point (+ x width) y) + (gpt/point (+ x width) (+ y height)) + (gpt/point x (+ y height))}) + +(defn- frame-snap-points [{:keys [x y width height] :as selrect}] + (into (selrect-snap-points selrect) + #{(gpt/point (+ x (/ width 2)) y) (gpt/point (+ x width) (+ y (/ height 2))) - (gpt/point (+ x width) (+ y height)) (gpt/point (+ x (/ width 2)) (+ y height)) - (gpt/point x (+ y height)) (gpt/point x (+ y (/ height 2)))})) (defn shape-snap-points [shape] - (let [shape (gsh/transform-shape shape) - shape-center (gsh/center-shape shape)] - (if (= :frame (:type shape)) - (-> shape - :selrect - (frame-snap-points)) - (into #{shape-center} (:points shape))))) + (let [shape (gsh/transform-shape shape)] + + (case (:type shape) + :frame (-> shape :selrect frame-snap-points) + (:path :curve) (-> shape :selrect selrect-snap-points) + (into #{(gsh/center-shape shape)} (:points shape))) + )) From 275f6e3dc27583ac2518fdd9e317567cf94d7965 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 13 Nov 2020 16:23:36 +0100 Subject: [PATCH 052/195] :tada: Improved reusability of drawing functions --- common/app/common/geom/point.cljc | 11 ++ common/app/common/geom/shapes/path.cljc | 6 +- common/app/common/geom/shapes/transforms.cljc | 3 +- .../app/main/data/workspace/drawing/path.cljs | 182 +++++++++++------- frontend/src/app/util/data.cljs | 28 +++ frontend/src/app/util/geom/snap_points.cljs | 1 - 6 files changed, 154 insertions(+), 77 deletions(-) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index 32112f9e15..8ca2bb45bc 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -26,6 +26,14 @@ [v] (instance? Point v)) +(defn ^boolean point-like? + [{:keys [x y] :as v}] + (and (map? v) + (not (nil? x)) + (not (nil? y)) + (number? x) + (number? y))) + (defn point "Create a Point instance." ([] (Point. 0 0)) @@ -37,6 +45,9 @@ (number? v) (Point. v v) + (point-like? v) + (Point. (:x v) (:y v)) + :else (throw (ex-info "Invalid arguments" {:v v})))) ([x y] diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index ab77dfda60..5f8e2d8f8e 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -21,7 +21,10 @@ segments) (defn content->points [content] - (mapv #(gpt/point (-> % :params :x) (-> % :params :y)) content)) + (->> content + (map #(when (-> % :params :x) (gpt/point (-> % :params :x) (-> % :params :y)))) + (remove nil?) + (into []))) ;; https://medium.com/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf ;; https://en.wikipedia.org/wiki/Bernstein_polynomial @@ -105,6 +108,7 @@ (let [calc-extremities (fn [command prev] (case (:command command) + :close-path [] :move-to [(command->point command)] ;; If it's a line we add the beginning point and endpoint diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 1b79e9b02a..d2ff83aec9 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -226,7 +226,8 @@ :content content :points points :selrect selrect - :rotation rotation))) + ;;:rotation rotation + ))) (defn apply-transform-curve [shape transform] diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 0fb022ba50..420ddda6f9 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -11,12 +11,101 @@ (:require [beicon.core :as rx] [potok.core :as ptk] + [app.common.math :as mth] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.main.streams :as ms] + [app.util.data :as d] [app.util.geom.path :as ugp] + [app.main.streams :as ms] [app.main.data.workspace.drawing.common :as common])) +;;;; + +(def close-path-distance 5) + +(defn seek-start-path [content] + (->> content + reverse + (d/seek (fn [{cmd :command}] (= cmd :move-to))) + :params)) + +(defn next-node + "Calculates the next-node to be inserted." + [shape position prev-point prev-handler] + (let [last-command (-> shape :content last :command) + start-point (-> shape :content seek-start-path) + + add-line? (and prev-point (not prev-handler) (not= last-command :close-path)) + add-curve? (and prev-point prev-handler (not= last-command :close-path)) + close-path? (and start-point + (< (mth/abs (gpt/distance (gpt/point start-point) + (gpt/point position))) + close-path-distance))] + (cond + close-path? {:command :close-path + :params []} + add-line? {:command :line-to + :params position} + add-curve? {:command :curve-to + :params (ugp/make-curve-params position prev-handler)} + :else {:command :move-to + :params position}))) + +(defn append-node + "Creates a new node in the path. Usualy used when drawing." + [shape position prev-point prev-handler] + (let [command (next-node shape position prev-point prev-handler)] + (as-> shape $ + (update $ :content (fnil conj []) command) + (update $ :selrect (gsh/content->selrect (:content $)))))) + +(defn suffix-keyword [kw suffix] + (let [strkw (if kw (name kw) "")] + (keyword (str strkw suffix)))) + +;; handler-type => :prev :next +(defn move-handler [shape index handler-type match-opposite? position] + (let [content (:content shape) + [command next-command] (-> (d/with-next content) (nth index)) + + update-command + (fn [{cmd :command params :params :as command} param-prefix prev-command] + (if (#{:line-to :curve-to} cmd) + (let [command (if (= cmd :line-to) + {:command :curve-to + :params (ugp/make-curve-params params (:params prev-command))} + command)] + (-> command + (update :params assoc + (suffix-keyword param-prefix "x") (:x position) + (suffix-keyword param-prefix "y") (:y position)))) + command)) + + update-content + (fn [shape index prefix] + (if (contains? (:content shape) index) + (let [prev-command (get-in shape [:content (dec index)])] + (update-in shape [:content index] update-command prefix prev-command)) + + shape))] + + (cond-> shape + (= :prev handler-type) + (update-content index :c2) + + (and (= :next handler-type) next-command) + (update-content (inc index) :c1) + + match-opposite? + (move-handler + index + (if (= handler-type :prev) :next :prev) + false + (ugp/opposite-handler (gpt/point (:params command)) + (gpt/point position)))))) + + +;;;; (defn finish-event? [{:keys [type shift] :as event}] (or (= event ::end-path-drawing) (= event :interrupt) @@ -74,92 +163,37 @@ (ptk/reify ::add-node ptk/UpdateEvent (update [_ state] - (let [point {:x x :y y} - {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object]) - - command (cond - (and last-point (not prev-handler)) - {:command :line-to - :params point} - - (and last-point prev-handler) - {:command :curve-to - :params (ugp/make-curve-params point prev-handler)} - - :else - nil) - ] - (-> state - (assoc-in [:workspace-drawing :object :preview] command)))))) + (let [position (gpt/point x y) + {:keys [last-point prev-handler] :as shape} (get-in state [:workspace-drawing :object]) + command (next-node shape position last-point prev-handler)] + (assoc-in state [:workspace-drawing :object :preview] command))))) (defn add-node [{:keys [x y]}] (ptk/reify ::add-node ptk/UpdateEvent (update [_ state] - (let [point {:x x :y y} - {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object]) - command (cond - (and last-point (not prev-handler)) - {:command :line-to - :params point} - - (and last-point prev-handler) - {:command :curve-to - :params (ugp/make-curve-params point prev-handler)} - - :else - {:command :move-to - :params point}) - ] - (-> state - (assoc-in [:workspace-drawing :object :last-point] point) - (update-in [:workspace-drawing :object] dissoc :prev-handler) - (update-in [:workspace-drawing :object :content] (fnil conj []) command) - (update-in [:workspace-drawing :object] calculate-selrect)))))) + (let [position (gpt/point x y) + {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object])] + (update-in + state + [:workspace-drawing :object] + #(-> % + (append-node position last-point prev-handler) + (assoc :last-point position) + (dissoc :prev-handler))))))) (defn drag-handler [{:keys [x y]}] (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] - (let [change-handler (fn [content] - (let [last-idx (dec (count content)) - last (get content last-idx nil) - prev (get content (dec last-idx) nil) - {last-x :x last-y :y} (:params last) - opposite (when last (ugp/opposite-handler (gpt/point last-x last-y) (gpt/point x y)))] - (cond - (and prev (= (:command last) :line-to)) - (-> content - (assoc last-idx {:command :curve-to - :params {:x (-> last :params :x) - :y (-> last :params :y) - :c1x (-> prev :params :x) - :c1y (-> prev :params :y) - :c2x (-> last :params :x) - :c2y (-> last :params :y)}}) - (update-in - [last-idx :params] - #(-> % - (assoc :c2x (:x opposite) - :c2y (:y opposite))))) - - (= (:command last) :curve-to) - (update-in content - [last-idx :params] - #(-> % - (assoc :c2x (:x opposite) - :c2y (:y opposite)))) - :else - content)) - - - ) - handler (gpt/point x y)] + (let [position (gpt/point x y) + shape (get-in state [:workspace-drawing :object]) + index (dec (count (:content shape)))] (-> state - (update-in [:workspace-drawing :object :content] change-handler) - (assoc-in [:workspace-drawing :object :drag-handler] handler)))))) + (update-in [:workspace-drawing :object] move-handler index :next true position) + (assoc-in [:workspace-drawing :object :drag-handler] position)))))) (defn finish-drag [] (ptk/reify ::finish-drag diff --git a/frontend/src/app/util/data.cljs b/frontend/src/app/util/data.cljs index 0a6c2889cb..04e0e518e7 100644 --- a/frontend/src/app/util/data.cljs +++ b/frontend/src/app/util/data.cljs @@ -118,6 +118,33 @@ (into {})) m1)) +(defn with-next + "Given a collectin will return a new collection where each element + is paried with the next item in the collection + (with-next (range 5)) => [[0 1] [1 2] [2 3] [3 4] [4 nil]" + [coll] + (map vector + coll + (concat [] (rest coll) [nil]))) + +(defn with-prev + "Given a collectin will return a new collection where each element + is paried with the previous item in the collection + (with-prev (range 5)) => [[0 nil] [1 0] [2 1] [3 2] [4 3]" + [coll] + (map vector + coll + (concat [nil] coll))) + +(defn with-prev-next + "Given a collection will return a new collection where every item is paired + with the previous and the next item of a collection + (with-prev-next (range 5)) => [[0 nil 1] [1 0 2] [2 1 3] [3 2 4] [4 3 nil]" + [coll] + (map vector + coll + (concat [nil] coll) + (concat [] (rest coll) [nil]))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Numbers Parsing @@ -221,3 +248,4 @@ ;; nil ;; (throw e#))))))) + diff --git a/frontend/src/app/util/geom/snap_points.cljs b/frontend/src/app/util/geom/snap_points.cljs index d6ad0bdaac..75f0427516 100644 --- a/frontend/src/app/util/geom/snap_points.cljs +++ b/frontend/src/app/util/geom/snap_points.cljs @@ -30,7 +30,6 @@ (defn shape-snap-points [shape] (let [shape (gsh/transform-shape shape)] - (case (:type shape) :frame (-> shape :selrect frame-snap-points) (:path :curve) (-> shape :selrect selrect-snap-points) From 8db7078ce81b2721db1e05388328ded3e7748ec7 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 16 Nov 2020 13:00:39 +0100 Subject: [PATCH 053/195] :sparkles: Path edition mode --- common/app/common/geom/shapes/path.cljc | 15 ++ frontend/resources/images/icons/nodes-add.svg | 3 + .../resources/images/icons/nodes-corner.svg | 3 + .../resources/images/icons/nodes-curve.svg | 3 + .../resources/images/icons/nodes-join.svg | 3 + .../resources/images/icons/nodes-merge.svg | 3 + .../resources/images/icons/nodes-remove.svg | 3 + .../resources/images/icons/nodes-separate.svg | 3 + .../resources/images/icons/nodes-snap.svg | 3 + .../styles/main/partials/workspace.scss | 73 +++++++ frontend/src/app/main/data/workspace.cljs | 3 + .../src/app/main/data/workspace/drawing.cljs | 2 +- .../app/main/data/workspace/drawing/path.cljs | 159 ++++++++++++-- frontend/src/app/main/ui/icons.cljs | 8 + frontend/src/app/main/ui/workspace.cljs | 3 +- .../src/app/main/ui/workspace/selection.cljs | 12 +- .../app/main/ui/workspace/shapes/common.cljs | 9 +- .../app/main/ui/workspace/shapes/path.cljs | 202 ++++++++++++------ .../src/app/main/ui/workspace/viewport.cljs | 28 ++- frontend/src/app/util/geom/path.cljs | 6 - 20 files changed, 436 insertions(+), 108 deletions(-) create mode 100644 frontend/resources/images/icons/nodes-add.svg create mode 100644 frontend/resources/images/icons/nodes-corner.svg create mode 100644 frontend/resources/images/icons/nodes-curve.svg create mode 100644 frontend/resources/images/icons/nodes-join.svg create mode 100644 frontend/resources/images/icons/nodes-merge.svg create mode 100644 frontend/resources/images/icons/nodes-remove.svg create mode 100644 frontend/resources/images/icons/nodes-separate.svg create mode 100644 frontend/resources/images/icons/nodes-snap.svg diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index 5f8e2d8f8e..1c9f26466f 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -146,3 +146,18 @@ (not (nil? c2x)) (set-tr :c2x :c2y)))] (mapv #(update % :params transform-params) content))) + +(defn apply-content-modifiers [content modifiers] + (let [red-fn (fn [content [index params]] + (if (contains? content index) + (cond-> content + (:x params) (update-in [index :params :x] + (:x params)) + (:y params) (update-in [index :params :y] + (:y params)) + + (:c1x params) (update-in [index :params :c1x] + (:c1x params)) + (:c1y params) (update-in [index :params :c1y] + (:c1y params)) + + (:c2x params) (update-in [index :params :c2x] + (:c2x params)) + (:c2y params) (update-in [index :params :c2y] + (:c2y params))) + content))] + (reduce red-fn content modifiers))) diff --git a/frontend/resources/images/icons/nodes-add.svg b/frontend/resources/images/icons/nodes-add.svg new file mode 100644 index 0000000000..9c5ecf93a7 --- /dev/null +++ b/frontend/resources/images/icons/nodes-add.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-corner.svg b/frontend/resources/images/icons/nodes-corner.svg new file mode 100644 index 0000000000..295e316ab5 --- /dev/null +++ b/frontend/resources/images/icons/nodes-corner.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-curve.svg b/frontend/resources/images/icons/nodes-curve.svg new file mode 100644 index 0000000000..b12913fc53 --- /dev/null +++ b/frontend/resources/images/icons/nodes-curve.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-join.svg b/frontend/resources/images/icons/nodes-join.svg new file mode 100644 index 0000000000..551451cb93 --- /dev/null +++ b/frontend/resources/images/icons/nodes-join.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-merge.svg b/frontend/resources/images/icons/nodes-merge.svg new file mode 100644 index 0000000000..5e0d9c3369 --- /dev/null +++ b/frontend/resources/images/icons/nodes-merge.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-remove.svg b/frontend/resources/images/icons/nodes-remove.svg new file mode 100644 index 0000000000..e00ecd534d --- /dev/null +++ b/frontend/resources/images/icons/nodes-remove.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-separate.svg b/frontend/resources/images/icons/nodes-separate.svg new file mode 100644 index 0000000000..4e188e3cb8 --- /dev/null +++ b/frontend/resources/images/icons/nodes-separate.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/images/icons/nodes-snap.svg b/frontend/resources/images/icons/nodes-snap.svg new file mode 100644 index 0000000000..1bd5edac4a --- /dev/null +++ b/frontend/resources/images/icons/nodes-snap.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index ccccec01e1..69282ab400 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -225,3 +225,76 @@ padding: $x-small; } } + +.viewport-actions { + position: absolute; + margin-left: auto; + width: 100%; + margin-top: 2rem; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + + .path-actions { + display: flex; + flex-direction: row; + background: white; + border-radius: 3px; + padding: 0.5rem; + border: 1px solid $color-gray-20; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); + } + + .viewport-actions-group { + display: flex; + flex-direction: row; + border-right: 1px solid $color-gray-20; + } + + .viewport-actions-entry { + width: 27px; + height: 20px; + margin: 0 0.25rem; + cursor: pointer; + + svg { + width: 27px; + height: 20px; + } + + &:hover svg { + fill: $color-primary; + } + + &.disabled { + opacity: 0.3; + + &:hover svg { + fill: initial; + } + } + } + + .viewport-actions-entry-wide { + width: 27px; + height: 20px; + + svg { + width: 27px; + height: 20px; + } + } + + .path-actions > :first-child .viewport-actions-entry { + margin-left: 0; + } + + .path-actions > :last-child { + border: none; + } + + .path-actions > :last-child .viewport-actions-entry { + margin-right: 0; + } +} diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 70cf54a206..112f98afa1 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -32,6 +32,7 @@ [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] [app.main.data.workspace.drawing :as dwd] + [app.main.data.workspace.drawing.path :as dwdp] [app.main.repo :as rp] [app.main.store :as st] [app.main.streams :as ms] @@ -1629,6 +1630,8 @@ (def add-shape dwc/add-shape) (def start-edition-mode dwc/start-edition-mode) +(defn start-path-edit [id] (dwdp/start-path-edit id)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index 63b0668fc3..7987488a2b 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -99,6 +99,6 @@ (box/handle-drawing-box)))))) ;; Export -(def close-drawing-path path/close-drawing-path) +#_(def close-drawing-path path/close-drawing-path) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 420ddda6f9..4d956d7b69 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -17,7 +17,9 @@ [app.util.data :as d] [app.util.geom.path :as ugp] [app.main.streams :as ms] - [app.main.data.workspace.drawing.common :as common])) + [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.drawing.common :as common] + [app.common.geom.shapes.path :as gsp])) ;;;; @@ -149,14 +151,14 @@ (update [_ state] (-> state (assoc-in [:workspace-drawing :object :initialized?] true) - (assoc-in [:workspace-drawing :object :last-point] nil))))) + (assoc-in [:workspace-local :edit-path :last-point] nil))))) (defn finish-path [] (ptk/reify ::finish-path ptk/UpdateEvent (update [_ state] (-> state - (assoc-in [:workspace-drawing :object :last-point] nil) + (update :workspace-local dissoc :edit-path) (update-in [:workspace-drawing :object] calculate-selrect))))) (defn preview-next-point [{:keys [x y]}] @@ -164,9 +166,9 @@ ptk/UpdateEvent (update [_ state] (let [position (gpt/point x y) - {:keys [last-point prev-handler] :as shape} (get-in state [:workspace-drawing :object]) + {:keys [last-point prev-handler] :as shape} (get-in state [:workspace-local :edit-path]) command (next-node shape position last-point prev-handler)] - (assoc-in state [:workspace-drawing :object :preview] command))))) + (assoc-in state [:workspace-local :edit-path :preview] command))))) (defn add-node [{:keys [x y]}] (ptk/reify ::add-node @@ -174,14 +176,11 @@ (update [_ state] (let [position (gpt/point x y) - {:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object])] - (update-in - state - [:workspace-drawing :object] - #(-> % - (append-node position last-point prev-handler) - (assoc :last-point position) - (dissoc :prev-handler))))))) + {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path])] + (-> state + (assoc-in [:workspace-local :edit-path :last-point] position) + (update-in [:workspace-local :edit-path] dissoc :prev-handler) + (update-in [:workspace-drawing :object] append-node position last-point prev-handler)))))) (defn drag-handler [{:keys [x y]}] (ptk/reify ::drag-handler @@ -193,16 +192,16 @@ index (dec (count (:content shape)))] (-> state (update-in [:workspace-drawing :object] move-handler index :next true position) - (assoc-in [:workspace-drawing :object :drag-handler] position)))))) + (assoc-in [:workspace-local :edit-path :drag-handler] position)))))) (defn finish-drag [] (ptk/reify ::finish-drag ptk/UpdateEvent (update [_ state] - (let [handler (get-in state [:workspace-drawing :object :drag-handler])] + (let [handler (get-in state [:workspace-local :edit-path :drag-handler])] (-> state - (update-in [:workspace-drawing :object] dissoc :drag-handler) - (assoc-in [:workspace-drawing :object :prev-handler] handler)))))) + (update-in [:workspace-local :edit-path] dissoc :drag-handler) + (assoc-in [:workspace-local :edit-path :prev-handler] handler)))))) (defn make-click-stream [stream down-event] @@ -238,7 +237,6 @@ ptk/WatchEvent (watch [_ state stream] - ;; clicks stream<[MouseEvent, Position]> (let [mouse-down (->> stream (rx/filter ms/mouse-down?)) finish-events (->> stream (rx/filter finish-event?)) @@ -266,10 +264,7 @@ (rx/merge mousemove-events mousedown-events) (rx/of (finish-path)) - (rx/of common/handle-finish-drawing))) - - - ))) + (rx/of common/handle-finish-drawing)))))) #_(def handle-drawing-path (ptk/reify ::handle-drawing-path @@ -331,7 +326,7 @@ (rx/of finish-drawing-path common/handle-finish-drawing))))))) -(defn close-drawing-path [] +#_(defn close-drawing-path [] (ptk/reify ::close-drawing-path ptk/UpdateEvent (update [_ state] @@ -340,3 +335,121 @@ ptk/WatchEvent (watch [_ state stream] (rx/of ::end-path-drawing)))) + + +(defn stop-path-edit [] + (ptk/reify ::stop-path-edit + ptk/UpdateEvent + (update [_ state] + (update state :workspace-local dissoc :edit-path)))) + +(defn start-path-edit + [id] + (ptk/reify ::start-path-edit + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:workspace-local :edit-path] {})) + + ptk/WatchEvent + (watch [_ state stream] + (->> stream + (rx/filter #(= % :interrupt)) + (rx/take 1) + (rx/map #(stop-path-edit)))))) + +(defn modify-point [index dx dy] + (ptk/reify ::modify-point + + ptk/UpdateEvent + (update [_ state] + + (-> state + (update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc + :c1x dx :c1y dy) + (update-in [:workspace-local :edit-path :content-modifiers index] assoc + :x dx :y dy :c2x dx :c2y dy) + )))) + +(defn modify-handler [index type dx dy] + (ptk/reify ::modify-point + ptk/UpdateEvent + (update [_ state] + (let [s1 (if (= type :prev) -1 1) + s2 (if (= type :prev) 1 -1)] + (-> state + (update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc + :c1x (* s1 dx) :c1y (* s1 dy)) + (update-in [:workspace-local :edit-path :content-modifiers index] assoc + :c2x (* s2 dx) :c2y (* s2 dy) )) + )))) + +(defn apply-content-modifiers [] + (ptk/reify ::apply-content-modifiers + ;;ptk/UpdateEvent + ;;(update [_ state] + ;; (update-in state [:workspace-local :edit-path] dissoc :content-modifiers)) + + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-in state [:workspace-local :edition]) + page-id (:current-page-id state) + old-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) + old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) + content-modifiers (get-in state [:workspace-local :edit-path :content-modifiers]) + new-content (gsp/apply-content-modifiers old-content content-modifiers) + new-selrect (gsh/content->selrect new-content) + rch [{:type :mod-obj + :id id + :page-id page-id + :operations [{:type :set :attr :content :val new-content} + {:type :set :attr :selrect :val new-selrect}]}] + + uch [{:type :mod-obj + :id id + :page-id page-id + :operations [{:type :set :attr :content :val old-content} + {:type :set :attr :selrect :val old-selrect}]}]] + + (rx/of (dwc/commit-changes rch uch {:commit-local? true}) + (fn [state] (update-in state [:workspace-local :edit-path] dissoc :content-modifiers))))))) + +(defn start-move-path-point + [index] + (ptk/reify ::start-move-path-point + ptk/WatchEvent + (watch [_ state stream] + (let [start-point @ms/mouse-position + start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers index :x] 0) + start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers index :y] 0)] + (rx/concat + (->> ms/mouse-position + (rx/take-until (->> stream (rx/filter ms/mouse-up?))) + (rx/map #(modify-point + index + (+ start-delta-x (- (:x %) (:x start-point))) + (+ start-delta-y (- (:y %) (:y start-point)))))) + (rx/concat (rx/of (apply-content-modifiers))) + ))))) + +(defn start-move-handler + [index type] + (ptk/reify ::start-move-handler + ptk/WatchEvent + (watch [_ state stream] + (let [[cx cy] (if (= :prev type) [:c2x :c2y] [:c1x :c1y]) + cidx (if (= :prev type) index (inc index)) + + start-point @ms/mouse-position + start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers cidx cx] 0) + start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers cidx cy] 0)] + + (rx/concat + (->> ms/mouse-position + (rx/take-until (->> stream (rx/filter ms/mouse-up?))) + (rx/map #(modify-handler + index + type + (+ start-delta-x (- (:x %) (:x start-point))) + (+ start-delta-y (- (:y %) (:y start-point))))) + ) + (rx/concat (rx/of (apply-content-modifiers)))))))) diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 5f9fc07059..0550c4a4a1 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -128,6 +128,14 @@ (def checkbox-checked (icon-xref :checkbox-checked)) (def checkbox-unchecked (icon-xref :checkbox-unchecked)) (def code (icon-xref :code)) +(def nodes-add (icon-xref :nodes-add)) +(def nodes-corner (icon-xref :nodes-corner)) +(def nodes-curve (icon-xref :nodes-curve)) +(def nodes-join (icon-xref :nodes-join)) +(def nodes-merge (icon-xref :nodes-merge)) +(def nodes-remove (icon-xref :nodes-remove)) +(def nodes-separate (icon-xref :nodes-separate)) +(def nodes-snap (icon-xref :nodes-snap)) (def loader-pencil (mf/html diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index ea77a68b97..dfca190994 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -29,7 +29,7 @@ [app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]] [app.main.ui.workspace.scroll :as scroll] [app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]] - [app.main.ui.workspace.viewport :refer [viewport coordinates]] + [app.main.ui.workspace.viewport :refer [viewport viewport-actions coordinates]] [app.util.dom :as dom] [beicon.core :as rx] [cuerdas.core :as str] @@ -65,6 +65,7 @@ (when (contains? layout :rules) [:& workspace-rules {:local local}]) + [:& viewport-actions] [:& viewport {:file file :local local :layout layout}]]] diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 120bcd543d..5f9708a581 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -31,7 +31,8 @@ [app.common.geom.matrix :as gmt] [app.util.debug :refer [debug?]] [app.main.ui.workspace.shapes.outline :refer [outline]] - [app.main.ui.measurements :as msr])) + [app.main.ui.measurements :as msr] + [app.main.ui.workspace.shapes.path :refer [path-editor]])) (def rotation-handler-size 25) (def resize-point-radius 4) @@ -366,8 +367,13 @@ [:& text-edition-selection-handlers {:shape shape :zoom zoom :color color}] - (and (or (= type :path) - (= type :curve)) + + (= (= type :path) + (= edition (:id shape))) + [:& path-editor {:zoom zoom + :shape shape}] + + (and (= type :curve) (= edition (:id shape))) [:& path-edition-selection-handlers {:shape shape :zoom zoom diff --git a/frontend/src/app/main/ui/workspace/shapes/common.cljs b/frontend/src/app/main/ui/workspace/shapes/common.cljs index 302c0cf482..af268cd692 100644 --- a/frontend/src/app/main/ui/workspace/shapes/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/common.cljs @@ -23,6 +23,7 @@ (defn- on-mouse-down [event {:keys [id type] :as shape}] (let [selected @refs/selected-shapes + edition @refs/selected-edition selected? (contains? selected id) drawing? @refs/selected-drawing-tool button (.-which (.-nativeEvent event))] @@ -35,9 +36,8 @@ nil (= type :frame) - (when selected? - (dom/stop-propagation event) - (st/emit! (dw/start-move-selected))) + (do (dom/stop-propagation event) + (st/emit! (dw/start-move-selected))) :else (do @@ -50,7 +50,8 @@ (st/emit! (dw/deselect-all))) (st/emit! (dw/select-shape id)))) - (st/emit! (dw/start-move-selected))))))) + (when (not= edition id) + (st/emit! (dw/start-move-selected)))))))) (defn on-context-menu [event shape] diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index d1f761ab59..338a45f799 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -10,22 +10,40 @@ (ns app.main.ui.workspace.shapes.path (:require [rumext.alpha :as mf] - [app.common.data :as d] + [okulary.core :as l] + [app.util.data :as d] [app.util.dom :as dom] [app.util.timers :as ts] + [app.main.refs :as refs] [app.main.streams :as ms] [app.main.constants :as c] [app.main.refs :as refs] [app.main.store :as st] [app.main.data.workspace :as dw] [app.main.data.workspace.drawing :as dr] + [app.main.data.workspace.drawing.path :as drp] [app.main.ui.keyboard :as kbd] [app.main.ui.shapes.path :as path] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.shapes.common :as common] [app.util.geom.path :as ugp] - [app.common.geom.shapes.path :as gsp])) + [app.common.geom.point :as gpt] + [app.common.geom.shapes.path :as gsp] + [app.main.ui.cursors :as cur] + [app.main.ui.icons :as i])) + +(def primary-color "#1FDEA7") +(def secondary-color "#DB00FF") +(def black-color "#000000") +(def white-color "#FFFFFF") +(def gray-color "#B1B2B5") + +(def edit-path-ref + (l/derived :edit-path refs/workspace-local)) + +(def content-modifiers-ref + (l/derived :content-modifiers edit-path-ref)) (mf/defc path-wrapper {::mf/wrap-props false} @@ -43,12 +61,15 @@ on-double-click (mf/use-callback (mf/deps shape) (fn [event] - (prn "?? PATH") - (when (and (not (::dr/initialized? shape)) (hover? (:id shape))) + (when (not (::dr/initialized? shape)) (do (dom/stop-propagation event) (dom/prevent-default event) - (st/emit! (dw/start-edition-mode (:id shape)))))))] + (st/emit! (dw/start-edition-mode (:id shape)) + (dw/start-path-edit (:id shape))))))) + + content-modifiers (mf/deref content-modifiers-ref) + shape (update shape :content gsp/apply-content-modifiers content-modifiers)] [:> shape-container {:shape shape :on-double-click on-double-click @@ -57,75 +78,142 @@ [:& path/path-shape {:shape shape :background? true}]])) +(mf/defc path-actions [{:keys [shape]}] + [:div.path-actions + [:div.viewport-actions-group + [:div.viewport-actions-entry i/nodes-add] + [:div.viewport-actions-entry i/nodes-remove]] -(mf/defc path-handler [{:keys [point handler zoom selected]}] + [:div.viewport-actions-group + [:div.viewport-actions-entry i/nodes-merge] + [:div.viewport-actions-entry i/nodes-join] + [:div.viewport-actions-entry i/nodes-separate]] + + [:div.viewport-actions-group + [:div.viewport-actions-entry i/nodes-corner] + [:div.viewport-actions-entry i/nodes-curve]] + + [:div.viewport-actions-group + [:div.viewport-actions-entry i/nodes-snap]]]) + + +(mf/defc path-preview [{:keys [zoom command from]}] + (when (not= :move-to (:command command)) + [:path {:style {:fill "transparent" + :stroke secondary-color + :stroke-width (/ 1 zoom)} + :d (ugp/content->path [{:command :move-to + :params {:x (:x from) + :y (:y from)}} + command])}])) + +(mf/defc path-point [{:keys [index position stroke-color fill-color zoom]}] + (let [{:keys [x y]} position + on-click (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event)) + on-mouse-down (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (drp/start-move-path-point index)))] + [:circle + {:cx x + :cy y + :r (/ 3 zoom) + :on-click on-click + :on-mouse-down on-mouse-down + :style {:cursor cur/resize-alt + :stroke-width (/ 1 zoom) + :stroke (or stroke-color black-color) + :fill (or fill-color white-color)}}])) + +(mf/defc path-handler [{:keys [index point handler zoom selected type]}] (when (and point handler) - (let [{:keys [x y]} handler] - [:g.handler + (let [{:keys [x y]} handler + on-click (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event)) + on-mouse-down (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (drp/start-move-handler index type)))] + [:g.handler {:class (name type)} [:line {:x1 (:x point) :y1 (:y point) :x2 x :y2 y - :style {:stroke "#B1B2B5" + :style {:stroke gray-color :stroke-width (/ 1 zoom)}}] [:rect {:x (- x (/ 3 zoom)) :y (- y (/ 3 zoom)) :width (/ 6 zoom) :height (/ 6 zoom) - :style {:stroke-width (/ 1 zoom) - :stroke (if selected "#000000" "#1FDEA7") - :fill (if selected "#1FDEA7" "#FFFFFF")}}]]))) + :on-click on-click + :on-mouse-down on-mouse-down + :style {:cursor cur/resize-alt + :stroke-width (/ 1 zoom) + :stroke (if selected black-color primary-color) + :fill (if selected primary-color white-color)}}]]))) (mf/defc path-editor [{:keys [shape zoom]}] - (let [points (gsp/content->points (:content shape)) - drag-handler (:drag-handler shape) - prev-handler (:prev-handler shape) - last-command (last (:content shape)) - selected false + (let [{:keys [content]} shape + {:keys [drag-handler prev-handler preview content-modifiers]} (mf/deref edit-path-ref) + content (gsp/apply-content-modifiers content content-modifiers) + points (gsp/content->points content) + last-command (last content) last-p (last points) - handlers (ugp/extract-handlers (:content shape)) - handlers (if (and prev-handler (not drag-handler)) - (conj handlers {:point last-p :prev prev-handler}) - handlers) - ] + selected false] [:g.path-editor - (when (and (:preview shape) (not (:drag-handler shape))) - [:* - [:path {:style {:fill "transparent" - :stroke "#DB00FF" - :stroke-width (/ 1 zoom)} - :d (ugp/content->path [{:command :move-to - :params {:x (:x last-p) - :y (:y last-p)}} - (:preview shape)])}] - [:circle - {:cx (-> shape :preview :params :x) - :cy (-> shape :preview :params :y) - :r (/ 3 zoom) - :style {:stroke-width (/ 1 zoom) - :stroke "#DB00FF" - :fill "#FFFFFF"}}]]) + (when (and preview (not drag-handler)) + [:g.preview {:style {:pointer-events "none"}} + [:& path-preview {:command preview + :from last-p + :zoom zoom}] + [:& path-point {:position (:params preview) + :fill-color secondary-color + :zoom zoom}]]) - (for [{:keys [point prev next]} handlers] - [:* - [:& path-handler {:point point - :handler prev - :zoom zoom - :type :prev - :selected false}] - [:& path-handler {:point point - :handler next - :zoom zoom - :type :next - :selected false}]]) + (for [[index [cmd next]] (d/enumerate (d/with-next content))] + (let [point (gpt/point (:params cmd))] + [:g.path-node + (when (= :curve-to (:command cmd)) + [:& path-handler {:point point + :handler (gpt/point (-> cmd :params :c2x) (-> cmd :params :c2y)) + :zoom zoom + :type :prev + :index index + :selected false}]) + + (when (= :curve-to (:command next)) + [:& path-handler {:point point + :handler (gpt/point (-> next :params :c1x) (-> next :params :c1y)) + :zoom zoom + :type :next + :index index + :selected false}]) + + (when (and (= index (dec (count content))) + prev-handler (not drag-handler)) + [:& path-handler {:point point + :handler prev-handler + :zoom zoom + :type :prev + :index index + :selected false}]) + + [:& path-point {:position point + :stroke-color (when-not selected primary-color) + :fill-color (when selected primary-color) + :index index + :zoom zoom}]])) (when drag-handler - [:* + [:g.drag-handler (when (not= :move-to (:command last-command)) [:& path-handler {:point last-p :handler (ugp/opposite-handler last-p drag-handler) @@ -136,14 +224,4 @@ :handler drag-handler :zoom zoom :type :drag - :selected false}]]) - - (for [{:keys [x y] :as point} points] - [:circle - {:cx x - :cy y - :r (/ 3 zoom) - :style {:stroke-width (/ 1 zoom) - :stroke (if selected "#000000" "#1FDEA7") - :fill (if selected "#1FDEA7" "#FFFFFF")} - }])])) + :selected false}]])])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index a2e7461ac3..547ceb36c1 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -1,4 +1,4 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public +; 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/. ;; @@ -52,7 +52,8 @@ [goog.events :as events] [potok.core :as ptk] [promesa.core :as p] - [rumext.alpha :as mf]) + [rumext.alpha :as mf] + [app.main.ui.workspace.shapes.path :refer [path-actions]]) (:import goog.events.EventType)) ;; --- Coordinates Widget @@ -222,7 +223,6 @@ drawing-obj (:object drawing) zoom (or zoom 1) - on-mouse-down (mf/use-callback (mf/deps drawing-tool edition) @@ -234,15 +234,13 @@ alt? (kbd/alt? event)] (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) (cond - (and (= 1 (.-which event))) - + (and (= 1 (.-which event)) (not edition)) (if drawing-tool (when (not (#{:comments :path} drawing-tool)) (st/emit! (dd/start-drawing drawing-tool))) (st/emit! dw/handle-selection)) - (and (not edition) - (= 2 (.-which event))) + (and (= 2 (.-which event))) (handle-viewport-positioning viewport-ref))))) on-context-menu @@ -294,12 +292,16 @@ on-double-click (mf/use-callback + (mf/deps edition) (fn [event] (dom/stop-propagation event) (let [ctrl? (kbd/ctrl? event) shift? (kbd/shift? event) alt? (kbd/alt? event)] - (st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?))))) + (st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?)) + + (if edition + (st/emit! dw/clear-edition-mode))))) on-key-down (mf/use-callback @@ -610,3 +612,13 @@ (when (= options-mode :prototype) [:& interactions {:selected selected}])]])) + +(mf/defc viewport-actions [] + (let [edition (mf/deref refs/selected-edition) + selected (mf/deref refs/selected-objects) + shape (-> selected first)] + (when (and (= (count selected) 1) + (= (:id shape) edition) + (= :path (:type shape))) + [:div.viewport-actions + [:& path-actions {:shape shape}]]))) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index 1da9ce3a0e..e8d40fff92 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -213,9 +213,3 @@ opposite (gpt/add point (gpt/negate phv))] opposite)) -(defn extract-handlers [content] - (let [extract (fn [{param1 :params :as cmd1} {param2 :params :as cmd2}] - {:point (gpt/point (:x param1) (:y param1)) - :prev (when (:c2x param1) (gpt/point (:c2x param1) (:c2y param1))) - :next (when (:c1x param2) (gpt/point (:c1x param2) (:c1y param2)))})] - (map extract content (d/concat [] (rest content) [nil])))) From b1c786077b0043d55b48eb8123309909da46bbcb Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 18 Nov 2020 11:37:10 +0100 Subject: [PATCH 054/195] :sparkles: Path create-edit workflow --- common/app/common/pages.cljc | 40 +- .../resources/images/cursors/pen-node.svg | 4 + .../resources/images/cursors/pointer-move.svg | 6 + .../resources/images/cursors/pointer-node.svg | 1 + frontend/resources/images/icons/pen.svg | 56 +++ .../resources/images/icons/pointer-inner.svg | 3 + .../styles/main/partials/workspace.scss | 20 +- frontend/src/app/main/data/workspace.cljs | 15 +- .../src/app/main/data/workspace/common.cljs | 11 +- .../src/app/main/data/workspace/drawing.cljs | 7 +- .../app/main/data/workspace/drawing/path.cljs | 422 ++++++++++++------ frontend/src/app/main/ui/cursors.clj | 17 +- frontend/src/app/main/ui/cursors.cljs | 11 +- frontend/src/app/main/ui/icons.cljs | 2 + .../src/app/main/ui/workspace/selection.cljs | 4 +- .../app/main/ui/workspace/shapes/frame.cljs | 1 - .../app/main/ui/workspace/shapes/path.cljs | 166 ++++--- .../src/app/main/ui/workspace/viewport.cljs | 9 +- 18 files changed, 564 insertions(+), 231 deletions(-) create mode 100644 frontend/resources/images/cursors/pen-node.svg create mode 100644 frontend/resources/images/cursors/pointer-move.svg create mode 100644 frontend/resources/images/cursors/pointer-node.svg create mode 100644 frontend/resources/images/icons/pen.svg create mode 100644 frontend/resources/images/icons/pointer-inner.svg diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index ae5a919831..491b1fc789 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -611,8 +611,7 @@ :stroke-alignment :center :stroke-width 2 :stroke-color "#000000" - :stroke-opacity 1 - :segments []} + :stroke-opacity 1} {:type :frame :name "Artboard" @@ -632,8 +631,7 @@ :stroke-alignment :center :stroke-width 2 :stroke-color "#000000" - :stroke-opacity 1 - :segments []} + :stroke-opacity 1} {:type :text :name "Text" @@ -646,22 +644,24 @@ (ex/raise :type :assertion :code :shape-type-not-implemented :context {:type type})) - (assoc shape - :id (uuid/next) - :x 0 - :y 0 - :width 1 - :height 1 - :selrect {:x 0 - :x1 0 - :x2 1 - :y 0 - :y1 0 - :y2 1 - :width 1 - :height 1} - :points [] - :segments []))) + + (cond-> shape + :always + (assoc :id (uuid/next)) + + (not #{:path :curve}) + (assoc :x 0 + :y 0 + :width 1 + :height 1 + :selrect {:x 0 + :y 0 + :x1 0 + :y1 0 + :x2 1 + :y2 1 + :width 1 + :height 1})))) (defn make-minimal-group [frame-id selection-rect group-name] diff --git a/frontend/resources/images/cursors/pen-node.svg b/frontend/resources/images/cursors/pen-node.svg new file mode 100644 index 0000000000..ba03c12c61 --- /dev/null +++ b/frontend/resources/images/cursors/pen-node.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/resources/images/cursors/pointer-move.svg b/frontend/resources/images/cursors/pointer-move.svg new file mode 100644 index 0000000000..895bbd8ee6 --- /dev/null +++ b/frontend/resources/images/cursors/pointer-move.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/resources/images/cursors/pointer-node.svg b/frontend/resources/images/cursors/pointer-node.svg new file mode 100644 index 0000000000..185862c1d7 --- /dev/null +++ b/frontend/resources/images/cursors/pointer-node.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/resources/images/icons/pen.svg b/frontend/resources/images/icons/pen.svg new file mode 100644 index 0000000000..9cd7833552 --- /dev/null +++ b/frontend/resources/images/icons/pen.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/frontend/resources/images/icons/pointer-inner.svg b/frontend/resources/images/icons/pointer-inner.svg new file mode 100644 index 0000000000..50798578b7 --- /dev/null +++ b/frontend/resources/images/icons/pointer-inner.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index 69282ab400..d6119cd4a4 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -253,13 +253,17 @@ } .viewport-actions-entry { - width: 27px; - height: 20px; + width: 28px; + height: 28px; margin: 0 0.25rem; cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + border-radius: 3px; svg { - width: 27px; + width: 20px; height: 20px; } @@ -267,13 +271,21 @@ fill: $color-primary; } - &.disabled { + &.is-disabled { opacity: 0.3; &:hover svg { fill: initial; } } + + &.is-toggled { + background: $color-black; + + svg { + fill: $color-primary; + } + } } .viewport-actions-entry-wide { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 112f98afa1..a8fc65d4d2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1632,13 +1632,24 @@ (defn start-path-edit [id] (dwdp/start-path-edit id)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts impl https://github.com/ccampbell/mousetrap +(defn esc-pressed [] + (ptk/reify :esc-pressed + ptk/WatchEvent + (watch [_ state stream] + ;; Not interrupt when we're editing a path + (let [edition-id (get-in state [:workspace-local :edition]) + path-edit-mode (get-in state [:workspace-local :edit-path edition-id :edit-mode])] + (if-not (= :draw path-edit-mode) + (rx/of :interrupt + (deselect-all true)) + (rx/empty)))))) + (def shortcuts {"ctrl+i" #(st/emit! (toggle-layout-flags :assets)) "ctrl+l" #(st/emit! (toggle-layout-flags :sitemap :layers)) @@ -1671,7 +1682,7 @@ "ctrl+c" #(st/emit! copy-selected) "ctrl+v" #(st/emit! paste) "ctrl+x" #(st/emit! copy-selected delete-selected) - "escape" #(st/emit! :interrupt (deselect-all true)) + "escape" #(st/emit! (esc-pressed)) "del" #(st/emit! delete-selected) "backspace" #(st/emit! delete-selected) "ctrl+up" #(st/emit! (vertical-order-selected :up)) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 3275799b5f..594c00f03e 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -461,7 +461,14 @@ (ptk/reify ::start-edition-mode ptk/UpdateEvent (update [_ state] - (assoc-in state [:workspace-local :edition] id)) + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data :pages-index page-id :objects])] + ;; Can only edit objects that exist + (if (contains? objects id) + (-> state + (assoc-in [:workspace-local :selected] #{id}) + (assoc-in [:workspace-local :edition] id)) + state))) ptk/WatchEvent (watch [_ state stream] @@ -486,7 +493,7 @@ (let [page-id (:current-page-id state) objects (lookup-page-objects state page-id) - id (uuid/next) + id (or (:id attrs) (uuid/next)) shape (gpr/setup-proportions attrs) unames (retrieve-used-names objects) diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index 7987488a2b..9e792a7977 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -45,8 +45,9 @@ (rx/of (start-drawing :path))) ;; NOTE: comments are a special case and they manage they - ;; own interrupt cycle. - (when (not= tool :comments) + ;; own interrupt cycle.q + (when (and (not= tool :comments) + (not= tool :path)) (->> stream (rx/filter dwc/interrupt?) (rx/take 1) @@ -90,7 +91,7 @@ (watch [_ state stream] (rx/of (case type :path - (path/handle-drawing-path) + (path/handle-new-shape) :curve (curve/handle-drawing-curve) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 4d956d7b69..2ac40bf29c 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -14,38 +14,48 @@ [app.common.math :as mth] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.util.data :as d] + [app.util.data :as ud] + [app.common.data :as cd] [app.util.geom.path :as ugp] [app.main.streams :as ms] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.drawing.common :as common] [app.common.geom.shapes.path :as gsp])) -;;;; +;; CONSTANTS +(defonce enter-keycode 13) -(def close-path-distance 5) -(defn seek-start-path [content] +;; PRIVATE METHODS + +(defn get-path-id [state] + (or (get-in state [:workspace-local :edition]) + (get-in state [:workspace-drawing :object :id]))) + +(defn get-path [state & path] + (let [edit-id (get-in state [:workspace-local :edition]) + page-id (:current-page-id state)] + (cd/concat + (if edit-id + [:workspace-data :pages-index page-id :objects edit-id] + [:workspace-drawing :object]) + path))) + +(defn last-start-path [content] (->> content reverse - (d/seek (fn [{cmd :command}] (= cmd :move-to))) + (cd/seek (fn [{cmd :command}] (= cmd :move-to))) :params)) (defn next-node "Calculates the next-node to be inserted." [shape position prev-point prev-handler] (let [last-command (-> shape :content last :command) - start-point (-> shape :content seek-start-path) + start-point (-> shape :content last-start-path) add-line? (and prev-point (not prev-handler) (not= last-command :close-path)) - add-curve? (and prev-point prev-handler (not= last-command :close-path)) - close-path? (and start-point - (< (mth/abs (gpt/distance (gpt/point start-point) - (gpt/point position))) - close-path-distance))] + add-curve? (and prev-point prev-handler (not= last-command :close-path))] (cond - close-path? {:command :close-path - :params []} add-line? {:command :line-to :params position} add-curve? {:command :curve-to @@ -56,19 +66,24 @@ (defn append-node "Creates a new node in the path. Usualy used when drawing." [shape position prev-point prev-handler] - (let [command (next-node shape position prev-point prev-handler)] - (as-> shape $ - (update $ :content (fnil conj []) command) - (update $ :selrect (gsh/content->selrect (:content $)))))) + (let [command (next-node shape position prev-point prev-handler) + content (:content shape []) + content (conj content command)] + (-> shape + (assoc :content content) + (assoc :selrect (gsh/content->selrect content)) + ;; TODO: REMOVE POINTS + (assoc :points (gsh/content->points content))))) -(defn suffix-keyword [kw suffix] +(defn suffix-keyword + [kw suffix] (let [strkw (if kw (name kw) "")] (keyword (str strkw suffix)))) -;; handler-type => :prev :next -(defn move-handler [shape index handler-type match-opposite? position] +(defn move-handler + [shape index handler-type match-opposite? position] (let [content (:content shape) - [command next-command] (-> (d/with-next content) (nth index)) + [command next-command] (-> (ud/with-next content) (nth index)) update-command (fn [{cmd :command params :params :as command} param-prefix prev-command] @@ -86,9 +101,11 @@ update-content (fn [shape index prefix] (if (contains? (:content shape) index) - (let [prev-command (get-in shape [:content (dec index)])] - (update-in shape [:content index] update-command prefix prev-command)) - + (let [prev-command (get-in shape [:content (dec index)]) + content (-> shape :content (update index update-command prefix prev-command))] + (-> shape + (assoc :content content) + (assoc :selrect (gsh/content->selrect content)))) shape))] (cond-> shape @@ -106,102 +123,94 @@ (ugp/opposite-handler (gpt/point (:params command)) (gpt/point position)))))) - -;;;; -(defn finish-event? [{:keys [type shift] :as event}] - (or (= event ::end-path-drawing) - (= event :interrupt) +(defn end-path-event? [{:keys [type shift] :as event}] + (or (= event ::end-path) + (= (ptk/type event) :esc-pressed) + (= event :interrupt) ;; ESC (and (ms/keyboard-event? event) (= type :down) - (= 13 (:key event))))) - -#_(defn init-path [] - (fn [state] - (update-in state [:workspace-drawing :object] - assoc :content [] - :initialized? true))) - -#_(defn add-path-command [command] - (fn [state] - (update-in state [:workspace-drawing :object :content] conj command))) - -#_(defn update-point-segment [state index point] - (let [segments (count (get-in state [:workspace-drawing :object :segments])) - exists? (< -1 index segments)] - (cond-> state - exists? (assoc-in [:workspace-drawing :object :segments index] point)))) - -#_(defn finish-drawing-path [] - (fn [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] (-> shape - (update :segments #(vec (butlast %))) - (gsh/update-path-selrect)))))) - + ;; TODO: Enter now finish path but can finish drawing/editing as well + (= enter-keycode (:key event))))) (defn calculate-selrect [shape] (assoc shape :points (gsh/content->points (:content shape)) :selrect (gsh/content->selrect (:content shape)))) -(defn init-path [] + +;; EVENTS + +(defn init-path [id] (ptk/reify ::init-path ptk/UpdateEvent (update [_ state] (-> state - (assoc-in [:workspace-drawing :object :initialized?] true) - (assoc-in [:workspace-local :edit-path :last-point] nil))))) + #_(assoc-in [:workspace-drawing :object :initialized?] true) + #_(assoc-in [:workspace-local :edit-path :last-point] nil))))) -(defn finish-path [] +(defn finish-path [id] (ptk/reify ::finish-path ptk/UpdateEvent (update [_ state] (-> state - (update :workspace-local dissoc :edit-path) - (update-in [:workspace-drawing :object] calculate-selrect))))) + (update-in [:workspace-local :edit-path id] dissoc :last-point :prev-handler :drag-handler :preview))))) (defn preview-next-point [{:keys [x y]}] - (ptk/reify ::add-node + (ptk/reify ::preview-next-point ptk/UpdateEvent (update [_ state] - (let [position (gpt/point x y) - {:keys [last-point prev-handler] :as shape} (get-in state [:workspace-local :edit-path]) + (let [id (get-path-id state) + position (gpt/point x y) + shape (get-in state (get-path state)) + {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id]) + command (next-node shape position last-point prev-handler)] - (assoc-in state [:workspace-local :edit-path :preview] command))))) + (assoc-in state [:workspace-local :edit-path id :preview] command))))) (defn add-node [{:keys [x y]}] (ptk/reify ::add-node ptk/UpdateEvent (update [_ state] - - (let [position (gpt/point x y) - {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path])] + (let [id (get-path-id state) + position (gpt/point x y) + {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id])] (-> state - (assoc-in [:workspace-local :edit-path :last-point] position) - (update-in [:workspace-local :edit-path] dissoc :prev-handler) - (update-in [:workspace-drawing :object] append-node position last-point prev-handler)))))) + (assoc-in [:workspace-local :edit-path id :last-point] position) + (update-in [:workspace-local :edit-path id] dissoc :prev-handler) + (update-in (get-path state) append-node position last-point prev-handler)))))) (defn drag-handler [{:keys [x y]}] (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] - (let [position (gpt/point x y) - shape (get-in state [:workspace-drawing :object]) + (let [id (get-path-id state) + position (gpt/point x y) + shape (get-in state (get-path state)) index (dec (count (:content shape)))] (-> state - (update-in [:workspace-drawing :object] move-handler index :next true position) - (assoc-in [:workspace-local :edit-path :drag-handler] position)))))) + (update-in (get-path state) move-handler index :next true position) + (assoc-in [:workspace-local :edit-path id :prev-handler] position) + (assoc-in [:workspace-local :edit-path id :drag-handler] position)))))) (defn finish-drag [] (ptk/reify ::finish-drag ptk/UpdateEvent (update [_ state] - (let [handler (get-in state [:workspace-local :edit-path :drag-handler])] + (let [id (get-path-id state) + handler (get-in state [:workspace-local :edit-path id :drag-handler])] (-> state - (update-in [:workspace-local :edit-path] dissoc :drag-handler) - (assoc-in [:workspace-local :edit-path :prev-handler] handler)))))) + (update-in [:workspace-local :edit-path id] dissoc :drag-handler) + (assoc-in [:workspace-local :edit-path id :prev-handler] handler)))) + + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-path-id state) + handler (get-in state [:workspace-local :edit-path id :prev-handler])] + ;; Update the preview because can be outdated after the dragging + (rx/of (preview-next-point handler)))))) + +;; EVENT STREAMS (defn make-click-stream [stream down-event] @@ -230,26 +239,31 @@ (rx/first) (rx/merge-map #(rx/of (add-node down-event) - ::end-path-drawing)))) + ::end-path)))) -(defn handle-drawing-path [] +;; MAIN ENTRIES + +(defn handle-drawing-path + [id] (ptk/reify ::handle-drawing-path ptk/WatchEvent (watch [_ state stream] (let [mouse-down (->> stream (rx/filter ms/mouse-down?)) - finish-events (->> stream (rx/filter finish-event?)) + end-path-events (->> stream (rx/filter end-path-event?)) + ;; Mouse move preview mousemove-events (->> ms/mouse-position - (rx/take-until finish-events) - (rx/throttle 100) + (rx/take-until end-path-events) + (rx/throttle 50) (rx/map #(preview-next-point %))) + ;; From mouse down we can have: click, drag and double click mousedown-events (->> mouse-down - (rx/take-until finish-events) - (rx/throttle 100) + (rx/take-until end-path-events) + (rx/throttle 50) (rx/with-latest merge ms/mouse-position) ;; We change to the stream that emits the first event @@ -258,13 +272,13 @@ (make-drag-stream stream %) (make-dbl-click-stream stream %))))] + (->> (rx/concat + (rx/of (init-path id)) + (rx/merge mousemove-events + mousedown-events) + (rx/of (finish-path id)))))))) + - (rx/concat - (rx/of (init-path)) - (rx/merge mousemove-events - mousedown-events) - (rx/of (finish-path)) - (rx/of common/handle-finish-drawing)))))) #_(def handle-drawing-path (ptk/reify ::handle-drawing-path @@ -326,29 +340,25 @@ (rx/of finish-drawing-path common/handle-finish-drawing))))))) -#_(defn close-drawing-path [] - (ptk/reify ::close-drawing-path - ptk/UpdateEvent - (update [_ state] - (assoc-in state [:workspace-drawing :object :close?] true)) - - ptk/WatchEvent - (watch [_ state stream] - (rx/of ::end-path-drawing)))) - (defn stop-path-edit [] (ptk/reify ::stop-path-edit ptk/UpdateEvent (update [_ state] - (update state :workspace-local dissoc :edit-path)))) + (let [id (get-in state [:workspace-local :edition])] + (update state :workspace-local dissoc :edit-path id))))) (defn start-path-edit [id] (ptk/reify ::start-path-edit ptk/UpdateEvent (update [_ state] - (assoc-in state [:workspace-local :edit-path] {})) + ;; Only edit if the object has been created + (if-let [id (get-in state [:workspace-local :edition])] + (assoc-in state [:workspace-local :edit-path id] {:edit-mode :move + :selected #{} + :snap-toggled true}) + state)) ptk/WatchEvent (watch [_ state stream] @@ -362,40 +372,37 @@ ptk/UpdateEvent (update [_ state] - - (-> state - (update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc - :c1x dx :c1y dy) - (update-in [:workspace-local :edit-path :content-modifiers index] assoc - :x dx :y dy :c2x dx :c2y dy) - )))) + (let [id (get-in state [:workspace-local :edition])] + (-> state + (update-in [:workspace-local :edit-path id :content-modifiers (inc index)] assoc + :c1x dx :c1y dy) + (update-in [:workspace-local :edit-path id :content-modifiers index] assoc + :x dx :y dy :c2x dx :c2y dy) + ))))) (defn modify-handler [index type dx dy] (ptk/reify ::modify-point ptk/UpdateEvent (update [_ state] - (let [s1 (if (= type :prev) -1 1) - s2 (if (= type :prev) 1 -1)] - (-> state - (update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc - :c1x (* s1 dx) :c1y (* s1 dy)) - (update-in [:workspace-local :edit-path :content-modifiers index] assoc - :c2x (* s2 dx) :c2y (* s2 dy) )) - )))) + (let [id (get-in state [:workspace-local :edition])] + (let [s1 (if (= type :prev) -1 1) + s2 (if (= type :prev) 1 -1)] + (-> state + (update-in [:workspace-local :edit-path id :content-modifiers (inc index)] assoc + :c1x (* s1 dx) :c1y (* s1 dy)) + (update-in [:workspace-local :edit-path id :content-modifiers index] assoc + :c2x (* s2 dx) :c2y (* s2 dy) )) + ))))) (defn apply-content-modifiers [] (ptk/reify ::apply-content-modifiers - ;;ptk/UpdateEvent - ;;(update [_ state] - ;; (update-in state [:workspace-local :edit-path] dissoc :content-modifiers)) - ptk/WatchEvent (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) page-id (:current-page-id state) old-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) - content-modifiers (get-in state [:workspace-local :edit-path :content-modifiers]) + content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) new-content (gsp/apply-content-modifiers old-content content-modifiers) new-selrect (gsh/content->selrect new-content) rch [{:type :mod-obj @@ -411,16 +418,59 @@ {:type :set :attr :selrect :val old-selrect}]}]] (rx/of (dwc/commit-changes rch uch {:commit-local? true}) - (fn [state] (update-in state [:workspace-local :edit-path] dissoc :content-modifiers))))))) + (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers))))))) + +(defn save-path-content [] + (ptk/reify ::save-path-content + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-in state [:workspace-local :edition]) + page-id (:current-page-id state) + old-content (get-in state [:workspace-local :edit-path id :old-content]) + old-selrect (gsh/content->selrect old-content) + new-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) + new-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) + + rch [{:type :mod-obj + :id id + :page-id page-id + :operations [{:type :set :attr :content :val new-content} + {:type :set :attr :selrect :val new-selrect}]}] + + uch [{:type :mod-obj + :id id + :page-id page-id + :operations [{:type :set :attr :content :val old-content} + {:type :set :attr :selrect :val old-selrect}]}]] + + (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) + +(declare start-draw-mode) +(defn check-changed-content [] + (ptk/reify ::check-changed-content + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-path-id state) + content (get-in state (get-path state :content)) + old-content (get-in state [:workspace-local :edit-path id :old-content]) + mode (get-in state [:workspace-local :edit-path id :edit-mode])] + + + (cond + (not= content old-content) (rx/of (save-path-content) + (start-draw-mode)) + (= mode :draw) (rx/of :interrupt) + :else (rx/of (finish-path id))))))) (defn start-move-path-point [index] (ptk/reify ::start-move-path-point ptk/WatchEvent (watch [_ state stream] - (let [start-point @ms/mouse-position - start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers index :x] 0) - start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers index :y] 0)] + (let [id (get-in state [:workspace-local :edition]) + start-point @ms/mouse-position + start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers index :x] 0) + start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers index :y] 0)] (rx/concat (->> ms/mouse-position (rx/take-until (->> stream (rx/filter ms/mouse-up?))) @@ -436,12 +486,13 @@ (ptk/reify ::start-move-handler ptk/WatchEvent (watch [_ state stream] - (let [[cx cy] (if (= :prev type) [:c2x :c2y] [:c1x :c1y]) + (let [id (get-in state [:workspace-local :edition]) + [cx cy] (if (= :prev type) [:c2x :c2y] [:c1x :c1y]) cidx (if (= :prev type) index (inc index)) start-point @ms/mouse-position - start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers cidx cx] 0) - start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers cidx cy] 0)] + start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers cidx cx] 0) + start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers cidx cy] 0)] (rx/concat (->> ms/mouse-position @@ -453,3 +504,114 @@ (+ start-delta-y (- (:y %) (:y start-point))))) ) (rx/concat (rx/of (apply-content-modifiers)))))))) + +(defn start-draw-mode [] + (ptk/reify ::start-draw-mode + ptk/UpdateEvent + (update [_ state] + (let [id (get-in state [:workspace-local :edition]) + page-id (:current-page-id state) + old-content (get-in state [:workspace-data :pages-index page-id :objects id :content])] + (-> state + (assoc-in [:workspace-local :edit-path id :old-content] old-content)))) + + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-in state [:workspace-local :edition]) + edit-mode (get-in state [:workspace-local :edit-path id :edit-mode])] + (if (= :draw edit-mode) + (rx/concat + (rx/of (handle-drawing-path id)) + (->> stream + (rx/filter (ptk/type? ::finish-path)) + (rx/take 1) + (rx/merge-map #(rx/of (check-changed-content))))) + (rx/empty)))))) + +(defn change-edit-mode [mode] + (ptk/reify ::change-edit-mode + ptk/UpdateEvent + (update [_ state] + (let [id (get-in state [:workspace-local :edition])] + (cond-> state + id (assoc-in [:workspace-local :edit-path id :edit-mode] mode)))) + + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-path-id state)] + (cond + (and id (= :move mode)) (rx/of ::end-path) + (and id (= :draw mode)) (rx/of (start-draw-mode)) + :else (rx/empty)))))) + +(defn select-handler [index type] + (ptk/reify ::select-handler + ptk/UpdateEvent + (update [_ state] + (let [id (get-in state [:workspace-local :edition])] + (-> state + (update-in [:workspace-local :edit-path id :selected] (fnil conj #{}) [index type])))))) + +(defn select-node [index] + (ptk/reify ::select-node + ptk/UpdateEvent + (update [_ state] + (let [id (get-in state [:workspace-local :edition])] + (-> state + (update-in [:workspace-local :edit-path id :selected] (fnil conj #{}) index)))))) + +(defn add-to-selection-handler [index type] + (ptk/reify ::add-to-selection-handler + ptk/UpdateEvent + (update [_ state] + state))) + +(defn add-to-selection-node [index] + (ptk/reify ::add-to-selection-node + ptk/UpdateEvent + (update [_ state] + state))) + +(defn remove-from-selection-handler [index] + (ptk/reify ::remove-from-selection-handler + ptk/UpdateEvent + (update [_ state] + state))) + +(defn remove-from-selection-node [index] + (ptk/reify ::remove-from-selection-handler + ptk/UpdateEvent + (update [_ state] + state))) + +(defn handle-new-shape-result [shape-id] + (ptk/reify ::handle-new-shape-result + ptk/UpdateEvent + (update [_ state] + (let [content (get-in state [:workspace-drawing :object :content] [])] + (if (> (count content) 1) + (assoc-in state [:workspace-drawing :object :initialized?] true) + state))) + + ptk/WatchEvent + (watch [_ state stream] + (->> (rx/of common/handle-finish-drawing + (dwc/start-edition-mode shape-id) + (start-path-edit shape-id) + (change-edit-mode :draw)))))) + +(defn handle-new-shape + "Creates a new path shape" + [] + (ptk/reify ::handle-new-shape + ptk/WatchEvent + (watch [_ state stream] + (let [shape-id (get-in state [:workspace-drawing :object :id])] + (rx/concat + (rx/of (handle-drawing-path shape-id)) + (->> stream + (rx/filter (ptk/type? ::finish-path)) + (rx/take 1) + (rx/observe-on :async) + (rx/map #(handle-new-shape-result shape-id))) + ))))) diff --git a/frontend/src/app/main/ui/cursors.clj b/frontend/src/app/main/ui/cursors.clj index 414297d112..d7ed83b71d 100644 --- a/frontend/src/app/main/ui/cursors.clj +++ b/frontend/src/app/main/ui/cursors.clj @@ -19,6 +19,7 @@ (def default-hotspot-x 12) (def default-hotspot-y 12) (def default-rotation 0) +(def default-height 20) (defn parse-svg [svg-data] (-> svg-data @@ -53,25 +54,27 @@ (str/replace #"\s+$" ""))) (defn encode-svg-cursor - [id rotation x y] + [id rotation x y height] (let [svg-path (str cursor-folder "/" (name id) ".svg") data (-> svg-path io/resource slurp parse-svg uri/percent-encode) transform (if rotation (str " transform='rotate(" rotation ")'") "") data (clojure.pprint/cl-format nil - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' height='20px'~A%3E~A%3C/svg%3E\") ~A ~A, auto" - transform data x y)] + "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' height='~Apx'~A%3E~A%3C/svg%3E\") ~A ~A, auto" + height transform data x y )] data)) (defmacro cursor-ref "Creates a static cursor given its name, rotation and x/y hotspot" - ([id] (encode-svg-cursor id default-rotation default-hotspot-x default-hotspot-y)) - ([id rotation] (encode-svg-cursor id rotation default-hotspot-x default-hotspot-y)) - ([id rotation x y] (encode-svg-cursor id rotation x y))) + ([id] (encode-svg-cursor id default-rotation default-hotspot-x default-hotspot-y default-height)) + ([id rotation] (encode-svg-cursor id rotation default-hotspot-x default-hotspot-y default-height)) + ([id rotation x y] (encode-svg-cursor id rotation x y default-height)) + ([id rotation x y height] (encode-svg-cursor id rotation x y height)) + ) (defmacro cursor-fn "Creates a dynamic cursor that can be rotated in runtime" [id initial] - (let [cursor (encode-svg-cursor id "{{rotation}}" default-hotspot-x default-hotspot-y)] + (let [cursor (encode-svg-cursor id "{{rotation}}" default-hotspot-x default-hotspot-y default-height)] `(fn [rot#] (str/replace ~cursor "{{rotation}}" (+ ~initial rot#))))) diff --git a/frontend/src/app/main/ui/cursors.cljs b/frontend/src/app/main/ui/cursors.cljs index f7dd21feda..bc60deba4c 100644 --- a/frontend/src/app/main/ui/cursors.cljs +++ b/frontend/src/app/main/ui/cursors.cljs @@ -8,8 +8,7 @@ ;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.ui.cursors - (:require-macros [app.main.ui.cursors :refer [cursor-ref - cursor-fn]]) + (:require-macros [app.main.ui.cursors :refer [cursor-ref cursor-fn]]) (:require [rumext.alpha :as mf] [cuerdas.core :as str] [app.util.timers :as ts])) @@ -33,6 +32,9 @@ (def rotate (cursor-fn :rotate 90)) (def text (cursor-ref :text)) (def picker (cursor-ref :picker 0 0 24)) +(def pointer-node (cursor-ref :pointer-node 0 0 10 32)) +(def pointer-move (cursor-ref :pointer-move 0 0 10 42)) +(def pen-node (cursor-ref :pen-node 0 0 10 36)) (mf/defc debug-preview {::mf/wrap-props false} @@ -49,8 +51,11 @@ [:div {:style {:width "100px" :height "100px" :background-image (-> value (str/replace #"(url\(.*\)).*" "$1")) - :background-size "cover" + :background-size "contain" + :background-repeat "no-repeat" + :background-position "center" :cursor value}}] [:span {:style {:white-space "nowrap" :margin-right "1rem"}} (pr-str key)]])))])) + diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs index 0550c4a4a1..f620afd849 100644 --- a/frontend/src/app/main/ui/icons.cljs +++ b/frontend/src/app/main/ui/icons.cljs @@ -136,6 +136,8 @@ (def nodes-remove (icon-xref :nodes-remove)) (def nodes-separate (icon-xref :nodes-separate)) (def nodes-snap (icon-xref :nodes-snap)) +(def pen (icon-xref :pen)) +(def pointer-inner (icon-xref :pointer-inner)) (def loader-pencil (mf/html diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 5f9708a581..cdd1040910 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -368,8 +368,8 @@ :zoom zoom :color color}] - (= (= type :path) - (= edition (:id shape))) + (and (= type :path) + (= edition (:id shape))) [:& path-editor {:zoom zoom :shape shape}] diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index d1665317ba..1d84fa6203 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -110,7 +110,6 @@ (mf/use-callback (mf/deps (:id shape)) (fn [event] - (prn "?? FRAME") (dom/prevent-default event) (st/emit! (dw/deselect-all) (dw/select-shape (:id shape))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 338a45f799..9396aca1fb 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -39,11 +39,25 @@ (def white-color "#FFFFFF") (def gray-color "#B1B2B5") -(def edit-path-ref - (l/derived :edit-path refs/workspace-local)) -(def content-modifiers-ref - (l/derived :content-modifiers edit-path-ref)) + +(def current-edit-path-ref + (let [selfn (fn [local] + (let [id (:edition local)] + (get-in local [:edit-path id])))] + (l/derived selfn refs/workspace-local))) + +(defn make-edit-path-ref [id] + (mf/use-memo + (mf/deps id) + (let [selfn #(get-in % [:edit-path id])] + #(l/derived selfn refs/workspace-local)))) + +(defn make-content-modifiers-ref [id] + (mf/use-memo + (mf/deps id) + (let [selfn #(get-in % [:edit-path id :content-modifiers])] + #(l/derived selfn refs/workspace-local)))) (mf/defc path-wrapper {::mf/wrap-props false} @@ -67,11 +81,14 @@ (dom/prevent-default event) (st/emit! (dw/start-edition-mode (:id shape)) (dw/start-path-edit (:id shape))))))) - + content-modifiers-ref (make-content-modifiers-ref (:id shape)) content-modifiers (mf/deref content-modifiers-ref) + editing-id (mf/deref refs/selected-edition) + editing? (= editing-id (:id shape)) shape (update shape :content gsp/apply-content-modifiers content-modifiers)] [:> shape-container {:shape shape + :pointer-events (when editing? "none") :on-double-click on-double-click :on-mouse-down on-mouse-down :on-context-menu on-context-menu} @@ -79,22 +96,30 @@ :background? true}]])) (mf/defc path-actions [{:keys [shape]}] - [:div.path-actions - [:div.viewport-actions-group - [:div.viewport-actions-entry i/nodes-add] - [:div.viewport-actions-entry i/nodes-remove]] + (let [id (mf/deref refs/selected-edition) + {:keys [edit-mode selected snap-toggled] :as all} (mf/deref current-edit-path-ref)] + [:div.path-actions + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class (when (= edit-mode :draw) "is-toggled") + :on-click #(st/emit! (drp/change-edit-mode :draw))} i/pen] + [:div.viewport-actions-entry {:class (when (= edit-mode :move) "is-toggled") + :on-click #(st/emit! (drp/change-edit-mode :move))} i/pointer-inner]] + + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-add] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-remove]] - [:div.viewport-actions-group - [:div.viewport-actions-entry i/nodes-merge] - [:div.viewport-actions-entry i/nodes-join] - [:div.viewport-actions-entry i/nodes-separate]] + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-merge] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-join] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-separate]] - [:div.viewport-actions-group - [:div.viewport-actions-entry i/nodes-corner] - [:div.viewport-actions-entry i/nodes-curve]] + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-corner] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-curve]] - [:div.viewport-actions-group - [:div.viewport-actions-entry i/nodes-snap]]]) + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class (when snap-toggled "is-toggled")} i/nodes-snap]]])) (mf/defc path-preview [{:keys [zoom command from]}] @@ -107,36 +132,58 @@ :y (:y from)}} command])}])) -(mf/defc path-point [{:keys [index position stroke-color fill-color zoom]}] +(mf/defc path-point [{:keys [index position stroke-color fill-color zoom edit-mode selected]}] (let [{:keys [x y]} position on-click (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event)) - on-mouse-down (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (drp/start-move-path-point index)))] - [:circle - {:cx x - :cy y - :r (/ 3 zoom) - :on-click on-click - :on-mouse-down on-mouse-down - :style {:cursor cur/resize-alt - :stroke-width (/ 1 zoom) - :stroke (or stroke-color black-color) - :fill (or fill-color white-color)}}])) + (cond + (= edit-mode :move) + (do + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (drp/select-node index))))) -(mf/defc path-handler [{:keys [index point handler zoom selected type]}] + on-mouse-down (fn [event] + (cond + (= edit-mode :move) + (do + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (drp/start-move-path-point index)))))] + [:g.path-point + [:circle.path-point + {:cx x + :cy y + :r (/ 3 zoom) + :style { ;; :cursor cur/resize-alt + :stroke-width (/ 1 zoom) + :stroke (or stroke-color black-color) + :fill (or fill-color white-color)}}] + [:circle {:cx x + :cy y + :r (/ 10 zoom) + :on-click on-click + :on-mouse-down on-mouse-down + :style {:fill "transparent"}}]] + )) + +(mf/defc path-handler [{:keys [index point handler zoom selected type edit-mode]}] (when (and point handler) (let [{:keys [x y]} handler on-click (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event)) + (cond + (= edit-mode :move) + (do + (dom/stop-propagation event) + (dom/prevent-default event) + (drp/select-handler index type)))) + on-mouse-down (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (drp/start-move-handler index type)))] + (cond + (= edit-mode :move) + (do + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (drp/start-move-handler index type)))))] [:g.handler {:class (name type)} [:line {:x1 (:x point) @@ -150,23 +197,30 @@ :y (- y (/ 3 zoom)) :width (/ 6 zoom) :height (/ 6 zoom) - :on-click on-click - :on-mouse-down on-mouse-down - :style {:cursor cur/resize-alt + + :style {;; :cursor cur/resize-alt :stroke-width (/ 1 zoom) :stroke (if selected black-color primary-color) - :fill (if selected primary-color white-color)}}]]))) + :fill (if selected primary-color white-color)}}] + + [:circle {:cx x + :cy y + :r (/ 10 zoom) + :on-click on-click + :on-mouse-down on-mouse-down + :style {:fill "transparent"}}]]))) (mf/defc path-editor [{:keys [shape zoom]}] (let [{:keys [content]} shape - {:keys [drag-handler prev-handler preview content-modifiers]} (mf/deref edit-path-ref) + edit-path-ref (make-edit-path-ref (:id shape)) + {:keys [edit-mode selected drag-handler prev-handler preview content-modifiers]} (mf/deref edit-path-ref) + selected (or selected #{}) content (gsp/apply-content-modifiers content content-modifiers) points (gsp/content->points content) last-command (last content) - last-p (last points) - selected false] + last-p (last points)] [:g.path-editor (when (and preview (not drag-handler)) @@ -187,7 +241,8 @@ :zoom zoom :type :prev :index index - :selected false}]) + :selected (selected [index :prev]) + :edit-mode edit-mode}]) (when (= :curve-to (:command next)) [:& path-handler {:point point @@ -195,7 +250,8 @@ :zoom zoom :type :next :index index - :selected false}]) + :selected (selected [index :next]) + :edit-mode edit-mode}]) (when (and (= index (dec (count content))) prev-handler (not drag-handler)) @@ -204,13 +260,15 @@ :zoom zoom :type :prev :index index - :selected false}]) + :selected (selected index) + :edit-mode edit-mode}]) [:& path-point {:position point - :stroke-color (when-not selected primary-color) - :fill-color (when selected primary-color) + :stroke-color (when-not (selected index) primary-color) + :fill-color (when (selected index) primary-color) :index index - :zoom zoom}]])) + :zoom zoom + :edit-mode edit-mode}]])) (when drag-handler [:g.drag-handler diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 547ceb36c1..fc07ba6dbc 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -199,6 +199,7 @@ vport vbox edition + edit-path tooltip selected panning @@ -221,6 +222,7 @@ drawing (mf/deref refs/workspace-drawing) drawing-tool (:tool drawing) drawing-obj (:object drawing) + drawing-path? (and edition (= :draw (get-in edit-path [edition :edit-mode]))) zoom (or zoom 1) on-mouse-down @@ -292,7 +294,7 @@ on-double-click (mf/use-callback - (mf/deps edition) + (mf/deps edition edit-path) (fn [event] (dom/stop-propagation event) (let [ctrl? (kbd/ctrl? event) @@ -300,7 +302,7 @@ alt? (kbd/alt? event)] (st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?)) - (if edition + (if (not drawing-path?) (st/emit! dw/clear-edition-mode))))) on-key-down @@ -431,6 +433,7 @@ final-x (- (:x viewport-coord) (/ (:width shape) 2)) final-y (- (:y viewport-coord) (/ (:height shape) 2))] (st/emit! (dw/add-shape (-> shape + (assoc :id (uuid/next)) (assoc :x final-x) (assoc :y final-y))))) @@ -537,7 +540,7 @@ (= drawing-tool :frame) cur/create-artboard (= drawing-tool :rect) cur/create-rectangle (= drawing-tool :circle) cur/create-ellipse - (= drawing-tool :path) cur/pen + (or (= drawing-tool :path) drawing-path?) cur/pen (= drawing-tool :curve)cur/pencil drawing-tool cur/create-shape :else cur/pointer-inner) From 55b71a111b210eb6ce2b214d2a1fc737ecb01068 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 19 Nov 2020 16:45:39 +0100 Subject: [PATCH 055/195] :bug: Fixes problems with transforms --- common/app/common/geom/shapes.cljc | 11 +--- common/app/common/geom/shapes/transforms.cljc | 59 ++++++++----------- common/app/common/math.cljc | 2 +- common/app/common/pages.cljc | 6 +- .../app/main/data/workspace/drawing/path.cljs | 50 ++++++++++------ .../src/app/main/ui/workspace/selection.cljs | 5 +- 6 files changed, 68 insertions(+), 65 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index cfe5314022..d61bd6689f 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -157,7 +157,8 @@ rotation of each shape. Mainly used for multiple selection." [shapes] (->> shapes - (map :selrect) + (gtr/transform-shape) + (map (comp gpr/points->selrect :points)) (gpr/join-selrects))) (defn translate-to-frame @@ -288,15 +289,9 @@ (defn center-rect [rect] (gco/center-rect rect)) (defn rect->selrect [rect] (gpr/rect->selrect rect)) - -#_(def shape->rect-shape gpr/shape->rect-shape) -#_(def fix-invalid-rect-values gtr/fix-invalid-rect-values) -#_(def rect->rect-shape gpr/rect->rect-shape) +(defn rect->points [rect] (gpr/rect->points rect)) (defn points->selrect [points] (gpr/points->selrect points)) -#_(def transform-shape-point gtr/transform-shape-point) -#_(def update-path-selrect gtr/update-path-selrect) -#_(def transform gtr/transform) (defn transform-shape [shape] (gtr/transform-shape shape)) (defn transform-matrix [shape] (gtr/transform-matrix shape)) (defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index d2ff83aec9..5e2806bcb9 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -108,6 +108,8 @@ resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) rt-modif (or (:rotation modifiers) 0) + center (gpt/transform center ds-modifier) + transform (-> (gmt/matrix) ;; Applies the current resize transformation @@ -120,7 +122,6 @@ ;; Applies the stacked transformations (gmt/translate center) (gmt/multiply (gmt/rotate-matrix rt-modif)) - #_(gmt/multiply current-transform) (gmt/translate (gpt/negate center)) ;; Displacement @@ -186,7 +187,7 @@ stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) h1 (calculate-height points-temp) - h2 (calculate-height (transform-points points-temp center stretch-matrix)) + h2 (calculate-height (transform-points points-rec center stretch-matrix)) h3 (/ h1 h2) h3 (if (mth/nan? h3) 1 h3) @@ -200,15 +201,10 @@ stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) - stretch-matrix (-> (gmt/matrix) - (gmt/rotate rotation-angle) - (gmt/skew skew-angle 0) - (gmt/scale (gpt/point 1 h3))) - ;; This is the inverse to be able to remove the transformation stretch-matrix-inverse (-> (gmt/matrix) - (gmt/scale (gpt/point 1 h3)) + (gmt/scale (gpt/point 1 (/ 1 h3))) (gmt/skew (- skew-angle) 0) (gmt/rotate (- rotation-angle)))] [stretch-matrix stretch-matrix-inverse])) @@ -217,17 +213,15 @@ (defn apply-transform-path [shape transform] (let [content (gpa/transform-content (:content shape) transform) - points (gpa/content->points content) + selrect (gpa/content->selrect content) + points (gpr/rect->points selrect) rotation (mod (+ (:rotation shape 0) (or (get-in shape [:modifiers :rotation]) 0)) - 360) - selrect (gpa/content->selrect content)] + 360)] (assoc shape :content content :points points - :selrect selrect - ;;:rotation rotation - ))) + :selrect selrect))) (defn apply-transform-curve [shape transform] @@ -255,22 +249,19 @@ (:height points-temp-dim)) rect-points (gpr/rect->points rect-shape) - [matrix matrix-inverse] (calculate-adjust-matrix points-temp rect-points (:flip-x shape) (:flip-y shape)) - ;;[matrix matrix-inverse] [(gmt/matrix) (gmt/matrix)] - - new-shape (as-> shape $ - (merge $ rect-shape) - (update $ :x #(mth/precision % 0)) - (update $ :y #(mth/precision % 0)) - (update $ :width #(mth/precision % 0)) - (update $ :height #(mth/precision % 0)) - (update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix)) - (update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix)))) - (assoc $ :points (into [] points)) - (assoc $ :selrect (gpr/rect->selrect rect-shape)) - (update $ :rotation #(mod (+ (or % 0) - (or (get-in $ [:modifiers :rotation]) 0)) 360)))] - new-shape)) + [matrix matrix-inverse] (calculate-adjust-matrix points-temp rect-points (:flip-x shape) (:flip-y shape))] + (as-> shape $ + (merge $ rect-shape) + (update $ :x #(mth/precision % 0)) + (update $ :y #(mth/precision % 0)) + (update $ :width #(mth/precision % 0)) + (update $ :height #(mth/precision % 0)) + (update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix)) + (update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix)))) + (assoc $ :points (into [] points)) + (assoc $ :selrect (gpr/rect->selrect rect-shape)) + (update $ :rotation #(mod (+ (or % 0) + (or (get-in $ [:modifiers :rotation]) 0)) 360))))) (defn apply-transform [shape transform] (let [apply-transform-fn @@ -281,9 +272,11 @@ (apply-transform-fn shape transform))) (defn set-flip [shape modifiers] - (cond-> shape - (< (get-in modifiers [:resize-vector :x]) 0) (update :flip-x not) - (< (get-in modifiers [:resize-vector :y]) 0) (update :flip-y not))) + (let [rx (get-in modifiers [:resize-vector :x]) + ry (get-in modifiers [:resize-vector :y])] + (cond-> shape + (and rx (< rx 0)) (update :flip-x not) + (and ry (< ry 0)) (update :flip-y not)))) (defn transform-shape [shape] (let [center (gco/center-shape shape)] diff --git a/common/app/common/math.cljc b/common/app/common/math.cljc index f9baa33870..dd16c402e9 100644 --- a/common/app/common/math.cljc +++ b/common/app/common/math.cljc @@ -24,7 +24,7 @@ (defn finite? [v] #?(:cljs (and (not (nil? v)) (js/isFinite v)) - :clj (Double/isFinite v))) + :clj (and (not (nil? v)) (Double/isFinite v)))) (defn abs [v] diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 491b1fc789..913128a0e2 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -798,10 +798,10 @@ ;; Rotate the group shape change the data and rotate back again (-> group - (assoc-in [:modifiers :rotation] (- (:rotation group 0))) - (geom/transform-shape) + (assoc :selrect selrect) + (assoc :points (geom/rect->points selrect)) (merge (select-keys selrect [:x :y :width :height])) - (assoc-in [:modifiers :rotation] (:rotation group)) + (assoc-in [:modifiers :rotation] (:rotation group 0)) (geom/transform-shape))))] (d/update-in-when data [:pages-index page-id :objects] reg-objects))) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 2ac40bf29c..8dec5b402a 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -47,6 +47,11 @@ (cd/seek (fn [{cmd :command}] (= cmd :move-to))) :params)) +(defn update-selrect [shape] + (let [selrect (gsh/content->selrect (:content shape)) + points (gsh/rect->points selrect)] + (assoc shape :points points :selrect selrect))) + (defn next-node "Calculates the next-node to be inserted." [shape position prev-point prev-handler] @@ -66,14 +71,10 @@ (defn append-node "Creates a new node in the path. Usualy used when drawing." [shape position prev-point prev-handler] - (let [command (next-node shape position prev-point prev-handler) - content (:content shape []) - content (conj content command)] + (let [command (next-node shape position prev-point prev-handler)] (-> shape - (assoc :content content) - (assoc :selrect (gsh/content->selrect content)) - ;; TODO: REMOVE POINTS - (assoc :points (gsh/content->points content))))) + (update :content (fnil conj []) command) + (update-selrect)))) (defn suffix-keyword [kw suffix] @@ -105,7 +106,7 @@ content (-> shape :content (update index update-command prefix prev-command))] (-> shape (assoc :content content) - (assoc :selrect (gsh/content->selrect content)))) + (update-selrect))) shape))] (cond-> shape @@ -132,11 +133,6 @@ ;; TODO: Enter now finish path but can finish drawing/editing as well (= enter-keycode (:key event))))) -(defn calculate-selrect [shape] - (assoc shape - :points (gsh/content->points (:content shape)) - :selrect (gsh/content->selrect (:content shape)))) - ;; EVENTS @@ -402,20 +398,30 @@ page-id (:current-page-id state) old-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) + old-points (get-in state [:workspace-data :pages-index page-id :objects id :points]) content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) new-content (gsp/apply-content-modifiers old-content content-modifiers) new-selrect (gsh/content->selrect new-content) + new-points (gsh/rect->points new-selrect) rch [{:type :mod-obj :id id :page-id page-id :operations [{:type :set :attr :content :val new-content} - {:type :set :attr :selrect :val new-selrect}]}] + {:type :set :attr :selrect :val new-selrect} + {:type :set :attr :points :val new-points}]} + {:type :reg-objects + :page-id page-id + :shapes [id]}] uch [{:type :mod-obj :id id :page-id page-id :operations [{:type :set :attr :content :val old-content} - {:type :set :attr :selrect :val old-selrect}]}]] + {:type :set :attr :selrect :val old-selrect} + {:type :set :attr :points :val old-points}]} + {:type :reg-objects + :page-id page-id + :shapes [id]}]] (rx/of (dwc/commit-changes rch uch {:commit-local? true}) (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers))))))) @@ -428,20 +434,30 @@ page-id (:current-page-id state) old-content (get-in state [:workspace-local :edit-path id :old-content]) old-selrect (gsh/content->selrect old-content) + old-points (gsh/rect->points old-content) new-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) new-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) + new-points (get-in state [:workspace-data :pages-index page-id :objects id :points]) rch [{:type :mod-obj :id id :page-id page-id :operations [{:type :set :attr :content :val new-content} - {:type :set :attr :selrect :val new-selrect}]}] + {:type :set :attr :selrect :val new-selrect} + {:type :set :attr :points :val new-points}]} + {:type :reg-objects + :page-id page-id + :shapes [id]}] uch [{:type :mod-obj :id id :page-id page-id :operations [{:type :set :attr :content :val old-content} - {:type :set :attr :selrect :val old-selrect}]}]] + {:type :set :attr :selrect :val old-selrect} + {:type :set :attr :points :val old-points}]} + {:type :reg-objects + :page-id page-id + :shapes [id]}]] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index cdd1040910..90443b15ce 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -270,7 +270,7 @@ (mf/defc multiple-selection-handlers [{:keys [shapes selected zoom color show-distances] :as props}] - (let [shape (geom/setup {:type :rect} (geom/selection-rect shapes)) + (let [shape (geom/setup {:type :rect} (geom/selection-rect (->> shapes (map geom/transform-shape)))) shape-center (geom/center-shape shape) hover-id (-> (mf/deref refs/current-hover) first) @@ -315,7 +315,7 @@ hover-id (when-not (= shape-id hover-id) hover-id) hover-shape (mf/deref (refs/object-by-id hover-id)) - shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape) + shape' (if (debug? :simple-selection) (geom/setup {:type :rect} (geom/selection-rect [shape])) shape) on-resize (fn [current-position initial-position event] (dom/stop-propagation event) (st/emit! (dw/start-resize current-position initial-position #{shape-id} shape'))) @@ -323,7 +323,6 @@ on-rotate #(do (dom/stop-propagation %) (st/emit! (dw/start-rotate [shape])))] - [:* [:& controls {:shape shape' :zoom zoom From e2593c2dad33e15a3229317591bb179228f3b57a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 19 Nov 2020 18:12:15 +0100 Subject: [PATCH 056/195] :recycle: Removed curves shapes --- common/app/common/geom/shapes.cljc | 44 +-- common/app/common/geom/shapes/common.cljc | 38 +-- common/app/common/geom/shapes/rect.cljc | 67 ----- common/app/common/geom/shapes/transforms.cljc | 262 ------------------ common/app/common/pages.cljc | 17 +- .../src/app/main/data/workspace/drawing.cljs | 2 - .../main/data/workspace/drawing/curve.cljs | 15 +- .../app/main/data/workspace/transforms.cljs | 2 +- frontend/src/app/main/exports.cljs | 1 - .../src/app/main/ui/handoff/attributes.cljs | 1 - frontend/src/app/main/ui/handoff/render.cljs | 1 - frontend/src/app/main/ui/viewer/shapes.cljs | 1 - .../src/app/main/ui/workspace/drawarea.cljs | 28 -- .../src/app/main/ui/workspace/selection.cljs | 44 --- .../src/app/main/ui/workspace/shapes.cljs | 1 - .../app/main/ui/workspace/shapes/outline.cljs | 4 +- .../main/ui/workspace/sidebar/history.cljs | 3 +- .../app/main/ui/workspace/sidebar/layers.cljs | 1 - .../main/ui/workspace/sidebar/options.cljs | 1 - frontend/src/app/util/geom/path.cljs | 15 + frontend/src/app/util/geom/snap_points.cljs | 4 +- 21 files changed, 41 insertions(+), 511 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index d61bd6689f..325f9e6343 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -30,24 +30,7 @@ dy (d/check-num dy)] (-> shape (assoc-in [:modifiers :displacement] (gmt/translate-matrix (gpt/point dx dy))) - (gtr/transform-shape))) - - #_(let [inc-x (nilf (fn [x] (+ (-chk x) (-chk dx)))) - inc-y (nilf (fn [y] (+ (-chk y) (-chk dy)))) - inc-point (nilf (fn [p] (-> p - (update :x inc-x) - (update :y inc-y))))] - (-> shape - (update :x inc-x) - (update :y inc-y) - (update-in [:selrect :x] inc-x) - (update-in [:selrect :x1] inc-x) - (update-in [:selrect :x2] inc-x) - (update-in [:selrect :y] inc-y) - (update-in [:selrect :y1] inc-y) - (update-in [:selrect :y2] inc-y) - (update :points #(mapv inc-point %)) - (update :segments #(mapv inc-point %))))) + (gtr/transform-shape)))) ;; --- Absolute Movement @@ -60,17 +43,6 @@ dy (- (d/check-num y) (-> shape :selrect :y))] (move shape (gpt/point dx dy)))) -;; --- Paths - -#_(defn update-path-point - "Update a concrete point in the path. - - The point should exists before, this function - does not adds it automatically." - [shape index point] - (assoc-in shape [:segments index] point)) - - ;; --- Resize (Dimensions) ;;; TODO: CHANGE TO USE THE MODIFIERS (defn resize @@ -136,20 +108,6 @@ :image (setup-image shape props) (setup-rect shape props))) -;; --- Resolve Shape - -;; (declare resolve-rect-shape) -;; (declare translate-from-frame) -;; (declare translate-to-frame) -;; -;; (defn resolve-shape -;; [objects shape] -;; (loop [pobj (get objects parent)] -;; (if (= :frame (:type pobj)) -;; (translate-from-frame shape pobj) -;; (recur (get objects (:parent pobj)))))) - - ;; --- Outer Rect (defn selection-rect diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index 1642663729..ba3b83527e 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -30,11 +30,6 @@ [selrect] (center-rect selrect)) -(defn center-shape - "Calculate the center of the shape." - [shape] - (center-rect (:selrect shape))) - (defn center-points [points] (let [minx (transduce (map :x) min ##Inf points) miny (transduce (map :y) min ##Inf points) @@ -43,6 +38,11 @@ (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) +(defn center-shape + "Calculate the center of the shape." + [shape] + (center-rect (:selrect shape))) + (defn make-centered-rect "Creates a rect given a center and a width and height" [center width height] @@ -50,31 +50,3 @@ :y (- (:y center) (/ height 2)) :width width :height height}) - -;; --- Center -#_( - (declare center-rect) - (declare center-path) - - - - - - (defn- center-path - [{:keys [segments] :as shape}] - (let [minx (apply min (map :x segments)) - miny (apply min (map :y segments)) - maxx (apply max (map :x segments)) - maxy (apply max (map :y segments))] - (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) - - (defn center->rect - "Creates a rect given a center and a width and height" - [center width height] - {:x (- (:x center) (/ width 2)) - :y (- (:y center) (/ height 2)) - :width width - :height height}) - - - ) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index 47f6543dc9..9cd0979962 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -58,70 +58,3 @@ :width (- maxx minx) :height (- maxy miny)})) -;; --- SHAPE -> RECT -#_( - (defn- rect->rect-shape - [{:keys [x y width height] :as shape}] - (assoc shape - :x1 x - :y1 y - :x2 (+ x width) - :y2 (+ y height))) - - (defn- path->rect-shape - [{:keys [segments] :as shape}] - (merge shape - {:type :rect} - (:selrect shape))) - - (defn shape->rect-shape - "Coerce shape to rect like shape." - - [{:keys [type] :as shape}] - (case type - (:curve :path) (path->rect-shape shape) - (rect->rect-shape shape))) - - ;; Shape->PATH - - (declare rect->path) - - (defn shape->path - [shape] - (case (:type shape) - (:curve :path) shape - (rect->path shape))) - - (defn rect->path - [{:keys [x y width height] :as shape}] - - (let [points [(gpt/point x y) - (gpt/point (+ x width) y) - (gpt/point (+ x width) (+ y height)) - (gpt/point x (+ y height)) - (gpt/point x y)]] - (-> shape - (assoc :type :path) - (assoc :segments points)))) - - ;; -- Points - - (defn points->selrect [points] - (let [minx (transduce (map :x) min ##Inf points) - miny (transduce (map :y) min ##Inf points) - maxx (transduce (map :x) max ##-Inf points) - maxy (transduce (map :y) max ##-Inf points)] - {:x1 minx - :y1 miny - :x2 maxx - :y2 maxy - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny) - :type :rect})) - - - - - ) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 5e2806bcb9..ec5e51f4ac 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -60,26 +60,6 @@ (transform-points matrix))] (gpr/points->rect points))) - -(defn- shape->points [shape] - (let [transform-point - (fn [point] - (-> point - (transform-point-center (gco/center-shape shape) - (:transform shape (gmt/matrix))) - (gpt/round))) - - points (cond - (and (= :path (:type shape)) (:content shape)) - (gpa/content->points (:content shape)) - - (seq (:segments shape)) - (gpa/segments->points (:content shape)) - - :else - (gpr/rect->points shape))] - (mapv transform-point points))) - (defn normalize-scale "We normalize the scale so it's not too close to 0" [scale] @@ -88,7 +68,6 @@ (and (>= scale 0) (< scale 0.01)) 0.01 :else scale)) - (defn modifiers->transform ([center modifiers] (modifiers->transform (gmt/matrix) center modifiers)) @@ -223,10 +202,6 @@ :points points :selrect selrect))) -(defn apply-transform-curve - [shape transform] - shape) - (defn apply-transform-rect "Given a new set of points transformed, set up the rectangle so it keeps its properties. We adjust de x,y,width,height and create a custom transform" @@ -267,7 +242,6 @@ (let [apply-transform-fn (case (:type shape) :path apply-transform-path - :curve apply-transform-curve apply-transform-rect)] (apply-transform-fn shape transform))) @@ -287,239 +261,3 @@ (apply-transform transform) (dissoc :modifiers))) shape))) - -#_(defn transform-shape - "Transform the shape properties given the modifiers" - ([shape] - (letfn [(transform-by-type [shape] - (case (:type shape) - (:curve :path) - (transform-path-shape shape) - - #_:default - (transform-rect-shape shape)))] - - (cond-> shape - (:modifiers shape) (transform-by-type) - :always (dissoc :modifiers))))) - -;; --- Transform Shape - -#_( - (declare transform-rect) - (declare transform-path) - (declare transform) - - (defn center-transform [shape matrix] - (let [shape-center (gco/center shape)] - (-> shape - (transform - (-> (gmt/matrix) - (gmt/translate shape-center) - (gmt/multiply matrix) - (gmt/translate (gpt/negate shape-center))))))) - - (defn- transform-rect - [{:keys [x y width height] :as shape} mx] - (let [tl (gpt/transform (gpt/point x y) mx) - tr (gpt/transform (gpt/point (+ x width) y) mx) - bl (gpt/transform (gpt/point x (+ y height)) mx) - br (gpt/transform (gpt/point (+ x width) (+ y height)) mx) - ;; TODO: replace apply with transduce (performance) - minx (apply min (map :x [tl tr bl br])) - maxx (apply max (map :x [tl tr bl br])) - miny (apply min (map :y [tl tr bl br])) - maxy (apply max (map :y [tl tr bl br]))] - (assoc shape - :x minx - :y miny - :width (- maxx minx) - :height (- maxy miny)))) - - (defn- transform-path - [{:keys [segments] :as shape} xfmt] - (let [segments (mapv #(gpt/transform % xfmt) segments)] - (assoc shape :segments segments))) - - - - - - (defn update-path-selrect [shape] - (as-> shape $ - (assoc $ :points (shape->points $)) - (assoc $ :selrect (gpr/points->selrect (:points $))) - (assoc $ :x (get-in $ [:selrect :x])) - (assoc $ :y (get-in $ [:selrect :y])) - (assoc $ :width (get-in $ [:selrect :width])) - (assoc $ :height (get-in $ [:selrect :height])))) - - (defn fix-invalid-rect-values - [rect-shape] - (letfn [(check [num] - (if (or (nil? num) (mth/nan? num) (= ##Inf num) (= ##-Inf num)) 0 num)) - (to-positive [num] (if (< num 1) 1 num))] - (-> rect-shape - (update :x check) - (update :y check) - (update :width (comp to-positive check)) - (update :height (comp to-positive check))))) - - - - - - - (declare transform-points) - - (defn apply-modifiers - [transform-stack modifiers points] - (let [ds-modifier (:displacement modifiers (gmt/matrix)) - {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) - - ;; Normalize x/y vector coordinates because scale by 0 is infinite - res-x (normalize-scale res-x) - res-y (normalize-scale res-y) - resize (gpt/point res-x res-y) - - origin (:resize-origin modifiers (gpt/point 0 0)) - - resize-transform (:resize-transform modifiers (gmt/matrix)) - resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) - rt-modif (or (:rotation modifiers) 0) - - points (transform-points ds-modifier) - center (gco/center-points points)] - - (-> points - (transform-points - (-> (gmt/matrix) - - ;; Applies the current resize transformation - (gmt/translate origin) - (gmt/multiply resize-transform) - (gmt/scale resize) - (gmt/multiply resize-transform-inverse) - (gmt/translate (gpt/negate origin)) - - ;; Applies the stacked transformations - (gmt/translate center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - (gmt/multiply transform-stack) - (gmt/translate (gpt/negate center))))))) - - (defn transform-path-shape - [shape] - shape - #_(-> shape - transform-apply-modifiers - update-path-selrect) - ;; TODO: Addapt for paths is not working - #_(let [shape-path (transform-apply-modifiers shape) - shape-path-center (center shape-path) - - shape-transform-inverse' (-> (gmt/matrix) - (gmt/translate shape-path-center) - (gmt/multiply (:transform-inverse shape (gmt/matrix))) - (gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0)))) - (gmt/translate (gpt/negate shape-path-center)))] - (-> shape-path - (transform shape-transform-inverse') - (add-rotate-transform (:rotation-modifier shape 0))))) - - (defn adjust-rect-transforms [shape] - ) - - (defn transform-rect-shape - [shape] - (let [points (-> (:points shape (shape->points shape)) - (apply-modifiers (:transform shape) (:modifiers shape) points)) - - center (gco/center-points points) - - resize-vector (-> (get-in shape [:modifiers :resize-vector] (gpt/point 1 1)) - (update :x #(if (zero? %) 1 %)) - (update :y #(if (zero? %) 1 %))) - - ;; Reverse the current transformation stack to get the base rectangle - tr-inverse (:transform-inverse shape (gmt/matrix)) - points-temp (transform-poins points center tr-inverse) - points-temp-dim (gpr/rect-points-dimensions points) - points-temp-rec (gpr/points->selrect points) - - ;; This rectangle is the new data for the current rectangle. We want to change our rectangle - ;; to have this width, height, x, y - rec (-> (gco/center->rect center (:width points-temp-dim) (:height points-temp-dim)) - (gpr/rect->points)) - ;;rec (fix-invalid-rect-values rec) - ;;rec-path (gpr/rect->path rec) - - ;; The next matrix is a series of transformations we have to do to the previous rec so that - ;; after applying them the end result is the `shape-path-temp` - ;; This is compose of three transformations: skew, resize and rotation - stretch-matrix (gmt/matrix) - - skew-angle (calculate-rec-path-skew-angle shape-path-temp) - - ;; When one of the axis is flipped we have to reverse the skew - skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle ) - skew-angle (if (mth/nan? skew-angle) 0 skew-angle) - - - stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0)) - - h1 (calculate-rec-path-height shape-path-temp) - h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix)) - h3 (/ h1 h2) - h3 (if (mth/nan? h3) 1 h3) - - stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) - - rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) - shape-path-temp resize-vector) - - stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix) - - ;; This is the inverse to be able to remove the transformation - stretch-matrix-inverse (-> (gmt/matrix) - (gmt/scale (gpt/point 1 h3)) - (gmt/skew (- skew-angle) 0) - (gmt/rotate (- rotation-angle))) - - new-shape (as-> shape $ - (merge $ rec) - (update $ :x #(mth/precision % 0)) - (update $ :y #(mth/precision % 0)) - (update $ :width #(mth/precision % 0)) - (update $ :height #(mth/precision % 0)) - (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) - (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) - (assoc $ :points (shape->points $)) - (assoc $ :selrect (gpr/points->selrect (:points $))) - (update $ :selrect fix-invalid-rect-values) - (update $ :rotation #(mod (+ (or % 0) - (or (get-in $ [:modifiers :rotation]) 0)) 360)))] - new-shape)) - - (defn transform-points - "Apply the matrix transformation to points" - [points xfmt] - - (cond->> points - (gmt/matrix? xfmt) (map #(gpt/transform % xfmt)))) - - #_(defn transform - "Apply the matrix transformation to shape" - [{:keys [type] :as shape} xfmt] - (if (gmt/matrix? xfmt) - (case type - :path (transform-path shape xfmt) - :curve (transform-path shape xfmt) - (transform-rect shape xfmt)) - shape)) - - - - - - ) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 913128a0e2..2212d77df3 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -623,23 +623,15 @@ :stroke-color "#000000" :stroke-opacity 0} - {:type :curve - :name "Path" - :fill-color "#000000" - :fill-opacity 0 - :stroke-style :solid - :stroke-alignment :center - :stroke-width 2 - :stroke-color "#000000" - :stroke-opacity 1} - {:type :text :name "Text" :content nil}]) (defn make-minimal-shape [type] - (let [shape (d/seek #(= type (:type %)) minimal-shapes)] + (let [type (cond (= type :curve) :path + :else type) + shape (d/seek #(= type (:type %)) minimal-shapes)] (when-not shape (ex/raise :type :assertion :code :shape-type-not-implemented @@ -649,7 +641,7 @@ :always (assoc :id (uuid/next)) - (not #{:path :curve}) + (not= :path (:type shape)) (assoc :x 0 :y 0 :width 1 @@ -771,6 +763,7 @@ {:rotation angle :displacement displacement})) +;; reg-objects operation "regenerates" the values for the parent groups (defmethod process-change :reg-objects [data {:keys [page-id shapes]}] (letfn [(reg-objects [objects] diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index 9e792a7977..d83d2b79c6 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -99,7 +99,5 @@ ;; default (box/handle-drawing-box)))))) -;; Export -#_(def close-drawing-path path/close-drawing-path) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 108a8b5210..387525fa41 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -28,10 +28,15 @@ (defn insert-point-segment [state point] (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) -(defn update-selrect [{:keys [segments] :as shape}] - (let [points (->> segments - (map #(apply gpt/point %)))] - (assoc shape :selrect (gsh/points->selrect points)))) +(defn curve-to-path [{:keys [segments] :as shape}] + (let [content (path/segments->content segments) + selrect (gsh/content->selrect content) + points (gsh/rect->points selrect)] + (-> shape + (dissoc :segments) + (assoc :content content) + (assoc :selrect selrect) + (assoc :points points)))) (defn finish-drawing-curve [state] (update-in @@ -39,7 +44,7 @@ (fn [shape] (-> shape (update :segments #(path/simplify % simplify-tolerance)) - (update-selrect))))) + (curve-to-path))))) (defn handle-drawing-curve [] (ptk/reify ::handle-drawing-curve diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 331efc6282..6c203d6432 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -84,7 +84,7 @@ {:keys [rotation]} shape shapev (-> (gpt/point width height)) - rotation (if (#{:curve :path} (:type shape)) 0 rotation) + rotation (if (= :path (:type shape)) 0 rotation) ;; Vector modifiers depending on the handler handler-modif (let [[x y] (handler-modifiers handler)] (gpt/point x y)) diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 74a543dad3..38721a84c2 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -84,7 +84,6 @@ opts #js {:shape shape}] [:> shape-container {:shape shape} (case (:type shape) - :curve [:> path/path-shape opts] :text [:> text/text-shape opts] :rect [:> rect/rect-shape opts] :path [:> path/path-shape opts] diff --git a/frontend/src/app/main/ui/handoff/attributes.cljs b/frontend/src/app/main/ui/handoff/attributes.cljs index 487396f0ae..4cf91cafb4 100644 --- a/frontend/src/app/main/ui/handoff/attributes.cljs +++ b/frontend/src/app/main/ui/handoff/attributes.cljs @@ -28,7 +28,6 @@ :rect [:layout :fill :stroke :shadow :blur] :circle [:layout :fill :stroke :shadow :blur] :path [:layout :fill :stroke :shadow :blur] - :curve [:layout :fill :stroke :shadow :blur] :image [:image :layout :shadow :blur] :text [:layout :text :shadow :blur]}) diff --git a/frontend/src/app/main/ui/handoff/render.cljs b/frontend/src/app/main/ui/handoff/render.cljs index d1893c0aef..714abbc6e1 100644 --- a/frontend/src/app/main/ui/handoff/render.cljs +++ b/frontend/src/app/main/ui/handoff/render.cljs @@ -127,7 +127,6 @@ opts #js {:shape shape :frame frame}] (case (:type shape) - :curve [:> path-wrapper opts] :text [:> text-wrapper opts] :rect [:> rect-wrapper opts] :path [:> path-wrapper opts] diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index a17bd9f313..211c50b1fd 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -153,7 +153,6 @@ (geom/translate-to-frame frame)) opts #js {:shape shape}] (case (:type shape) - :curve [:> path-wrapper opts] :text [:> text-wrapper opts] :rect [:> rect-wrapper opts] :path [:> path-wrapper opts] diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index 0ce96a02ca..5cb7523419 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -45,31 +45,3 @@ :fill "transparent" :stroke-width (/ 1 zoom)}}]))) -#_(mf/defc path-draw-area - [{:keys [shape] :as props}] - (let [locale (i18n/use-locale) - on-click - (fn [event] - (dom/stop-propagation event) - (st/emit! (dw/assign-cursor-tooltip nil) - (dd/close-drawing-path))) - - on-mouse-enter - (fn [event] - (let [msg (t locale "workspace.viewport.click-to-close-path")] - (st/emit! (dw/assign-cursor-tooltip msg)))) - - on-mouse-leave - (fn [event] - (st/emit! (dw/assign-cursor-tooltip nil)))] - - [:g.drawing - [:& shapes/shape-wrapper {:shape shape}] - #_(when (not= :curve (:type shape)) - [:circle.close-bezier - {:cx x - :cy y - :r 5 - :on-click on-click - :on-mouse-enter on-mouse-enter - :on-mouse-leave on-mouse-leave}])])) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 90443b15ce..54787f1e9a 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -215,44 +215,6 @@ :resize-side [:> resize-side-handler props])))]))) ;; --- Selection Handlers (Component) -(mf/defc path-edition-selection-handlers - [{:keys [shape modifiers zoom color] :as props}] - (letfn [(on-mouse-down [event index] - (dom/stop-propagation event) - ;; TODO: this need code ux refactor - (let [stoper (get-edition-stream-stoper) - stream (->> (ms/mouse-position-deltas @ms/mouse-position) - (rx/take-until stoper))] - ;; (when @refs/selected-alignment - ;; (st/emit! (dw/initial-path-point-align (:id shape) index))) - (rx/subscribe stream #(on-handler-move % index)))) - - (get-edition-stream-stoper [] - (let [stoper? #(and (ms/mouse-event? %) (= (:type %) :up))] - (rx/merge - (rx/filter stoper? st/stream) - (->> st/stream - (rx/filter #(= % :interrupt)) - (rx/take 1))))) - - (on-handler-move [delta index] - (st/emit! (dw/update-path (:id shape) index delta)))] - - (let [transform (geom/transform-matrix shape) - displacement (:displacement modifiers) - segments (cond->> (:segments shape) - displacement (map #(gpt/transform % displacement)))] - [:g.controls - (for [[index {:keys [x y]}] (map-indexed vector segments)] - (let [{:keys [x y]} (gpt/transform (gpt/point x y) transform)] - [:circle {:cx x :cy y - :r (/ 6.0 zoom) - :key index - :on-mouse-down #(on-mouse-down % index) - :fill "#ffffff" - :stroke color - :style {:cursor cur/move-pointer}}]))]))) - ;; TODO: add specs for clarity (mf/defc text-edition-selection-handlers @@ -372,12 +334,6 @@ [:& path-editor {:zoom zoom :shape shape}] - (and (= type :curve) - (= edition (:id shape))) - [:& path-edition-selection-handlers {:shape shape - :zoom zoom - :color color}] - :else [:& single-selection-handlers {:shape shape :zoom zoom diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index cd9dd7521c..52cb950406 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -108,7 +108,6 @@ :on-mouse-leave on-mouse-leave :style {:cursor (if @alt? cur/duplicate nil)}} (case (:type shape) - :curve [:> path/path-wrapper opts] :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] :group [:> group-wrapper opts] diff --git a/frontend/src/app/main/ui/workspace/shapes/outline.cljs b/frontend/src/app/main/ui/workspace/shapes/outline.cljs index 361636e446..f41f371ece 100644 --- a/frontend/src/app/main/ui/workspace/shapes/outline.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/outline.cljs @@ -28,7 +28,7 @@ outline-type (case (:type shape) :circle "ellipse" - (:curve :path) "path" + :path "path" "rect") common {:fill "transparent" @@ -44,7 +44,7 @@ :rx (/ width 2) :ry (/ height 2)} - (:curve :path) + :path {:d (path/render-path shape)} {:x x diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.cljs b/frontend/src/app/main/ui/workspace/sidebar/history.cljs index aebc62bb59..2ad04ab133 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/history.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/history.cljs @@ -129,7 +129,6 @@ :rect i/box :circle i/circle :text i/text - :curve i/curve :path i/curve :frame i/artboard :group i/folder @@ -141,7 +140,7 @@ i/layers)) (defn is-shape? [type] - #{:shape :rect :circle :text :curve :path :frame :group}) + #{:shape :rect :circle :text :path :frame :group}) (defn parse-entry [{:keys [redo-changes]}] (->> redo-changes diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 2b83cb73f6..9bf8287152 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -39,7 +39,6 @@ :circle i/circle :path i/curve :rect i/box - :curve i/curve :text i/text :group (if (some? (:component-id shape)) i/component diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs index 0a4020a8d1..467d87f947 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs @@ -48,7 +48,6 @@ :icon [:& icon/options {:shape shape}] :circle [:& circle/options {:shape shape}] :path [:& path/options {:shape shape}] - :curve [:& path/options {:shape shape}] :image [:& image/options {:shape shape}] nil) [:& exports-menu diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index e8d40fff92..eb64b84b35 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -213,3 +213,18 @@ opposite (gpt/add point (gpt/negate phv))] opposite)) +(defn segments->content [segments] + (let [initial (first segments) + closed? (= (first segments) (last segments)) + lines (if closed? + (take (- (count segments) 2) (rest segments)) + (rest segments))] + + (d/concat [{:command :move-to + :params (select-keys initial [:x :y])}] + (->> lines + (mapv #(hash-map :command :line-to + :params (select-keys % [:x :y])))) + + (when closed? + [{:command :close-path}])))) diff --git a/frontend/src/app/util/geom/snap_points.cljs b/frontend/src/app/util/geom/snap_points.cljs index 75f0427516..2f9fdb000d 100644 --- a/frontend/src/app/util/geom/snap_points.cljs +++ b/frontend/src/app/util/geom/snap_points.cljs @@ -32,6 +32,4 @@ (let [shape (gsh/transform-shape shape)] (case (:type shape) :frame (-> shape :selrect frame-snap-points) - (:path :curve) (-> shape :selrect selrect-snap-points) - (into #{(gsh/center-shape shape)} (:points shape))) - )) + (into #{(gsh/center-shape shape)} (:points shape))))) From f339f1ee984fc133c1eae2b17c246ca8232f25a5 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 20 Nov 2020 09:38:33 +0100 Subject: [PATCH 057/195] :sparkles: Migrates model to the new paths --- .gitignore | 1 + common/app/common/geom/shapes.cljc | 11 ++-- common/app/common/geom/shapes/path.cljc | 17 +++++ common/app/common/geom/shapes/rect.cljc | 16 ++--- common/app/common/pages.cljc | 2 +- common/app/common/pages_migrations.cljc | 62 ++++++++++++++++++- .../styles/main/partials/dashboard-grid.scss | 6 ++ frontend/src/app/main/data/workspace.cljs | 16 ----- .../main/data/workspace/drawing/curve.cljs | 3 +- frontend/src/app/main/ui/shapes/path.cljs | 27 +------- .../app/main/ui/workspace/shapes/outline.cljs | 6 +- .../workspace/sidebar/options/measures.cljs | 14 +++-- frontend/src/app/util/geom/path.cljs | 15 ----- 13 files changed, 114 insertions(+), 82 deletions(-) diff --git a/.gitignore b/.gitignore index a7cb67059f..0e01a66857 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ node_modules /media /deploy /web +/_dump diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 325f9e6343..56fe8ccb6c 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -233,12 +233,11 @@ (defn setup-selrect [{:keys [x y width height] :as shape}] - (-> shape - (assoc :selrect - {:x x :y y - :width width :height height - :x1 x :y1 y - :x2 (+ x width) :y2 (+ y height)}))) + (let [selrect (gpr/rect->selrect shape) + points (gpr/rect->points shape)] + (-> shape + (assoc :selrect selrect + :points points)))) ;; EXPORTS diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index 1c9f26466f..538b9b13d7 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -161,3 +161,20 @@ (:c2y params) (update-in [index :params :c2y] + (:c2y params))) content))] (reduce red-fn content modifiers))) + +(defn segments->content + ([segments] + (segments->content segments false)) + + ([segments closed?] + (let [initial (first segments) + lines (rest segments)] + + (d/concat [{:command :move-to + :params (select-keys initial [:x :y])}] + (->> lines + (mapv #(hash-map :command :line-to + :params (select-keys % [:x :y])))) + + (when closed? + [{:command :close-path}]))))) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index 9cd0979962..bca71f3adb 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -24,10 +24,10 @@ (gpt/point x (+ y height))]) (defn points->rect [points] - (let [minx (transduce (map :x) min ##Inf points) - miny (transduce (map :y) min ##Inf points) - maxx (transduce (map :x) max ##-Inf points) - maxy (transduce (map :y) max ##-Inf points)] + (let [minx (transduce (comp (map :x) (remove nil?)) min ##Inf points) + miny (transduce (comp (map :y) (remove nil?)) min ##Inf points) + maxx (transduce (comp (map :x) (remove nil?)) max ##-Inf points) + maxy (transduce (comp (map :y) (remove nil?)) max ##-Inf points)] {:x minx :y miny :width (- maxx minx) @@ -45,10 +45,10 @@ (-> rect rect->points points->selrect)) (defn join-selrects [selrects] - (let [minx (transduce (map :x1) min ##Inf selrects) - miny (transduce (map :y1) min ##Inf selrects) - maxx (transduce (map :x2) max ##-Inf selrects) - maxy (transduce (map :y2) max ##-Inf selrects)] + (let [minx (transduce (comp (map :x1) (remove nil?)) min ##Inf selrects) + miny (transduce (comp (map :y1) (remove nil?)) min ##Inf selrects) + maxx (transduce (comp (map :x2) (remove nil?)) max ##-Inf selrects) + maxy (transduce (comp (map :y2) (remove nil?)) max ##-Inf selrects)] {:x minx :y miny :x1 minx diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 2212d77df3..52accc13e0 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -20,7 +20,7 @@ [app.common.spec :as us] [app.common.uuid :as uuid])) -(def file-version 2) +(def file-version 3) (def max-safe-int 9007199254740991) (def min-safe-int -9007199254740991) diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index 7d9b89bc03..75697f5e37 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -2,6 +2,7 @@ (:require [app.common.pages :as cp] [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.path :as gsp] [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] [app.common.spec :as us] @@ -35,7 +36,6 @@ ;; -- MIGRATIONS -- ;; Ensure that all :shape attributes on shapes are vectors. - (defmethod migrate 2 [data] (letfn [(update-object [id object] @@ -49,3 +49,63 @@ (update page :objects #(d/mapm update-object %)))] (update data :pages-index #(d/mapm update-page %)))) + +;; Changes paths formats +(defmethod migrate 3 + [data] + (letfn [(migrate-path [shape] + (if-not (contains? shape :content) + (let [content (gsp/segments->content (:segments shape) (:close? shape)) + selrect (gsh/content->selrect content) + points (gsh/rect->points selrect)] + (-> shape + (dissoc :segments) + (dissoc :close?) + (assoc :content content) + (assoc :selrect selrect) + (assoc :points points))) + ;; If the shape contains :content is already in the new format + shape)) + + (fix-frames-selrects [frame] + (if (= (:id frame) uuid/zero) + frame + (let [frame-rect (select-keys frame [:x :y :width :height])] + (-> frame + (assoc :selrect (gsh/rect->selrect frame-rect)) + (assoc :points (gsh/rect->points frame-rect)))))) + + (fix-empty-points [shape] + (let [shape (cond-> shape + (empty? (:selrect shape)) (gsh/setup-selrect))] + (cond-> shape + (empty? (:points shape)) + (assoc :points (gsh/rect->points (:selrect shape)))))) + + (update-object [id object] + (cond-> object + (= :curve (:type object)) + (assoc :type :path) + + (or (#{:curve :path} (:type object))) + (migrate-path) + + (= :frame (:type object)) + (fix-frames-selrects) + + (and (empty? (:points object)) (not= (:id object) uuid/zero)) + (fix-empty-points) + + :always + (-> + ;; Setup an empty transformation to re-calculate selrects + ;; and points data + (assoc :modifiers {:displacement (gmt/matrix)}) + (gsh/transform-shape)) + + )) + + (update-page [id page] + (update page :objects #(d/mapm update-object %)))] + + (update data :pages-index #(d/mapm update-page %)))) diff --git a/frontend/resources/styles/main/partials/dashboard-grid.scss b/frontend/resources/styles/main/partials/dashboard-grid.scss index 7f0364275c..79b5da8adf 100644 --- a/frontend/resources/styles/main/partials/dashboard-grid.scss +++ b/frontend/resources/styles/main/partials/dashboard-grid.scss @@ -206,6 +206,12 @@ &.menu { margin-right: 0; + width: 2rem; + height: 2rem; + display: flex; + justify-content: flex-end; + align-items: flex-end; + flex-direction: column; svg { fill: $color-gray-60; diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index a8fc65d4d2..c760d812c3 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1046,22 +1046,6 @@ (rx/of (dwt/set-modifiers [id] {:displacement displ}) (dwt/apply-modifiers [id])))))) -;; --- Path Modifications - -(defn update-path - "Update a concrete point in the path shape." - [id index delta] - (us/verify ::us/uuid id) - (us/verify ::us/integer index) - (us/verify gpt/point? delta) - #_(ptk/reify ::update-path - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state)] - (-> state - (update-in [:workspace-data page-id :objects id :segments index] gpt/add delta) - (update-in [:workspace-data page-id :objects id] gsh/update-path-selrect)))))) - ;; --- Shape attrs (Layers Sidebar) (defn toggle-collapse diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 387525fa41..e06e7240d4 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -13,6 +13,7 @@ [potok.core :as ptk] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.path :as gsp] [app.main.streams :as ms] [app.util.geom.path :as path] [app.main.data.workspace.drawing.common :as common])) @@ -29,7 +30,7 @@ (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) (defn curve-to-path [{:keys [segments] :as shape}] - (let [content (path/segments->content segments) + (let [content (gsp/segments->content segments) selrect (gsh/content->selrect content) points (gsh/rect->points selrect)] (-> shape diff --git a/frontend/src/app/main/ui/shapes/path.cljs b/frontend/src/app/main/ui/shapes/path.cljs index ff1a0bce38..85a0e0cd28 100644 --- a/frontend/src/app/main/ui/shapes/path.cljs +++ b/frontend/src/app/main/ui/shapes/path.cljs @@ -20,28 +20,6 @@ ;; --- Path Shape -;; LEGACY FORMAT -(defn- render-path - [{:keys [segments close?] :as shape}] - (let [numsegs (count segments)] - (loop [buffer [] - index 0] - (cond - (>= index numsegs) - (if close? - (str/join " " (conj buffer "Z")) - (str/join " " buffer)) - - (zero? index) - (let [{:keys [x y] :as segment} (nth segments index) - buffer (conj buffer (str/istr "M~{x},~{y}"))] - (recur buffer (inc index))) - - :else - (let [{:keys [x y] :as segment} (nth segments index) - buffer (conj buffer (str/istr "L~{x},~{y}"))] - (recur buffer (inc index))))))) - (mf/defc path-shape {::mf/wrap-props false} [props] @@ -51,10 +29,7 @@ {:keys [id x y width height]} (:selrect shape) mask-id (mf/use-ctx mask-id-ctx) transform (geom/transform-matrix shape) - pdata (if (:content shape) - (ugp/content->path (:content shape)) - (render-path shape)) - + pdata (ugp/content->path (:content shape)) props (-> (attrs/extract-style-attrs shape) (obj/merge! #js {:transform transform diff --git a/frontend/src/app/main/ui/workspace/shapes/outline.cljs b/frontend/src/app/main/ui/workspace/shapes/outline.cljs index f41f371ece..309bdc5ffc 100644 --- a/frontend/src/app/main/ui/workspace/shapes/outline.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/outline.cljs @@ -13,8 +13,8 @@ [app.common.geom.shapes :as gsh] [app.util.object :as obj] [rumext.util :refer [map->obj]] - [app.main.ui.shapes.path :as path] - [app.main.refs :as refs])) + [app.main.refs :as refs] + [app.util.geom.path :as ugp])) (mf/defc outline @@ -45,7 +45,7 @@ :ry (/ height 2)} :path - {:d (path/render-path shape)} + {:d (ugp/content->path (:content shape))} {:x x :y y diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index f76fa2ee08..6d67412d8b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -43,11 +43,15 @@ old-shapes (deref (refs/objects-by-id ids)) frames (map #(deref (refs/object-by-id (:frame-id %))) old-shapes) - shapes (map gsh/transform-shape frames old-shapes) - values (cond-> values - (not= (:x values) :multiple) (assoc :x (:x (:selrect (first shapes)))) - (not= (:y values) :multiple) (assoc :y (:y (:selrect (first shapes))))) + shapes (as-> old-shapes $ + (map gsh/transform-shape $) + (map gsh/translate-to-frame $ frames)) + + values (let [{:keys [x y]} (-> shapes first :points gsh/points->selrect)] + (cond-> values + (not= (:x values) :multiple) (assoc :x x) + (not= (:y values) :multiple) (assoc :y y))) proportion-lock (:proportion-lock values) @@ -65,7 +69,7 @@ do-position-change (fn [shape' frame' value attr] - (let [from (-> shape' :selrect attr) + (let [from (-> shape' :points gsh/points->selrect attr) to (+ value (attr frame')) target (+ (attr shape') (- to from))] (st/emit! (udw/update-position (:id shape') {attr target})))) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index eb64b84b35..e8d40fff92 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -213,18 +213,3 @@ opposite (gpt/add point (gpt/negate phv))] opposite)) -(defn segments->content [segments] - (let [initial (first segments) - closed? (= (first segments) (last segments)) - lines (if closed? - (take (- (count segments) 2) (rest segments)) - (rest segments))] - - (d/concat [{:command :move-to - :params (select-keys initial [:x :y])}] - (->> lines - (mapv #(hash-map :command :line-to - :params (select-keys % [:x :y])))) - - (when closed? - [{:command :close-path}])))) From b66b0cb43199c7af664cb4c8152455f85db12926 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 23 Nov 2020 22:10:12 +0100 Subject: [PATCH 058/195] :sparkles: Close paths and internals refactor --- common/app/common/geom/shapes/path.cljc | 18 - .../app/main/data/workspace/drawing/path.cljs | 398 ++++++++++-------- .../app/main/ui/workspace/shapes/path.cljs | 222 +++++----- frontend/src/app/util/data.cljs | 5 +- frontend/src/app/util/geom/path.cljs | 82 +++- 5 files changed, 431 insertions(+), 294 deletions(-) diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index 538b9b13d7..d62b8df08d 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -17,9 +17,6 @@ [app.common.math :as mth] [app.common.data :as d])) -(defn segments->points [segments] - segments) - (defn content->points [content] (->> content (map #(when (-> % :params :x) (gpt/point (-> % :params :x) (-> % :params :y)))) @@ -147,21 +144,6 @@ (mapv #(update % :params transform-params) content))) -(defn apply-content-modifiers [content modifiers] - (let [red-fn (fn [content [index params]] - (if (contains? content index) - (cond-> content - (:x params) (update-in [index :params :x] + (:x params)) - (:y params) (update-in [index :params :y] + (:y params)) - - (:c1x params) (update-in [index :params :c1x] + (:c1x params)) - (:c1y params) (update-in [index :params :c1y] + (:c1y params)) - - (:c2x params) (update-in [index :params :c2x] + (:c2x params)) - (:c2y params) (update-in [index :params :c2y] + (:c2y params))) - content))] - (reduce red-fn content modifiers))) - (defn segments->content ([segments] (segments->content segments false)) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 8dec5b402a..0cc24d467b 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -12,6 +12,7 @@ [beicon.core :as rx] [potok.core :as ptk] [app.common.math :as mth] + [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.util.data :as ud] @@ -28,11 +29,16 @@ ;; PRIVATE METHODS -(defn get-path-id [state] +(defn get-path-id + "Retrieves the currently editing path id" + [state] (or (get-in state [:workspace-local :edition]) (get-in state [:workspace-drawing :object :id]))) -(defn get-path [state & path] +(defn get-path + "Retrieves the location of the path object and additionaly can pass + the arguments. This location can be used in get-in, assoc-in... functions" + [state & path] (let [edit-id (get-in state [:workspace-local :edition]) page-id (:current-page-id state)] (cd/concat @@ -41,13 +47,9 @@ [:workspace-drawing :object]) path))) -(defn last-start-path [content] - (->> content - reverse - (cd/seek (fn [{cmd :command}] (= cmd :move-to))) - :params)) - -(defn update-selrect [shape] +(defn update-selrect + "Updates the selrect and points for a path" + [shape] (let [selrect (gsh/content->selrect (:content shape)) points (gsh/rect->points selrect)] (assoc shape :points points :selrect selrect))) @@ -56,8 +58,6 @@ "Calculates the next-node to be inserted." [shape position prev-point prev-handler] (let [last-command (-> shape :content last :command) - start-point (-> shape :content last-start-path) - add-line? (and prev-point (not prev-handler) (not= last-command :close-path)) add-curve? (and prev-point prev-handler (not= last-command :close-path))] (cond @@ -76,53 +76,17 @@ (update :content (fnil conj []) command) (update-selrect)))) -(defn suffix-keyword - [kw suffix] - (let [strkw (if kw (name kw) "")] - (keyword (str strkw suffix)))) +(defn move-handler-modifiers [content index prefix match-opposite? dx dy] + (let [[cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y]) + [ocx ocy] (if (= prefix :c1) [:c2x :c2y] [:c1x :c1y]) + opposite-index (ugp/opposite-index content index prefix)] -(defn move-handler - [shape index handler-type match-opposite? position] - (let [content (:content shape) - [command next-command] (-> (ud/with-next content) (nth index)) + (cond-> {} + :always + (update index assoc cx dx cy dy) - update-command - (fn [{cmd :command params :params :as command} param-prefix prev-command] - (if (#{:line-to :curve-to} cmd) - (let [command (if (= cmd :line-to) - {:command :curve-to - :params (ugp/make-curve-params params (:params prev-command))} - command)] - (-> command - (update :params assoc - (suffix-keyword param-prefix "x") (:x position) - (suffix-keyword param-prefix "y") (:y position)))) - command)) - - update-content - (fn [shape index prefix] - (if (contains? (:content shape) index) - (let [prev-command (get-in shape [:content (dec index)]) - content (-> shape :content (update index update-command prefix prev-command))] - (-> shape - (assoc :content content) - (update-selrect))) - shape))] - - (cond-> shape - (= :prev handler-type) - (update-content index :c2) - - (and (= :next handler-type) next-command) - (update-content (inc index) :c1) - - match-opposite? - (move-handler - index - (if (= handler-type :prev) :next :prev) - false - (ugp/opposite-handler (gpt/point (:params command)) - (gpt/point position)))))) + (and match-opposite? opposite-index) + (update opposite-index assoc ocx (- dx) ocy (- dy))))) (defn end-path-event? [{:keys [type shift] :as event}] (or (= event ::end-path) @@ -175,29 +139,58 @@ (update-in [:workspace-local :edit-path id] dissoc :prev-handler) (update-in (get-path state) append-node position last-point prev-handler)))))) +(defn start-drag-handler [] + (ptk/reify ::start-drag-handler + ptk/UpdateEvent + (update [_ state] + (let [content (get-in state (get-path state :content)) + index (dec (count content)) + command (get-in state (get-path state :content index :command)) + + make-curve + (fn [command] + (let [params (ugp/make-curve-params + (get-in content [index :params]) + (get-in content [(dec index) :params]))] + (-> command + (assoc :command :curve-to :params params))))] + + (cond-> state + (= command :line-to) + (update-in (get-path state :content index) make-curve)))))) + (defn drag-handler [{:keys [x y]}] (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] (let [id (get-path-id state) - position (gpt/point x y) + handler-position (gpt/point x y) shape (get-in state (get-path state)) - index (dec (count (:content shape)))] + content (:content shape) + index (dec (count content)) + node-position (ugp/command->point (nth content index)) + {dx :x dy :y} (gpt/subtract handler-position node-position) + match-opposite? true + modifiers (move-handler-modifiers content (inc index) :c1 match-opposite? dx dy)] (-> state - (update-in (get-path state) move-handler index :next true position) - (assoc-in [:workspace-local :edit-path id :prev-handler] position) - (assoc-in [:workspace-local :edit-path id :drag-handler] position)))))) + (assoc-in [:workspace-local :edit-path id :content-modifiers] modifiers) + (assoc-in [:workspace-local :edit-path id :prev-handler] handler-position) + (assoc-in [:workspace-local :edit-path id :drag-handler] handler-position)))))) (defn finish-drag [] (ptk/reify ::finish-drag ptk/UpdateEvent (update [_ state] (let [id (get-path-id state) + modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) handler (get-in state [:workspace-local :edit-path id :drag-handler])] (-> state + (update-in (get-path state :content) ugp/apply-content-modifiers modifiers) (update-in [:workspace-local :edit-path id] dissoc :drag-handler) - (assoc-in [:workspace-local :edit-path id :prev-handler] handler)))) + (update-in [:workspace-local :edit-path id] dissoc :content-modifiers) + (assoc-in [:workspace-local :edit-path id :prev-handler] handler) + (update-in (get-path state) update-selrect)))) ptk/WatchEvent (watch [_ state stream] @@ -206,6 +199,76 @@ ;; Update the preview because can be outdated after the dragging (rx/of (preview-next-point handler)))))) +(defn close-path [position] + (ptk/reify ::close-path + ptk/WatchEvent + (watch [_ state stream] + (rx/of (add-node position) + ::end-path)))) + +(defn close-path-drag-start [position] + (ptk/reify ::close-path-drag-start + ptk/WatchEvent + (watch [_ state stream] + (let [zoom (get-in state [:workspace-local :zoom]) + threshold (/ 5 zoom) + check-if-dragging + (fn [current-position] + (let [start (gpt/point position) + current (gpt/point current-position)] + (>= (gpt/distance start current) 100))) + + stop-stream + (->> stream (rx/filter #(or (end-path-event? %) + (ms/mouse-up? %)))) + + position-stream + (->> ms/mouse-position + (rx/take-until stop-stream) + (rx/throttle 50)) + + drag-events-stream + (->> position-stream + (rx/map #(drag-handler %)))] + + + (rx/concat + (rx/of (close-path position)) + + (->> position-stream + (rx/filter check-if-dragging) + (rx/take 1) + (rx/merge-map + #(rx/concat + (rx/of (start-drag-handler)) + drag-events-stream + (rx/of (finish-drag)))))))))) + +(defn close-path-drag-end [position] + (ptk/reify ::close-path-drag-end)) + +(defn path-pointer-enter [position] + (ptk/reify ::path-pointer-enter)) + +(defn path-pointer-leave [position] + (ptk/reify ::path-pointer-leave)) + +(defn start-path-from-point [position] + (ptk/reify ::start-path-from-point + ptk/WatchEvent + (watch [_ state stream] + (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) + (ms/mouse-up? %)))) + drag-events (->> ms/mouse-position + (rx/take-until mouse-up) + (rx/map #(drag-handler %)))] + + (rx/concat (rx/of (add-node position)) + (rx/of (start-drag-handler)) + drag-events + (rx/of (finish-drag)))) + ))) + ;; EVENT STREAMS (defn make-click-stream @@ -218,13 +281,15 @@ (defn make-drag-stream [stream down-event] - (let [mouse-up (->> stream (rx/filter ms/mouse-up?)) + (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) + (ms/mouse-up? %)))) drag-events (->> ms/mouse-position (rx/take-until mouse-up) (rx/map #(drag-handler %)))] (->> (rx/timer 400) (rx/merge-map #(rx/concat (rx/of (add-node down-event)) + (rx/of (start-drag-handler)) drag-events (rx/of (finish-drag))))))) @@ -237,14 +302,27 @@ #(rx/of (add-node down-event) ::end-path)))) +(defn make-node-events-stream + [stream] + (->> (rx/merge + (->> stream (rx/filter (ptk/type? ::close-path))) + (->> stream (rx/filter (ptk/type? ::close-path-drag-start)))) + (rx/take 1) + (rx/merge-map #(rx/empty)))) + ;; MAIN ENTRIES (defn handle-drawing-path [id] (ptk/reify ::handle-drawing-path + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (-> state + (assoc-in [:workspace-local :edit-path id :edit-mode] :draw)))) + ptk/WatchEvent (watch [_ state stream] - (let [mouse-down (->> stream (rx/filter ms/mouse-down?)) end-path-events (->> stream (rx/filter end-path-event?)) @@ -264,7 +342,8 @@ ;; We change to the stream that emits the first event (rx/switch-map - #(rx/race (make-click-stream stream %) + #(rx/race (make-node-events-stream stream) + (make-click-stream stream %) (make-drag-stream stream %) (make-dbl-click-stream stream %))))] @@ -276,67 +355,6 @@ -#_(def handle-drawing-path - (ptk/reify ::handle-drawing-path - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - - last-point (volatile! @ms/mouse-position) - - stoper (->> (rx/filter stoper-event? stream) - (rx/share)) - - mouse (rx/sample 10 ms/mouse-position) - - points (->> stream - (rx/filter ms/mouse-click?) - (rx/filter #(false? (:shift %))) - (rx/with-latest vector mouse) - (rx/map second)) - - counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) - - stream' (->> mouse - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/with-latest vector counter) - (rx/map flatten)) - - imm-transform #(vector (- % 7) (+ % 7) %) - immanted-zones (vec (concat - (map imm-transform (range 0 181 15)) - (map (comp imm-transform -) (range 0 181 15)))) - - align-position (fn [angle pos] - (reduce (fn [pos [a1 a2 v]] - (if (< a1 angle a2) - (reduced (gpt/update-angle pos v)) - pos)) - pos - immanted-zones))] - - (rx/merge - (rx/of #(initialize-drawing % @last-point)) - - (->> points - (rx/take-until stoper) - (rx/map (fn [pt] #(insert-point-segment % pt)))) - - (rx/concat - (->> stream' - (rx/take-until stoper) - (rx/map (fn [[point ctrl? index :as xxx]] - (let [point (if ctrl? - (as-> point $ - (gpt/subtract $ @last-point) - (align-position (gpt/angle $) $) - (gpt/add $ @last-point)) - point)] - #(update-point-segment % index point))))) - (rx/of finish-drawing-path - common/handle-finish-drawing))))))) - - (defn stop-path-edit [] (ptk/reify ::stop-path-edit ptk/UpdateEvent @@ -363,12 +381,12 @@ (rx/take 1) (rx/map #(stop-path-edit)))))) -(defn modify-point [index dx dy] +(defn modify-point [index prefix dx dy] (ptk/reify ::modify-point - ptk/UpdateEvent (update [_ state] - (let [id (get-in state [:workspace-local :edition])] + (let [id (get-in state [:workspace-local :edition]) + [cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y])] (-> state (update-in [:workspace-local :edit-path id :content-modifiers (inc index)] assoc :c1x dx :c1y dy) @@ -376,19 +394,22 @@ :x dx :y dy :c2x dx :c2y dy) ))))) -(defn modify-handler [index type dx dy] +(defn modify-handler [id index prefix dx dy match-opposite?] (ptk/reify ::modify-point ptk/UpdateEvent (update [_ state] - (let [id (get-in state [:workspace-local :edition])] - (let [s1 (if (= type :prev) -1 1) - s2 (if (= type :prev) 1 -1)] - (-> state - (update-in [:workspace-local :edit-path id :content-modifiers (inc index)] assoc - :c1x (* s1 dx) :c1y (* s1 dy)) - (update-in [:workspace-local :edit-path id :content-modifiers index] assoc - :c2x (* s2 dx) :c2y (* s2 dy) )) - ))))) + (let [content (get-in state (get-path state :content)) + [cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y]) + [ocx ocy] (if (= prefix :c1) [:c2x :c2y] [:c1x :c1y]) + opposite-index (ugp/opposite-index content index prefix)] + (cond-> state + :always + (update-in [:workspace-local :edit-path id :content-modifiers index] assoc + cx dx cy dy) + + (and match-opposite? opposite-index) + (update-in [:workspace-local :edit-path id :content-modifiers opposite-index] assoc + ocx (- dx) ocy (- dy))))))) (defn apply-content-modifiers [] (ptk/reify ::apply-content-modifiers @@ -400,7 +421,7 @@ old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) old-points (get-in state [:workspace-data :pages-index page-id :objects id :points]) content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) - new-content (gsp/apply-content-modifiers old-content content-modifiers) + new-content (ugp/apply-content-modifiers old-content content-modifiers) new-selrect (gsh/content->selrect new-content) new-points (gsh/rect->points new-selrect) rch [{:type :mod-obj @@ -478,46 +499,82 @@ (= mode :draw) (rx/of :interrupt) :else (rx/of (finish-path id))))))) +(defn move-path-point [start-point end-point] + (ptk/reify ::move-point + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state) + content (get-in state (get-path state :content)) + + {dx :x dy :y} (gpt/subtract end-point start-point) + + handler-indices (-> (ugp/content->handlers content) + (get start-point)) + + command-for-point (fn [[index command]] + (let [point (ugp/command->point command)] + (= point start-point))) + + point-indices (->> (d/enumerate content) + (filter command-for-point) + (map first)) + + + point-reducer (fn [modifiers index] + (-> modifiers + (assoc-in [index :x] dx) + (assoc-in [index :y] dy))) + + handler-reducer (fn [modifiers [index prefix]] + (let [cx (ud/prefix-keyword prefix :x) + cy (ud/prefix-keyword prefix :y)] + (-> modifiers + (assoc-in [index cx] dx) + (assoc-in [index cy] dy)))) + + modifiers (as-> (get-in state [:workspace-local :edit-path id :content-modifiers] {}) $ + (reduce point-reducer $ point-indices) + (reduce handler-reducer $ handler-indices))] + + (assoc-in state [:workspace-local :edit-path id :content-modifiers] modifiers))))) + (defn start-move-path-point - [index] + [position] (ptk/reify ::start-move-path-point ptk/WatchEvent + ;; TODO REWRITE (watch [_ state stream] - (let [id (get-in state [:workspace-local :edition]) - start-point @ms/mouse-position - start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers index :x] 0) - start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers index :y] 0)] + (let [stopper (->> stream (rx/filter ms/mouse-up?))] (rx/concat (->> ms/mouse-position - (rx/take-until (->> stream (rx/filter ms/mouse-up?))) - (rx/map #(modify-point - index - (+ start-delta-x (- (:x %) (:x start-point))) - (+ start-delta-y (- (:y %) (:y start-point)))))) - (rx/concat (rx/of (apply-content-modifiers))) - ))))) + (rx/take-until stopper) + (rx/map #(move-path-point position %))) + (rx/of (apply-content-modifiers))))))) (defn start-move-handler - [index type] + [index prefix] (ptk/reify ::start-move-handler ptk/WatchEvent (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) - [cx cy] (if (= :prev type) [:c2x :c2y] [:c1x :c1y]) - cidx (if (= :prev type) index (inc index)) - + [cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y]) start-point @ms/mouse-position - start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers cidx cx] 0) - start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers cidx cy] 0)] + start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers index cx] 0) + start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers index cy] 0)] (rx/concat (->> ms/mouse-position (rx/take-until (->> stream (rx/filter ms/mouse-up?))) - (rx/map #(modify-handler - index - type - (+ start-delta-x (- (:x %) (:x start-point))) - (+ start-delta-y (- (:y %) (:y start-point))))) + (rx/with-latest vector ms/mouse-position-alt) + (rx/map + (fn [[pos alt?]] + (modify-handler + id + index + prefix + (+ start-delta-x (- (:x pos) (:x start-point))) + (+ start-delta-y (- (:y pos) (:y start-point))) + (not alt?)))) ) (rx/concat (rx/of (apply-content-modifiers)))))))) @@ -568,13 +625,21 @@ (-> state (update-in [:workspace-local :edit-path id :selected] (fnil conj #{}) [index type])))))) -(defn select-node [index] +(defn select-node [position] (ptk/reify ::select-node ptk/UpdateEvent (update [_ state] (let [id (get-in state [:workspace-local :edition])] (-> state - (update-in [:workspace-local :edit-path id :selected] (fnil conj #{}) index)))))) + (update-in [:workspace-local :edit-path id :selected-node] (fnil conj #{}) position)))))) + +(defn deselect-node [position] + (ptk/reify ::deselect-node + ptk/UpdateEvent + (update [_ state] + (let [id (get-in state [:workspace-local :edition])] + (-> state + (update-in [:workspace-local :edit-path id :selected-node] (fnil disj #{}) position)))))) (defn add-to-selection-handler [index type] (ptk/reify ::add-to-selection-handler @@ -629,5 +694,4 @@ (rx/filter (ptk/type? ::finish-path)) (rx/take 1) (rx/observe-on :async) - (rx/map #(handle-new-shape-result shape-id))) - ))))) + (rx/map #(handle-new-shape-result shape-id)))))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 9396aca1fb..d7330361ee 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -29,7 +29,6 @@ [app.main.ui.workspace.shapes.common :as common] [app.util.geom.path :as ugp] [app.common.geom.point :as gpt] - [app.common.geom.shapes.path :as gsp] [app.main.ui.cursors :as cur] [app.main.ui.icons :as i])) @@ -39,8 +38,6 @@ (def white-color "#FFFFFF") (def gray-color "#B1B2B5") - - (def current-edit-path-ref (let [selfn (fn [local] (let [id (:edition local)] @@ -85,7 +82,7 @@ content-modifiers (mf/deref content-modifiers-ref) editing-id (mf/deref refs/selected-edition) editing? (= editing-id (:id shape)) - shape (update shape :content gsp/apply-content-modifiers content-modifiers)] + shape (update shape :content ugp/apply-content-modifiers content-modifiers)] [:> shape-container {:shape shape :pointer-events (when editing? "none") @@ -122,69 +119,83 @@ [:div.viewport-actions-entry {:class (when snap-toggled "is-toggled")} i/nodes-snap]]])) -(mf/defc path-preview [{:keys [zoom command from]}] - (when (not= :move-to (:command command)) - [:path {:style {:fill "transparent" - :stroke secondary-color - :stroke-width (/ 1 zoom)} - :d (ugp/content->path [{:command :move-to - :params {:x (:x from) - :y (:y from)}} - command])}])) - -(mf/defc path-point [{:keys [index position stroke-color fill-color zoom edit-mode selected]}] +(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path?]}] (let [{:keys [x y]} position - on-click (fn [event] - (cond - (= edit-mode :move) - (do - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (drp/select-node index))))) - on-mouse-down (fn [event] - (cond - (= edit-mode :move) - (do - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (drp/start-move-path-point index)))))] + on-enter + (fn [event] + (st/emit! (drp/path-pointer-enter position))) + + on-leave + (fn [event] + (st/emit! (drp/path-pointer-leave position))) + + on-click + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (and (= edit-mode :move) (not selected?)) + (st/emit! (drp/select-node position)) + + (and (= edit-mode :move) selected?) + (st/emit! (drp/deselect-node position)))) + + on-mouse-down + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (= edit-mode :move) + (st/emit! (drp/start-move-path-point position)) + + (and (= edit-mode :draw) start-path?) + (st/emit! (drp/start-path-from-point position)) + + (and (= edit-mode :draw) (not start-path?)) + (st/emit! (drp/close-path-drag-start position))))] [:g.path-point [:circle.path-point {:cx x :cy y :r (/ 3 zoom) - :style { ;; :cursor cur/resize-alt + :style {:cursor (when (= edit-mode :draw) cur/pen-node) :stroke-width (/ 1 zoom) - :stroke (or stroke-color black-color) - :fill (or fill-color white-color)}}] + :stroke (cond (or selected? hover?) black-color + preview? secondary-color + :else primary-color) + :fill (cond selected? primary-color + :else white-color)}}] [:circle {:cx x :cy y :r (/ 10 zoom) :on-click on-click :on-mouse-down on-mouse-down - :style {:fill "transparent"}}]] - )) + :style {:fill "transparent"}}]])) -(mf/defc path-handler [{:keys [index point handler zoom selected type edit-mode]}] +(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode]}] (when (and point handler) (let [{:keys [x y]} handler - on-click (fn [event] - (cond - (= edit-mode :move) - (do - (dom/stop-propagation event) - (dom/prevent-default event) - (drp/select-handler index type)))) + on-click + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (cond + (= edit-mode :move) + (drp/select-handler index prefix))) - on-mouse-down (fn [event] - (cond - (= edit-mode :move) - (do - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (drp/start-move-handler index type)))))] - [:g.handler {:class (name type)} + on-mouse-down + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (= edit-mode :move) + (st/emit! (drp/start-move-handler index prefix))))] + + [:g.handler {:pointer-events (when (= edit-mode :draw))} [:line {:x1 (:x point) :y1 (:y point) @@ -198,11 +209,12 @@ :width (/ 6 zoom) :height (/ 6 zoom) - :style {;; :cursor cur/resize-alt + :style {:cursor cur/pointer-move :stroke-width (/ 1 zoom) - :stroke (if selected black-color primary-color) - :fill (if selected primary-color white-color)}}] - + :stroke (cond (or selected? hover?) black-color + :else primary-color) + :fill (cond selected? primary-color + :else white-color)}}] [:circle {:cx x :cy y :r (/ 10 zoom) @@ -210,76 +222,78 @@ :on-mouse-down on-mouse-down :style {:fill "transparent"}}]]))) +(mf/defc path-preview [{:keys [zoom command from]}] + [:g.preview {:style {:pointer-events "none"}} + (when (not= :move-to (:command command)) + [:path {:style {:fill "transparent" + :stroke secondary-color + :stroke-width (/ 1 zoom)} + :d (ugp/content->path [{:command :move-to + :params {:x (:x from) + :y (:y from)}} + command])}]) + [:& path-point {:position (:params command) + :preview? true + :zoom zoom}]]) + (mf/defc path-editor [{:keys [shape zoom]}] - (let [{:keys [content]} shape - edit-path-ref (make-edit-path-ref (:id shape)) - {:keys [edit-mode selected drag-handler prev-handler preview content-modifiers]} (mf/deref edit-path-ref) + (let [edit-path-ref (make-edit-path-ref (:id shape)) + {:keys [edit-mode selected drag-handler prev-handler preview content-modifiers last-point]} (mf/deref edit-path-ref) + {:keys [content]} shape selected (or selected #{}) - content (gsp/apply-content-modifiers content content-modifiers) - points (gsp/content->points content) + content (ugp/apply-content-modifiers content content-modifiers) + points (->> content ugp/content->points (into #{})) last-command (last content) - last-p (last points)] + last-p (->> content last ugp/command->point) + handlers (ugp/content->handlers content)] [:g.path-editor (when (and preview (not drag-handler)) - [:g.preview {:style {:pointer-events "none"}} - [:& path-preview {:command preview - :from last-p - :zoom zoom}] - [:& path-point {:position (:params preview) - :fill-color secondary-color - :zoom zoom}]]) + [:& path-preview {:command preview + :from last-p + :zoom zoom}]) - (for [[index [cmd next]] (d/enumerate (d/with-next content))] - (let [point (gpt/point (:params cmd))] - [:g.path-node - (when (= :curve-to (:command cmd)) - [:& path-handler {:point point - :handler (gpt/point (-> cmd :params :c2x) (-> cmd :params :c2y)) - :zoom zoom - :type :prev - :index index - :selected (selected [index :prev]) - :edit-mode edit-mode}]) + (for [position points] + [:g.path-node + [:& path-point {:position position + :selected? false + :zoom zoom + :edit-mode edit-mode + :start-path? (nil? last-point)}] - (when (= :curve-to (:command next)) - [:& path-handler {:point point - :handler (gpt/point (-> next :params :c1x) (-> next :params :c1y)) - :zoom zoom - :type :next - :index index - :selected (selected [index :next]) - :edit-mode edit-mode}]) + [:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")} + (for [[index prefix] (get handlers position)] + (let [command (get content index) + x (get-in command [:params (d/prefix-keyword prefix :x)]) + y (get-in command [:params (d/prefix-keyword prefix :y)]) + handler-position (gpt/point x y)] + [:& path-handler {:point position + :handler handler-position + :index index + :prefix prefix + :zoom zoom + :selected? false + :hover? false + :preview? false + :edit-mode edit-mode}]))]]) - (when (and (= index (dec (count content))) - prev-handler (not drag-handler)) - [:& path-handler {:point point - :handler prev-handler - :zoom zoom - :type :prev - :index index - :selected (selected index) - :edit-mode edit-mode}]) - - [:& path-point {:position point - :stroke-color (when-not (selected index) primary-color) - :fill-color (when (selected index) primary-color) - :index index + (when prev-handler + [:g.prev-handler {:pointer-events "none"} + [:& path-handler {:point last-p + :handler prev-handler :zoom zoom - :edit-mode edit-mode}]])) + :selected false}]]) (when drag-handler - [:g.drag-handler + [:g.drag-handler {:pointer-events "none"} (when (not= :move-to (:command last-command)) [:& path-handler {:point last-p :handler (ugp/opposite-handler last-p drag-handler) :zoom zoom - :type :drag-opposite :selected false}]) [:& path-handler {:point last-p :handler drag-handler :zoom zoom - :type :drag :selected false}]])])) diff --git a/frontend/src/app/util/data.cljs b/frontend/src/app/util/data.cljs index 04e0e518e7..2350262e9d 100644 --- a/frontend/src/app/util/data.cljs +++ b/frontend/src/app/util/data.cljs @@ -248,4 +248,7 @@ ;; nil ;; (throw e#))))))) - +(defn prefix-keyword [prefix kw] + (let [prefix (if (keyword? prefix) (name prefix) prefix) + kw (if (keyword? kw) (name kw) kw)] + (keyword (str prefix kw)))) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index e8d40fff92..601c628748 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -10,7 +10,8 @@ (ns app.util.geom.path (:require [cuerdas.core :as str] - [app.common.data :as d] + [app.util.data :as d] + [app.common.data :as cd] [app.common.geom.point :as gpt] [app.util.geom.path-impl-simplify :as impl-simplify])) @@ -208,8 +209,81 @@ :c2y (:y h2)})) (defn opposite-handler + "Calculates the coordinates of the opposite handler" [point handler] - (let [phv (gpt/to-vec point handler) - opposite (gpt/add point (gpt/negate phv))] - opposite)) + (let [phv (gpt/to-vec point handler)] + (gpt/add point (gpt/negate phv)))) +(defn opposite-handler-keep-distance + "Calculates the coordinates of the opposite handler but keeping the old distance" + [point handler old-opposite] + (let [old-distance (gpt/distance point old-opposite) + phv (gpt/to-vec point handler) + phv2 (gpt/multiply + (gpt/unit (gpt/negate phv)) + (gpt/point old-distance))] + (gpt/add point phv2))) + +(defn apply-content-modifiers [content modifiers] + (letfn [(apply-to-index [content [index params]] + (if (contains? content index) + (cond-> content + (and + (or (:c1x params) (:c1y params) (:c2x params) (:c2y params)) + (= :line-to (get-in content [index :params :command]))) + (-> (assoc-in [index :command] :curve-to) + (assoc-in [index :params] :curve-to) (make-curve-params + (get-in content [index :params]) + (get-in content [(dec index) :params]))) + + (:x params) (update-in [index :params :x] + (:x params)) + (:y params) (update-in [index :params :y] + (:y params)) + + (:c1x params) (update-in [index :params :c1x] + (:c1x params)) + (:c1y params) (update-in [index :params :c1y] + (:c1y params)) + + (:c2x params) (update-in [index :params :c2x] + (:c2x params)) + (:c2y params) (update-in [index :params :c2y] + (:c2y params))) + content))] + (reduce apply-to-index content modifiers))) + +(defn command->point [{{:keys [x y]} :params}] + (gpt/point x y)) + +(defn content->points [content] + (->> content + (map #(when (-> % :params :x) (gpt/point (-> % :params :x) (-> % :params :y)))) + (remove nil?) + (into []))) + +(defn content->handlers [content] + (->> (d/with-prev content) ;; [cmd, prev] + (d/enumerate) ;; [idx [cmd, prev]] + + (mapcat (fn [[index [cur-cmd prev-cmd]]] + (if (and prev-cmd + (= :curve-to (:command cur-cmd))) + (let [cur-pos (command->point cur-cmd) + pre-pos (command->point prev-cmd)] + [[pre-pos [index :c1]] + [cur-pos [index :c2]]]) + []))) + + (group-by first) + (cd/mapm #(mapv second %2)))) + +(defn opposite-index [content index prefix] + (let [point (if (= prefix :c2) + (command->point (nth content index)) + (command->point (nth content (dec index)))) + + handlers (-> (content->handlers content) + (get point)) + + opposite-prefix (if (= prefix :c1) :c2 :c1) + + result (when (<= (count handlers) 2) + (->> handlers + (d/seek (fn [[index prefix]] (= prefix opposite-prefix))) + (first)))] + result)) From b37ee0fcac502d5f8577e69f3352f06837336981 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Nov 2020 08:35:01 +0100 Subject: [PATCH 059/195] :sparkles: Adds comments cursor --- frontend/resources/images/cursors/comments.svg | 4 ++++ frontend/src/app/main/ui/cursors.cljs | 2 +- frontend/src/app/main/ui/workspace/viewport.cljs | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 frontend/resources/images/cursors/comments.svg diff --git a/frontend/resources/images/cursors/comments.svg b/frontend/resources/images/cursors/comments.svg new file mode 100644 index 0000000000..4683f3a2ea --- /dev/null +++ b/frontend/resources/images/cursors/comments.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/app/main/ui/cursors.cljs b/frontend/src/app/main/ui/cursors.cljs index bc60deba4c..24028c30f0 100644 --- a/frontend/src/app/main/ui/cursors.cljs +++ b/frontend/src/app/main/ui/cursors.cljs @@ -35,6 +35,7 @@ (def pointer-node (cursor-ref :pointer-node 0 0 10 32)) (def pointer-move (cursor-ref :pointer-move 0 0 10 42)) (def pen-node (cursor-ref :pen-node 0 0 10 36)) +(def comments (cursor-ref :comments 0 2 20)) (mf/defc debug-preview {::mf/wrap-props false} @@ -58,4 +59,3 @@ [:span {:style {:white-space "nowrap" :margin-right "1rem"}} (pr-str key)]])))])) - diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index fc07ba6dbc..c469e240b5 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -536,12 +536,12 @@ :class (when drawing-tool "drawing") :style {:cursor (cond panning cur/hand - (= drawing-tool :comments) cur/hand + (= drawing-tool :comments) cur/comments (= drawing-tool :frame) cur/create-artboard (= drawing-tool :rect) cur/create-rectangle (= drawing-tool :circle) cur/create-ellipse (or (= drawing-tool :path) drawing-path?) cur/pen - (= drawing-tool :curve)cur/pencil + (= drawing-tool :curve) cur/pencil drawing-tool cur/create-shape :else cur/pointer-inner) :background-color (get options :background "#E8E9EA")} From 25fe4f1269628bb2a5cfeb0e32d3062208436cd3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Nov 2020 09:44:12 +0100 Subject: [PATCH 060/195] :recycle: Fixes after review --- common/app/common/geom/shapes.cljc | 22 ++++--- frontend/resources/images/icons/pen.svg | 57 +------------------ frontend/src/app/main/data/workspace.cljs | 2 +- .../app/main/data/workspace/drawing/path.cljs | 33 ++++------- 4 files changed, 30 insertions(+), 84 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 56fe8ccb6c..5109d9d6af 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -44,18 +44,26 @@ (move shape (gpt/point dx dy)))) ;; --- Resize (Dimensions) -;;; TODO: CHANGE TO USE THE MODIFIERS +;; Fixme: Improve using modifiers instead of calculating the selrect/points (defn resize [shape width height] (us/assert map? shape) (us/assert number? width) (us/assert number? height) - (-> shape - (assoc :width width :height height) - (update :selrect (fn [selrect] - (assoc selrect - :x2 (+ (:x1 selrect) width) - :y2 (+ (:y1 selrect) height)))))) + (let [selrect (-> (:selrect shape) + (assoc :width width) + (assoc :height height) + (assoc :x2 (+ (-> shape :selrect :x1) width)) + (assoc :y2 (+ (-> shape :selrect :y1) height))) + + center (gco/center-selrect selrect) + points (-> selrect gpr/rect->points (gtr/transform-points center (:transform shape)))] + + (-> shape + (assoc :width width) + (assoc :height height) + (assoc :selrect selrect) + (assoc :points points)))) (defn resize-rect [shape attr value] diff --git a/frontend/resources/images/icons/pen.svg b/frontend/resources/images/icons/pen.svg index 9cd7833552..cc3c91147f 100644 --- a/frontend/resources/images/icons/pen.svg +++ b/frontend/resources/images/icons/pen.svg @@ -1,56 +1,3 @@ - - - - - - image/svg+xml - - - - - - - + + diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index c760d812c3..f75a89a672 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1662,7 +1662,7 @@ "e" #(st/emit! (dwd/select-for-drawing :circle)) "t" #(st/emit! dwtxt/start-edit-if-selected (dwd/select-for-drawing :text)) - "w" #(st/emit! (dwd/select-for-drawing :path)) + "p" #(st/emit! (dwd/select-for-drawing :path)) "ctrl+c" #(st/emit! copy-selected) "ctrl+v" #(st/emit! paste) "ctrl+x" #(st/emit! copy-selected delete-selected) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 0cc24d467b..024e6baeed 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -101,12 +101,7 @@ ;; EVENTS (defn init-path [id] - (ptk/reify ::init-path - ptk/UpdateEvent - (update [_ state] - (-> state - #_(assoc-in [:workspace-drawing :object :initialized?] true) - #_(assoc-in [:workspace-local :edit-path :last-point] nil))))) + (ptk/reify ::init-path)) (defn finish-path [id] (ptk/reify ::finish-path @@ -347,13 +342,11 @@ (make-drag-stream stream %) (make-dbl-click-stream stream %))))] - (->> (rx/concat - (rx/of (init-path id)) - (rx/merge mousemove-events - mousedown-events) - (rx/of (finish-path id)))))))) - - + (rx/concat + (rx/of (init-path id)) + (rx/merge mousemove-events + mousedown-events) + (rx/of (finish-path id))))))) (defn stop-path-edit [] (ptk/reify ::stop-path-edit @@ -417,13 +410,13 @@ (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) page-id (:current-page-id state) - old-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) - old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) - old-points (get-in state [:workspace-data :pages-index page-id :objects id :points]) - content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) + shape (get-in state [:workspace-data :pages-index page-id :objects id]) + {old-content :content old-selrect :selrect old-points :points} shape + content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers] {}) new-content (ugp/apply-content-modifiers old-content content-modifiers) new-selrect (gsh/content->selrect new-content) new-points (gsh/rect->points new-selrect) + rch [{:type :mod-obj :id id :page-id page-id @@ -456,9 +449,8 @@ old-content (get-in state [:workspace-local :edit-path id :old-content]) old-selrect (gsh/content->selrect old-content) old-points (gsh/rect->points old-content) - new-content (get-in state [:workspace-data :pages-index page-id :objects id :content]) - new-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect]) - new-points (get-in state [:workspace-data :pages-index page-id :objects id :points]) + shape (get-in state [:workspace-data :pages-index page-id :objects id]) + {new-content :content new-selrect :selrect new-points :points} shape rch [{:type :mod-obj :id id @@ -491,7 +483,6 @@ content (get-in state (get-path state :content)) old-content (get-in state [:workspace-local :edit-path id :old-content]) mode (get-in state [:workspace-local :edit-path id :edit-mode])] - (cond (not= content old-content) (rx/of (save-path-content) From 0fcfd30535ee7fa3b882b304d4a35ef0bc5ef4f5 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Nov 2020 17:13:44 +0100 Subject: [PATCH 061/195] :bug: Fixes problems with previous migration --- common/app/common/geom/point.cljc | 19 +++++++++++-------- common/app/common/pages.cljc | 2 +- common/app/common/pages_migrations.cljc | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index 8ca2bb45bc..0d13aa542a 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -148,14 +148,17 @@ (assert (point? p)) (assert (point? other)) - (let [a (/ (+ (* x ox) - (* y oy)) - (* (length p) - (length other))) - a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a))) - d (-> (mth/degrees a) - (mth/precision 6))] - (if (mth/nan? d) 0 d))) + (if (or (= 0 (length p)) + (= 0 (length other))) + 0 + (let [a (/ (+ (* x ox) + (* y oy)) + (* (length p) + (length other))) + a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a))) + d (-> (mth/degrees a) + (mth/precision 6))] + (if (mth/nan? d) 0 d)))) (defn update-angle diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 52accc13e0..7b996b8fd6 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -20,7 +20,7 @@ [app.common.spec :as us] [app.common.uuid :as uuid])) -(def file-version 3) +(def file-version 4) (def max-safe-int 9007199254740991) (def min-safe-int -9007199254740991) diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index 75697f5e37..e36ca0f5b3 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -109,3 +109,18 @@ (update page :objects #(d/mapm update-object %)))] (update data :pages-index #(d/mapm update-page %)))) + +(defmethod migrate 4 + [data] + (letfn [(update-object [id object] + (cond-> object + (= (:id object) uuid/zero) + (assoc :points [] + :selrect {:x 0 :y 0 + :width 1 :height 1 + :x1 0 :y1 0 + :x2 1 :y2 1}))) + + (update-page [id page] + (update page :objects #(d/mapm update-object %)))] + (update data :pages-index #(d/mapm update-page %)))) From d2806fd9ba84fc0d27c30954021d9d44a9f86ad5 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Nov 2020 17:31:22 +0100 Subject: [PATCH 062/195] :bug: Fixes problem with schema and parameters --- common/app/common/pages.cljc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 7b996b8fd6..a0a53d2a51 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -273,9 +273,9 @@ (s/every uuid? :kind vector?)) (s/def ::shape-attrs - (s/keys :req-un [:internal.shape/selrect - :internal.shape/points] - :opt-un [:internal.shape/blocked + (s/keys :opt-un [:internal.shape/selrect + :internal.shape/points + :internal.shape/blocked :internal.shape/collapsed :internal.shape/content :internal.shape/fill-color @@ -351,7 +351,9 @@ ::component-id ::component-file ::component-root? - ::shape-ref]))) + ::shape-ref] + :req-un [:internal.shape/selrect + :internal.shape/points]))) (s/def :internal.page/objects (s/map-of uuid? ::shape)) From 3543acbac720369fba7a1203b1dc5d84fd3224bf Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Nov 2020 18:01:50 +0100 Subject: [PATCH 063/195] :bug: Fixed schema for shapes --- common/app/common/pages.cljc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index a0a53d2a51..311d9e9673 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -351,9 +351,7 @@ ::component-id ::component-file ::component-root? - ::shape-ref] - :req-un [:internal.shape/selrect - :internal.shape/points]))) + ::shape-ref]))) (s/def :internal.page/objects (s/map-of uuid? ::shape)) From 912be764003238207fb7528504c4d943478873bb Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 25 Nov 2020 09:57:52 +0100 Subject: [PATCH 064/195] :bug: Fixed problem with divide by zero --- common/app/common/geom/point.cljc | 23 ++++++++++--------- common/app/common/geom/shapes/transforms.cljc | 2 +- common/app/common/pages_migrations.cljc | 17 +++----------- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index 0d13aa542a..1f97b31744 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -148,17 +148,18 @@ (assert (point? p)) (assert (point? other)) - (if (or (= 0 (length p)) - (= 0 (length other))) - 0 - (let [a (/ (+ (* x ox) - (* y oy)) - (* (length p) - (length other))) - a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a))) - d (-> (mth/degrees a) - (mth/precision 6))] - (if (mth/nan? d) 0 d)))) + (let [length-p (length p) + length-other (length other)] + (if (or (mth/almost-zero? length-p) + (mth/almost-zero? length-other)) + 0 + (let [a (/ (+ (* x ox) + (* y oy)) + (* length-p length-other)) + a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a))) + d (-> (mth/degrees a) + (mth/precision 6))] + (if (mth/nan? d) 0 d))))) (defn update-angle diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index ec5e51f4ac..deebb59667 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -167,7 +167,7 @@ h1 (calculate-height points-temp) h2 (calculate-height (transform-points points-rec center stretch-matrix)) - h3 (/ h1 h2) + h3 (if-not (mth/almost-zero? h2) (/ h1 h2) 1) h3 (if (mth/nan? h3) 1 h3) stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 h3))) diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index e36ca0f5b3..257d135b52 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -110,17 +110,6 @@ (update data :pages-index #(d/mapm update-page %)))) -(defmethod migrate 4 - [data] - (letfn [(update-object [id object] - (cond-> object - (= (:id object) uuid/zero) - (assoc :points [] - :selrect {:x 0 :y 0 - :width 1 :height 1 - :x1 0 :y1 0 - :x2 1 :y2 1}))) - - (update-page [id page] - (update page :objects #(d/mapm update-object %)))] - (update data :pages-index #(d/mapm update-page %)))) +;; We did rollback version 4 migration. +;; Keep this in order to remember the next version to be 5 +(defmethod migrate 4 [data] data) From ebb7410e5b84681c1b032819488eaf8a66eefebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 11 Nov 2020 13:03:24 +0100 Subject: [PATCH 065/195] :sparkles: Synchronize add/delete/move shapes in componentes --- backend/src/app/services/mutations/files.clj | 3 +- common/app/common/pages.cljc | 79 +- common/app/common/pages_helpers.cljc | 46 +- .../app/main/data/workspace/libraries.cljs | 27 +- .../data/workspace/libraries_helpers.cljs | 890 +++++++++++------- 5 files changed, 640 insertions(+), 405 deletions(-) diff --git a/backend/src/app/services/mutations/files.clj b/backend/src/app/services/mutations/files.clj index 27da20bd5f..38d971c0e3 100644 --- a/backend/src/app/services/mutations/files.clj +++ b/backend/src/app/services/mutations/files.clj @@ -251,7 +251,8 @@ :add-media :mod-media :del-media :add-component :mod-component :del-component :add-typography :mod-typography :del-typography} (:type change)) - (and (= (:type change) :mod-obj) + (and (#{:add-obj :mod-obj :del-obj + :reg-objects :mov-objects} (:type change)) (some? (:component-id change))))) (declare update-file) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 311d9e9673..0d59551c8f 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -435,6 +435,14 @@ :internal.file/recent-colors :internal.file/media])) +(s/def ::container-type #{:page :component}) + +(s/def ::container + (s/keys :req-un [::container-type + ::id + ::name + :internal.page/objects])) + (defmulti operation-spec :type) (s/def :internal.operations.set/attr keyword?) @@ -461,9 +469,9 @@ (s/def :internal.changes.add-obj/obj ::shape) (defmethod change-spec :add-obj [_] - (s/keys :req-un [::id ::page-id ::frame-id + (s/keys :req-un [::id (or ::page-id ::component-id) :internal.changes.add-obj/obj] - :opt-un [::parent-id])) + :opt-un [::parent-id ::frame-id])) (s/def ::operation (s/multi-spec operation-spec :type)) (s/def ::operations (s/coll-of ::operation)) @@ -472,16 +480,17 @@ (s/keys :req-un [::id (or ::page-id ::component-id) ::operations])) (defmethod change-spec :del-obj [_] - (s/keys :req-un [::id ::page-id])) + (s/keys :req-un [::id (or ::page-id ::component-id)])) (s/def :internal.changes.reg-objects/shapes (s/coll-of uuid? :kind vector?)) (defmethod change-spec :reg-objects [_] - (s/keys :req-un [::page-id :internal.changes.reg-objects/shapes])) + (s/keys :req-un [(or ::page-id ::component-id) + :internal.changes.reg-objects/shapes])) (defmethod change-spec :mov-objects [_] - (s/keys :req-un [::page-id ::parent-id :internal.shape/shapes] + (s/keys :req-un [(or ::page-id ::component-id) ::parent-id :internal.shape/shapes] :opt-un [::index])) (defmethod change-spec :add-page [_] @@ -701,26 +710,26 @@ (assoc data :options (d/dissoc-in (:options data) path))))))) (defmethod process-change :add-obj - [data {:keys [id obj page-id frame-id parent-id index] :as change}] - (d/update-in-when data [:pages-index page-id] - (fn [data] - (let [parent-id (or parent-id frame-id) - objects (:objects data)] - (when (and (contains? objects parent-id) - (contains? objects frame-id)) - (let [obj (assoc obj - :frame-id frame-id - :parent-id parent-id - :id id)] - (-> data - (update :objects assoc id obj) - (update-in [:objects parent-id :shapes] - (fn [shapes] - (let [shapes (or shapes [])] - (cond - (some #{id} shapes) shapes - (nil? index) (conj shapes id) - :else (cph/insert-at-index shapes index [id])))))))))))) + [data {:keys [id obj page-id component-id frame-id parent-id index] :as change}] + (let [update-fn (fn [data] + (let [parent-id (or parent-id frame-id) + objects (:objects data)] + (let [obj (assoc obj + :frame-id frame-id + :parent-id parent-id + :id id)] + (-> data + (update :objects assoc id obj) + (update-in [:objects parent-id :shapes] + (fn [shapes] + (let [shapes (or shapes [])] + (cond + (some #{id} shapes) shapes + (nil? index) (conj shapes id) + :else (cph/insert-at-index shapes index [id])))))))))] + (if page-id + (d/update-in-when data [:pages-index page-id] update-fn) + (d/update-in-when data [:components component-id] update-fn)))) (defmethod process-change :mod-obj [data {:keys [id page-id component-id operations] :as change}] @@ -733,8 +742,8 @@ (d/update-in-when data [:components component-id :objects] update-fn)))) (defmethod process-change :del-obj - [data {:keys [page-id id] :as change}] - (letfn [(delete-object [objects id] + [data {:keys [page-id component-id id] :as change}] + (letfn [(delete-object [objects] (if-let [target (get objects id)] (let [parent-id (cph/get-parent id objects) frame-id (:frame-id target) @@ -752,7 +761,9 @@ ; dependend objects (as-> $ (reduce delete-object $ (:shapes target))))) objects))] - (d/update-in-when data [:pages-index page-id :objects] delete-object id))) + (if page-id + (d/update-in-when data [:pages-index page-id :objects] delete-object) + (d/update-in-when data [:components component-id :objects] delete-object)))) (defn rotation-modifiers [center shape angle] @@ -765,7 +776,7 @@ ;; reg-objects operation "regenerates" the values for the parent groups (defmethod process-change :reg-objects - [data {:keys [page-id shapes]}] + [data {:keys [page-id component-id shapes]}] (letfn [(reg-objects [objects] (reduce #(update %1 %2 update-group %1) objects (sequence (comp @@ -797,10 +808,12 @@ (assoc-in [:modifiers :rotation] (:rotation group 0)) (geom/transform-shape))))] - (d/update-in-when data [:pages-index page-id :objects] reg-objects))) + (if page-id + (d/update-in-when data [:pages-index page-id :objects] reg-objects) + (d/update-in-when data [:components component-id :objects] reg-objects)))) (defmethod process-change :mov-objects - [data {:keys [parent-id shapes index page-id] :as change}] + [data {:keys [parent-id shapes index page-id component-id] :as change}] (letfn [(is-valid-move? [objects shape-id] (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] (and (not (invalid-targets parent-id)) @@ -881,7 +894,9 @@ (reduce (partial update-frame-ids frm-id) $ (get-in $ [parent-id :shapes]))) objects)))] - (d/update-in-when data [:pages-index page-id :objects] move-objects))) + (if page-id + (d/update-in-when data [:pages-index page-id :objects] move-objects) + (d/update-in-when data [:components component-id :objects] move-objects)))) (defmethod process-change :add-page [data {:keys [id name page]}] diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index e9722ec2dc..9683e9369f 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -42,11 +42,25 @@ objects) nil))) +(defn make-container + [page-or-component container-type] + (assoc page-or-component + :container-type container-type)) + +(defn is-page + [container] + (= (:container-type container) :page)) + +(defn is-component + [container] + (= (:container-type container) :component)) + (defn get-container - [page-id component-id local-file] - (if (some? page-id) - (get-in local-file [:pages-index page-id]) - (get-in local-file [:components component-id]))) + [container-id container-type local-file] + (-> (if (= container-type :page) + (get-in local-file [:pages-index container-id]) + (get-in local-file [:components container-id])) + (assoc :container-type container-type))) (defn get-shape [container shape-id] @@ -59,6 +73,12 @@ (get-in libraries [file-id :data]))] (get-in file [:components component-id]))) +(defn is-master-of + [shape-master shape-inst] + (and (:shape-ref shape-inst) + (or (= (:shape-ref shape-inst) (:id shape-master)) + (= (:shape-ref shape-inst) (:shape-ref shape-master))))) + (defn get-component-root [component] (get-in component [:objects (:id component)])) @@ -75,12 +95,12 @@ (defn get-children-objects "Retrieve all children objects recursively for a given object" [id objects] - (map #(get objects %) (get-children id objects))) + (mapv #(get objects %) (get-children id objects))) (defn get-object-with-children - "Retrieve a list with an object and all of its children" + "Retrieve a vector with an object and all of its children" [id objects] - (map #(get objects %) (cons id (get-children id objects)))) + (mapv #(get objects %) (cons id (get-children id objects)))) (defn is-shape-grouped "Checks if a shape is inside a group" @@ -210,17 +230,17 @@ :parent-id parent-id) (some? (:shapes object)) - (assoc :shapes (map :id new-direct-children))) + (assoc :shapes (mapv :id new-direct-children))) new-object (update-new-object new-object object) - new-objects (concat [new-object] new-children) + new-objects (d/concat [new-object] new-children) updated-object (update-original-object object new-object) updated-objects (if (identical? object updated-object) updated-children - (concat [updated-object] updated-children))] + (d/concat [updated-object] updated-children))] [new-object new-objects updated-objects]) @@ -232,9 +252,9 @@ (recur (next child-ids) - (concat new-direct-children [new-child]) - (concat new-children new-child-objects) - (concat updated-children updated-child-objects)))))))) + (d/concat new-direct-children [new-child]) + (d/concat new-children new-child-objects) + (d/concat updated-children updated-child-objects)))))))) (defn indexed-shapes diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 9bcf04238b..77d9879705 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -32,6 +32,7 @@ [cljs.spec.alpha :as s] [potok.core :as ptk])) +;; Change this to :info :debug or :trace to debug this module (log/set-level! :warn) (declare sync-file) @@ -493,16 +494,18 @@ (ptk/reify ::reset-component ptk/WatchEvent (watch [_ state stream] - ;; ===== Uncomment this to debug ===== (log/info :msg "RESET-COMPONENT of shape" :id (str id)) - (let [[rchanges uchanges] - (dwlh/generate-sync-shape-and-children-components (get state :current-page-id) - nil - id - (get state :workspace-data) - (get state :workspace-libraries) - true)] - ;; ===== Uncomment this to debug ===== + (let [local-file (get state :workspace-data) + libraries (get state :workspace-libraries) + container (cph/get-container (get state :current-page-id) + :page + local-file) + [rchanges uchanges] + (dwlh/generate-sync-shape-direct container + id + local-file + libraries + true)] (log/debug :msg "RESET-COMPONENT finished" :js/rchanges rchanges) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) @@ -516,7 +519,6 @@ (ptk/reify ::update-component ptk/WatchEvent (watch [_ state stream] - ;; ===== Uncomment this to debug ===== (log/info :msg "UPDATE-COMPONENT of shape" :id (str id)) (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) @@ -529,7 +531,6 @@ (get state :workspace-data) (get state :workspace-libraries))] - ;; ===== Uncomment this to debug ===== (log/debug :msg "UPDATE-COMPONENT finished" :js/rchanges rchanges) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) @@ -552,7 +553,6 @@ ptk/WatchEvent (watch [_ state stream] - ;; ===== Uncomment this to debug ===== (log/info :msg "SYNC-FILE" :file (str (or file-id "local"))) (let [library-changes [(dwlh/generate-sync-library :components file-id state) (dwlh/generate-sync-library :colors file-id state) @@ -566,7 +566,6 @@ uchanges (d/concat [] (->> library-changes (remove nil?) (map second) (flatten)) (->> file-changes (remove nil?) (map second) (flatten)))] - ;; ===== Uncomment this to debug ===== (log/debug :msg "SYNC-FILE finished" :js/rchanges rchanges) (rx/concat (rx/of (dm/hide-tag :sync-dialog)) @@ -593,14 +592,12 @@ (ptk/reify ::sync-file-2nd-stage ptk/WatchEvent (watch [_ state stream] - ;; ===== Uncomment this to debug ===== (log/info :msg "SYNC-FILE (2nd stage)" :file (str (or file-id "local"))) (let [[rchanges1 uchanges1] (dwlh/generate-sync-file :components nil state) [rchanges2 uchanges2] (dwlh/generate-sync-library :components file-id state) rchanges (d/concat rchanges1 rchanges2) uchanges (d/concat uchanges1 uchanges2)] (when rchanges - ;; ===== Uncomment this to debug ===== (log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges rchanges) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 9298399738..42ff924792 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -18,6 +18,7 @@ [app.util.logging :as log] [app.util.text :as ut])) +;; Change this to :info :debug or :trace to debug this module (log/set-level! :warn) (defonce empty-changes [[] []]) @@ -36,14 +37,17 @@ (declare has-asset-reference-fn) (declare get-assets) -(declare generate-sync-shape-and-children-components) -(declare generate-sync-shape-and-children-normal) -(declare generate-sync-shape-and-children-nested) +(declare generate-sync-shape-direct) +(declare generate-sync-shape-direct-recursive) (declare generate-sync-shape-inverse) -(declare generate-sync-shape-inverse-normal) -(declare generate-sync-shape-inverse-nested) -(declare generate-sync-shape<-component) -(declare generate-sync-shape->component) +(declare generate-sync-shape-inverse-recursive) + +(declare compare-children) +(declare concat-changes) +(declare add-shape-to-instance) +(declare add-shape-to-master) +(declare remove-shape) +(declare move-shape) (declare remove-component-and-ref) (declare remove-ref) (declare reset-touched) @@ -133,9 +137,7 @@ (generate-sync-container asset-type library-id state - page - (:id page) - nil)] + (cph/make-container page :page))] (recur (next pages) (d/concat rchanges page-rchanges) (d/concat uchanges page-uchanges))) @@ -165,9 +167,8 @@ (generate-sync-container asset-type library-id state - local-component - nil - (:id local-component))] + (cph/make-container local-component + :component))] (recur (next local-components) (d/concat rchanges comp-rchanges) (d/concat uchanges comp-uchanges))) @@ -176,11 +177,11 @@ (defn- generate-sync-container "Generate changes to synchronize all shapes in a particular container (a page or a component) that are linked to the given library." - [asset-type library-id state container page-id component-id] + [asset-type library-id state container] - (if page-id - (log/debug :msg "Sync page in local file" :page-id page-id) - (log/debug :msg "Sync component in local library" :component-id component-id)) + (if (= (:container-type container) :page) + (log/debug :msg "Sync page in local file" :page-id (:id container)) + (log/debug :msg "Sync component in local library" :component-id (:id container))) (let [has-asset-reference? (has-asset-reference-fn asset-type library-id) linked-shapes (cph/select-objects has-asset-reference? container)] @@ -192,9 +193,7 @@ (generate-sync-shape asset-type library-id state - (get container :objects) - page-id - component-id + container shape)] (recur (next shapes) (d/concat rchanges shape-rchanges) @@ -241,16 +240,15 @@ (defmulti generate-sync-shape "Generate changes to synchronize one shape, that use the given type of asset of the given library." - (fn [type _ _ _ _ _ _ _] type)) + (fn [type _ _ _ _] type)) (defmethod generate-sync-shape :components - [_ library-id state objects page-id component-id shape] - (generate-sync-shape-and-children-components page-id - component-id - (:id shape) - (get state :workspace-data) - (get state :workspace-libraries) - false)) + [_ library-id state container shape] + (generate-sync-shape-direct container + (:id shape) + (get state :workspace-data) + (get state :workspace-libraries) + false)) (defn- generate-sync-text-shape [shape page-id component-id update-node] (let [old-content (:content shape) @@ -275,11 +273,13 @@ (defmethod generate-sync-shape :colors - [_ library-id state _ page-id component-id shape] + [_ library-id state container shape] ;; Synchronize a shape that uses some colors of the library. The value of the ;; color in the library is copied to the shape. - (let [colors (get-assets library-id :colors state)] + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container)) + colors (get-assets library-id :colors state)] (if (= :text (:type shape)) (let [update-node (fn [node] (if-let [color (get colors (:fill-color-ref-id node))] @@ -325,11 +325,13 @@ (conj uoperations uoperation)))))))))) (defmethod generate-sync-shape :typographies - [_ library-id state _ page-id component-id shape] + [_ library-id state container shape] ;; Synchronize a shape that uses some typographies of the library. The attributes ;; of the typography are copied to the shape." - (let [typographies (get-assets library-id :typographies state) + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container)) + typographies (get-assets library-id :typographies state) update-node (fn [node] (if-let [typography (get typographies (:typography-ref-id node))] (merge node (d/without-keys typography [:name :id])) @@ -345,7 +347,7 @@ (get-in state [:workspace-data asset-type]) (get-in state [:workspace-libraries library-id :data asset-type]))) -(defn generate-sync-shape-and-children-components +(defn generate-sync-shape-direct "Generate changes to synchronize one shape that the root of a component instance, and all its children, from the given component. If reset? is false, all atributes of each component shape that have @@ -353,121 +355,99 @@ be copied to this one. If reset? is true, all changed attributes will be copied and the 'touched' flags in the instance shape will be cleared." - [page-id component-id shape-id local-file libraries reset?] - (log/debug :msg "Sync shape and children" :shape (str shape-id) :reset? reset?) - (let [container (cph/get-container page-id component-id local-file) - shape (cph/get-shape container shape-id) - component (cph/get-component (:component-id shape) - (:component-file shape) - local-file - libraries) - root-shape shape - root-component (cph/get-component-root component)] + [container shape-id local-file libraries reset?] + (log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?) + (let [shape-inst (cph/get-shape container shape-id) + component (cph/get-component (:component-id shape-inst) + (:component-file shape-inst) + local-file + libraries) + shape-master (cph/get-shape component (:shape-ref shape-inst)) - (generate-sync-shape-and-children-normal page-id - component-id - container - shape - component - root-shape - root-component - reset?))) + root-inst shape-inst + root-master (cph/get-component-root component)] -(defn- generate-sync-shape-and-children-normal - [page-id component-id container shape component root-shape root-component reset?] - (log/trace :msg "Sync shape (normal)" - :shape (str (:name shape)) + (generate-sync-shape-direct-recursive container + shape-inst + component + shape-master + root-inst + root-master + {:omit-touched? (not reset?) + :reset-touched? reset? + :set-touched? false}))) + +(defn- generate-sync-shape-direct-recursive + [container shape-inst component shape-master root-inst root-master options] + (log/trace :msg "Sync shape direct" + :shape (str (:name shape-inst)) :component (:name component)) - (let [[rchanges uchanges] - (generate-sync-shape<-component shape - root-shape - root-component - component - page-id - component-id - reset?) - children-ids (get shape :shapes [])] - - (loop [children-ids (seq children-ids) - rchanges rchanges - uchanges uchanges] - (let [child-id (first children-ids)] - (if (nil? child-id) - [rchanges uchanges] - (let [child-shape (cph/get-shape container child-id) - - [child-rchanges child-uchanges] - (if (nil? (:component-id child-shape)) - (generate-sync-shape-and-children-normal page-id - component-id - container - child-shape - component - root-shape - root-component - reset?) - (generate-sync-shape-and-children-nested page-id - component-id - container - child-shape - component - root-shape - root-component - reset?))] - (recur (next children-ids) - (d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)))))))) - -(defn- generate-sync-shape-and-children-nested - [page-id component-id container shape component root-shape root-component reset?] - (log/trace :msg "Sync shape (nested)" - :shape (str (:name shape)) - :component (:name component)) - (let [component-shape (d/seek #(= (:shape-ref %) - (:shape-ref shape)) - (vals (:objects component))) - root-shape (if (:component-id shape) - shape - root-shape) - root-component (if (:component-id shape) - component-shape - root-component) + (let [root-inst (if (:component-id shape-inst) + shape-inst + root-inst) + root-master (if (:component-id shape-inst) + shape-master + root-master) [rchanges uchanges] - (update-attrs shape - component-shape - root-shape - root-component - page-id - component-id - {:omit-touched? false - :reset-touched? false - :set-touched? false - :copy-touched? true}) + (update-attrs shape-inst + shape-master + root-inst + root-master + container + options) - children-ids (get shape :shapes [])] + children-inst (mapv #(cph/get-shape container %) + (:shapes shape-inst)) + children-master (mapv #(cph/get-shape component %) + (:shapes shape-master)) - (loop [children-ids (seq children-ids) - rchanges rchanges - uchanges uchanges] - (let [child-id (first children-ids)] - (if (nil? child-id) - [rchanges uchanges] - (let [child-shape (cph/get-shape container child-id) + only-inst (fn [shape-inst] + (remove-shape shape-inst + container)) - [child-rchanges child-uchanges] - (generate-sync-shape-and-children-nested page-id - component-id - container - child-shape - component - root-shape - root-component - reset?)] - (recur (next children-ids) - (d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)))))))) + only-master (fn [shape-master] + (add-shape-to-instance shape-master + component + container + root-inst + root-master)) + + both (fn [shape-inst shape-master] + (let [options (if-not (:component-id shape-inst) + options + {:omit-touched? false + :reset-touched? false + :set-touched? false + :copy-touched? true})] + + (generate-sync-shape-direct-recursive container + shape-inst + component + shape-master + root-inst + root-master + options))) + + moved (fn [shape-inst shape-master] + (move-shape + shape-inst + (d/index-of children-inst shape-inst) + (d/index-of children-master shape-master) + container)) + + [child-rchanges child-uchanges] + (compare-children children-inst + children-master + only-inst + only-master + both + moved + false)] + + [(d/concat rchanges child-rchanges) + (d/concat uchanges child-uchanges)])) (defn- generate-sync-shape-inverse "Generate changes to update the component a shape is linked to, from @@ -478,229 +458,448 @@ And if the component shapes are, in turn, instances of a second component, their 'touched' flags will be set accordingly." [page-id shape-id local-file libraries] - (log/debug :msg "Sync inverse shape and children" :shape (str shape-id)) - (let [page (cph/get-container page-id nil local-file) - shape (cph/get-shape page shape-id) - component (cph/get-component (:component-id shape) - (:component-file shape) + (log/debug :msg "Sync shape inverse" :shape (str shape-id)) + (let [container (cph/get-container page-id :page local-file) + shape-inst (cph/get-shape container shape-id) + component (cph/get-component (:component-id shape-inst) + (:component-file shape-inst) local-file libraries) - root-shape shape - root-component (cph/get-component-root component)] + shape-master (cph/get-shape component (:shape-ref shape-inst)) - (generate-sync-shape-inverse-normal page - shape - component - root-shape - root-component))) + root-inst shape-inst + root-master (cph/get-component-root component)] -(defn- generate-sync-shape-inverse-normal - [page shape component root-shape root-component] - (log/trace :msg "Sync shape inverse (normal)" - :shape (str (:name shape)) + (generate-sync-shape-inverse-recursive container + shape-inst + component + shape-master + root-inst + root-master + {:omit-touched? false + :reset-touched? false + :set-touched? true}))) + +(defn- generate-sync-shape-inverse-recursive + [container shape-inst component shape-master root-inst root-master options] + (log/trace :msg "Sync shape inverse" + :shape (str (:name shape-inst)) :component (:name component)) - (let [[rchanges uchanges] - (generate-sync-shape->component shape - root-shape - root-component - component - (:id page)) - children-ids (get shape :shapes [])] + (let [root-inst (if (:component-id shape-inst) + shape-inst + root-inst) + root-master (if (:component-id shape-inst) + shape-master + root-master) - (loop [children-ids (seq children-ids) - rchanges rchanges - uchanges uchanges] - (let [child-id (first children-ids)] - (if (nil? child-id) - [rchanges uchanges] - (let [child-shape (cph/get-shape page child-id) - - [child-rchanges child-uchanges] - (if (nil? (:component-id child-shape)) - (generate-sync-shape-inverse-normal page - child-shape - component - root-shape - root-component) - (generate-sync-shape-inverse-nested page - child-shape - component - root-shape - root-component))] - (recur (next children-ids) - (d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)))))))) - -(defn- generate-sync-shape-inverse-nested - [page shape component root-shape root-component] - (log/trace :msg "Sync shape inverse (nested)" - :shape (str (:name shape)) - :component (:name component)) - (let [component-shape (d/seek #(= (:shape-ref %) - (:shape-ref shape)) - (vals (:objects component))) - root-shape (if (:component-id shape) - shape - root-shape) - root-component (if (:component-id shape) - component-shape - root-component) + component-container (cph/make-container component :component) [rchanges uchanges] - (update-attrs component-shape - shape - root-component - root-shape - nil - (:id component) - {:omit-touched? false - :reset-touched? false - :set-touched? false - :copy-touched? true}) + (concat-changes + (update-attrs shape-master + shape-inst + root-master + root-inst + component-container + options) + (if (:set-touched? options) + (reset-touched shape-inst container) + empty-changes)) - children-ids (get shape :shapes [])] + children-inst (mapv #(cph/get-shape container %) + (:shapes shape-inst)) + children-master (mapv #(cph/get-shape component %) + (:shapes shape-master)) - (loop [children-ids (seq children-ids) - rchanges rchanges - uchanges uchanges] - (let [child-id (first children-ids)] - (if (nil? child-id) - [rchanges uchanges] - (let [child-shape (cph/get-shape page child-id) + only-inst (fn [shape-inst] + (add-shape-to-master shape-inst + component + container + root-inst + root-master)) - [child-rchanges child-uchanges] - (generate-sync-shape-inverse-nested page - child-shape - component - root-shape - root-component)] - (recur (next children-ids) - (d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)))))))) + only-master (fn [shape-master] + (remove-shape shape-master + component-container)) -(defn- generate-sync-shape<-component - "Generate changes to synchronize one shape that is linked to other shape - inside a component. Same considerations as above about reset-touched?" - [shape root-shape root-component component page-id component-id reset?] - (if (nil? component) - (remove-component-and-ref shape page-id component-id) - (let [component-shape (get (:objects component) (:shape-ref shape))] - (if (nil? component-shape) - (remove-ref shape page-id component-id) - (update-attrs shape - component-shape - root-shape - root-component - page-id - component-id - {:omit-touched? (not reset?) - :reset-touched? reset? - :set-touched? false}))))) + both (fn [shape-inst shape-master] + (let [options (if-not (:component-id shape-inst) + options + {:omit-touched? false + :reset-touched? false + :set-touched? false + :copy-touched? true})] -(defn- generate-sync-shape->component - "Generate changes to synchronize one shape inside a component, with other - shape that is linked to it." - [shape root-shape root-component component page-id] - (if (nil? component) - empty-changes - (let [component-shape (get (:objects component) (:shape-ref shape))] - (if (nil? component-shape) - empty-changes - (let [[rchanges1 uchanges1] - (update-attrs component-shape - shape - root-component - root-shape - nil - (:id root-component) - {:omit-touched? false - :reset-touched? false - :set-touched? true}) - [rchanges2 uchanges2] - (reset-touched shape - page-id - nil)] - [(d/concat rchanges1 rchanges2) - (d/concat uchanges2 uchanges2)]))))) + (generate-sync-shape-inverse-recursive container + shape-inst + component + shape-master + root-inst + root-master + options))) + + moved (fn [shape-inst shape-master] + (move-shape + shape-master + (d/index-of children-master shape-master) + (d/index-of children-inst shape-inst) + component-container)) + + [child-rchanges child-uchanges] + (compare-children children-inst + children-master + only-inst + only-master + both + moved + true)] + + [(d/concat rchanges child-rchanges) + (d/concat uchanges child-uchanges)])) ; ---- Operation generation helpers ---- -(defn- remove-component-and-ref - [shape page-id component-id] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :component-root? - :val nil} - {:type :set - :attr :component-id - :val nil} - {:type :set - :attr :component-file - :val nil} - {:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :component-root? - :val (:component-root? shape)} - {:type :set - :attr :component-id - :val (:component-id shape)} - {:type :set - :attr :component-file - :val (:component-file shape)} - {:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]})]]) +(defn- compare-children + [children-inst children-master only-inst-cb only-master-cb both-cb moved-cb inverse?] + (loop [children-inst (seq (or children-inst [])) + children-master (seq (or children-master [])) + [rchanges uchanges] [[] []]] + (let [child-inst (first children-inst) + child-master (first children-master)] + (cond + (and (nil? child-inst) (nil? child-master)) + [rchanges uchanges] -(defn- -remove-ref - [shape page-id component-id] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]})]]) + (nil? child-inst) + (reduce (fn [changes child] + (concat-changes changes (only-master-cb child))) + [rchanges uchanges] + children-master) + + (nil? child-master) + (reduce (fn [changes child] + (concat-changes changes (only-inst-cb child))) + [rchanges uchanges] + children-inst) + + :else + (if (cph/is-master-of child-master child-inst) + (recur (next children-inst) + (next children-master) + (concat-changes [rchanges uchanges] + (both-cb child-inst child-master))) + + (let [child-inst' (d/seek #(cph/is-master-of child-master %) + children-inst) + child-master' (d/seek #(cph/is-master-of % child-inst) + children-master)] + (cond + (nil? child-inst') + (recur children-inst + (next children-master) + (concat-changes [rchanges uchanges] + (only-master-cb child-master))) + + (nil? child-master') + (recur (next children-inst) + children-master + (concat-changes [rchanges uchanges] + (only-inst-cb child-inst))) + + :else + (if inverse? + (recur (next children-inst) + (remove #(= (:id %) (:id child-master')) children-master) + (-> [rchanges uchanges] + (concat-changes (both-cb child-inst' child-master)) + (concat-changes (moved-cb child-inst child-master')))) + (recur (remove #(= (:id %) (:id child-inst')) children-inst) + (next children-master) + (-> [rchanges uchanges] + (concat-changes (both-cb child-inst child-master')) + (concat-changes (moved-cb child-inst' child-master)))))))))))) + +(defn concat-changes + [[rchanges1 uchanges1] [rchanges2 uchanges2]] + [(d/concat rchanges1 rchanges2) + (d/concat uchanges1 uchanges2)]) + +(defn- add-shape-to-instance + [component-shape component page root-instance root-master] + (log/info :msg (str "ADD [P] " (:name component-shape))) + (let [component-parent-shape (cph/get-shape component (:parent-id component-shape)) + parent-shape (d/seek #(cph/is-master-of component-parent-shape %) + (cph/get-object-with-children (:id root-instance) + (:objects page))) + all-parents (vec (cons (:id parent-shape) + (cph/get-parents parent-shape (:objects page)))) + + update-new-shape (fn [new-shape original-shape] + (let [new-pos (calc-new-pos new-shape + original-shape + root-instance + root-master)] + (cond-> new-shape + true + (assoc :shape-ref (:id original-shape) + :frame-id (:frame-id parent-shape) + :x (:x new-pos) + :y (:y new-pos)) + + (:component-id original-shape) + (assoc :component-id (:component-id original-shape)) + + (:component-file original-shape) + (assoc :component-file (:component-file original-shape)) + + (:component-root original-shape) + (assoc :component-root (:component-root original-shape)) + + (:touched original-shape) + (assoc :touched (:touched original-shape))))) + + update-original-shape (fn [original-shape new-shape] + original-shape) + + [new-shape new-shapes _] + (cph/clone-object component-shape + (:id parent-shape) + (get page :objects) + update-new-shape + update-original-shape) + + rchanges (d/concat + (mapv (fn [shape'] + {:type :add-obj + :id (:id shape') + :page-id (:id page) + :parent-id (:parent-id shape') + :obj shape'}) + new-shapes) + [{:type :reg-objects + :page-id (:id page) + :shapes all-parents}]) + + uchanges (mapv (fn [shape'] + {:type :del-obj + :id (:id shape') + :page-id (:id page)}) + new-shapes)] + + [rchanges uchanges])) + +(defn- add-shape-to-master + [shape component page root-instance root-master] + (log/info :msg (str "ADD [C] " (:name shape))) + (let [parent-shape (cph/get-shape page (:parent-id shape)) + component-parent-shape (d/seek #(cph/is-master-of % parent-shape) + (cph/get-object-with-children (:id root-master) + (:objects component))) + all-parents (vec (cons (:id component-parent-shape) + (cph/get-parents component-parent-shape (:objects component)))) + + update-new-shape (fn [new-shape original-shape] + (let [new-pos (calc-new-pos new-shape + original-shape + root-master + root-instance)] + (assoc new-shape + :x (:x new-pos) + :y (:y new-pos)))) + + update-original-shape (fn [original-shape new-shape] + (if-not (:shape-ref original-shape) + (assoc original-shape + :shape-ref (:id new-shape)) + original-shape)) + + [new-shape new-shapes updated-shapes] + (cph/clone-object shape + (:shape-ref parent-shape) + (get page :objects) + update-new-shape + update-original-shape) + + rchanges (d/concat + (mapv (fn [shape'] + {:type :add-obj + :id (:id shape') + :component-id (:id component) + :parent-id (:parent-id shape') + :obj shape'}) + new-shapes) + [{:type :reg-objects + :component-id (:id component) + :shapes all-parents}] + (mapv (fn [shape'] + {:type :mod-obj + :page-id (:id page) + :id (:id shape') + :operations [{:type :set + :attr :component-id + :val (:component-id shape')} + {:type :set + :attr :component-file + :val (:component-file shape')} + {:type :set + :attr :component-root? + :val (:component-root? shape')} + {:type :set + :attr :shape-ref + :val (:shape-ref shape')} + {:type :set + :attr :touched + :val (:touched shape')}]}) + updated-shapes)) + + uchanges (mapv (fn [shape'] + {:type :del-obj + :id (:id shape') + :page-id (:id page)}) + new-shapes)] + + [rchanges uchanges])) + +(defn- remove-shape + [shape container] + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container)) + + objects (get container :objects) + parents (cph/get-parents (:id shape) objects) + children (cph/get-children (:id shape) objects) + + add-change (fn [id] + (let [shape' (get objects id)] + (d/without-nils {:type :add-obj + :id id + :page-id page-id + :component-id component-id + :index (cph/position-on-parent id objects) + :frame-id (:frame-id shape') + :parent-id (:parent-id shape') + :obj shape'}))) + + rchanges [(d/without-nils {:type :del-obj + :page-id page-id + :component-id component-id + :id (:id shape)})] + + uchanges (d/concat + [(add-change (:id shape))] + (map add-change children) + [(d/without-nils {:type :reg-objects + :page-id page-id + :component-id component-id + :shapes (vec parents)})])] + [rchanges uchanges])) + +(defn- move-shape + [shape index-before index-after container] + (log/info :msg (str "MOVE " + (:name shape) + " " + index-before + " -> " + index-after)) + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container))] + (let [rchanges [(d/without-nils {:type :mov-objects + :parent-id (:parent-id shape) + :shapes [(:id shape)] + :index index-after + :page-id page-id + :component-id component-id})] + uchanges [(d/without-nils {:type :mov-objects + :parent-id (:parent-id shape) + :shapes [(:id shape)] + :index index-before + :page-id page-id + :component-id component-id})]] + [rchanges uchanges]))) + +(defn- remove-component-and-ref + [shape container] + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container))] + [[(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set + :attr :component-root? + :val nil} + {:type :set + :attr :component-id + :val nil} + {:type :set + :attr :component-file + :val nil} + {:type :set + :attr :shape-ref + :val nil} + {:type :set-touched + :touched nil}]})] + [(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set + :attr :component-root? + :val (:component-root? shape)} + {:type :set + :attr :component-id + :val (:component-id shape)} + {:type :set + :attr :component-file + :val (:component-file shape)} + {:type :set + :attr :shape-ref + :val (:shape-ref shape)} + {:type :set-touched + :touched (:touched shape)}]})]])) + +(defn- remove-ref + [shape container] + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container))] + [[(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set + :attr :shape-ref + :val nil} + {:type :set-touched + :touched nil}]})] + [(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set + :attr :shape-ref + :val (:shape-ref shape)} + {:type :set-touched + :touched (:touched shape)}]})]])) (defn- reset-touched - [shape page-id component-id] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set-touched - :touched (:touched shape)}]})]]) + [shape container] + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container))] + [[(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set-touched + :touched nil}]})] + [(d/without-nils {:type :mod-obj + :id (:id shape) + :page-id page-id + :component-id component-id + :operations [{:type :set-touched + :touched (:touched shape)}]})]])) (defn- update-attrs "The main function that implements the sync algorithm. Copy @@ -711,7 +910,7 @@ the dest shape. If set-touched? is true, the corresponding 'touched' flags will be set in dest shape if they are different than their current values." - [dest-shape origin-shape dest-root origin-root page-id component-id + [dest-shape origin-shape dest-root origin-root container {:keys [omit-touched? reset-touched? set-touched? copy-touched?] :as options :or {omit-touched? false reset-touched? false @@ -721,10 +920,13 @@ (log/info :msg (str "SYNC " (:name origin-shape) " -> " - (if page-id "[W] " "[C] ") + (if (cph/is-page container) "[P] " "[C] ") (:name dest-shape))) - (let [; The position attributes need a special sync algorith, because we do + (let [page-id (when (cph/is-page container) (:id container)) + component-id (when (cph/is-component container) (:id container)) + + ; The position attributes need a special sync algorith, because we do ; not synchronize the absolute position, but the position relative of ; the container shape of the component. new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root) From 2582766a899876a1f99c88138643ca7c5842dc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 18 Nov 2020 13:55:45 +0100 Subject: [PATCH 066/195] :recycle: Simplify container type management --- common/app/common/pages.cljc | 4 +- common/app/common/pages_helpers.cljc | 22 +- .../data/workspace/libraries_helpers.cljs | 317 +++++++++--------- 3 files changed, 172 insertions(+), 171 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 0d59551c8f..1d4e76fb31 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -435,10 +435,10 @@ :internal.file/recent-colors :internal.file/media])) -(s/def ::container-type #{:page :component}) +(s/def :internal.container/type #{:page :component}) (s/def ::container - (s/keys :req-un [::container-type + (s/keys :req-un [:internal.container/type ::id ::name :internal.page/objects])) diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index 9683e9369f..ecc0dd463f 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -43,24 +43,24 @@ nil))) (defn make-container - [page-or-component container-type] + [page-or-component type] (assoc page-or-component - :container-type container-type)) + :type type)) -(defn is-page +(defn page? [container] - (= (:container-type container) :page)) + (= (:type container) :page)) -(defn is-component +(defn component? [container] - (= (:container-type container) :component)) + (= (:type container) :component)) (defn get-container - [container-id container-type local-file] - (-> (if (= container-type :page) - (get-in local-file [:pages-index container-id]) - (get-in local-file [:components container-id])) - (assoc :container-type container-type))) + [id type local-file] + (-> (if (= type :page) + (get-in local-file [:pages-index id]) + (get-in local-file [:components id])) + (assoc :type type))) (defn get-shape [container shape-id] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 42ff924792..46a70c2d56 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -179,7 +179,7 @@ (a page or a component) that are linked to the given library." [asset-type library-id state container] - (if (= (:container-type container) :page) + (if (cph/page? container) (log/debug :msg "Sync page in local file" :page-id (:id container)) (log/debug :msg "Sync component in local library" :component-id (:id container))) @@ -250,36 +250,36 @@ (get state :workspace-libraries) false)) -(defn- generate-sync-text-shape [shape page-id component-id update-node] +(defn- generate-sync-text-shape [shape container update-node] (let [old-content (:content shape) new-content (ut/map-node update-node old-content) - rchanges [(d/without-nils {:type :mod-obj - :page-id page-id - :component-id component-id - :id (:id shape) - :operations [{:type :set - :attr :content - :val new-content}]})] - lchanges [(d/without-nils {:type :mod-obj - :page-id page-id - :component-id component-id - :id (:id shape) - :operations [{:type :set - :attr :content - :val old-content}]})]] + rchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :content + :val new-content}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + uchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :content + :val old-content}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] + (if (= new-content old-content) empty-changes - [rchanges lchanges]))) - + [rchanges uchanges]))) (defmethod generate-sync-shape :colors [_ library-id state container shape] ;; Synchronize a shape that uses some colors of the library. The value of the ;; color in the library is copied to the shape. - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container)) - colors (get-assets library-id :colors state)] + (let [colors (get-assets library-id :colors state)] (if (= :text (:type shape)) (let [update-node (fn [node] (if-let [color (get colors (:fill-color-ref-id node))] @@ -288,7 +288,7 @@ :fill-opacity (:opacity color) :fill-color-gradient (:gradient color)) node))] - (generate-sync-text-shape shape page-id component-id update-node)) + (generate-sync-text-shape shape container update-node)) (loop [attrs (seq color-sync-attrs) roperations [] uoperations []] @@ -296,16 +296,18 @@ (if (nil? attr) (if (empty? roperations) empty-changes - (let [rchanges [(d/without-nils {:type :mod-obj - :page-id page-id - :component-id component-id - :id (:id shape) - :operations roperations})] - uchanges [(d/without-nils {:type :mod-obj - :page-id page-id - :component-id component-id - :id (:id shape) - :operations uoperations})]] + (let [rchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations roperations} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + uchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations uoperations} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] [rchanges uchanges])) (if-not (contains? shape attr-ref-id) (recur (next attrs) @@ -329,14 +331,12 @@ ;; Synchronize a shape that uses some typographies of the library. The attributes ;; of the typography are copied to the shape." - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container)) - typographies (get-assets library-id :typographies state) + (let [typographies (get-assets library-id :typographies state) update-node (fn [node] (if-let [typography (get typographies (:typography-ref-id node))] (merge node (d/without-keys typography [:name :id])) node))] - (generate-sync-text-shape shape page-id component-id update-node))) + (generate-sync-text-shape shape container update-node))) ;; ---- Component synchronization helpers ---- @@ -764,36 +764,38 @@ (defn- remove-shape [shape container] - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container)) - - objects (get container :objects) + (let [objects (get container :objects) parents (cph/get-parents (:id shape) objects) children (cph/get-children (:id shape) objects) add-change (fn [id] (let [shape' (get objects id)] - (d/without-nils {:type :add-obj - :id id - :page-id page-id - :component-id component-id - :index (cph/position-on-parent id objects) - :frame-id (:frame-id shape') - :parent-id (:parent-id shape') - :obj shape'}))) + (as-> {:type :add-obj + :id id + :index (cph/position-on-parent id objects) + :parent-id (:parent-id shape') + :obj shape'} $ + (cond-> $ + (:frame-id shape') + (assoc :frame-id (:frame-id shape'))) + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container)))))) - rchanges [(d/without-nils {:type :del-obj - :page-id page-id - :component-id component-id - :id (:id shape)})] + rchanges [(as-> {:type :del-obj + :id (:id shape)} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] uchanges (d/concat [(add-change (:id shape))] (map add-change children) - [(d/without-nils {:type :reg-objects - :page-id page-id - :component-id component-id - :shapes (vec parents)})])] + [(as-> {:type :reg-objects + :shapes (vec parents)} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))])] [rchanges uchanges])) (defn- move-shape @@ -804,102 +806,102 @@ index-before " -> " index-after)) - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container))] - (let [rchanges [(d/without-nils {:type :mov-objects - :parent-id (:parent-id shape) - :shapes [(:id shape)] - :index index-after - :page-id page-id - :component-id component-id})] - uchanges [(d/without-nils {:type :mov-objects - :parent-id (:parent-id shape) - :shapes [(:id shape)] - :index index-before - :page-id page-id - :component-id component-id})]] - [rchanges uchanges]))) + (let [rchanges [(as-> {:type :mov-objects + :parent-id (:parent-id shape) + :shapes [(:id shape)] + :index index-after} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + uchanges [(as-> {:type :mov-objects + :parent-id (:parent-id shape) + :shapes [(:id shape)] + :index index-before} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] + [rchanges uchanges])) (defn- remove-component-and-ref [shape container] - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container))] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :component-root? - :val nil} - {:type :set - :attr :component-id - :val nil} - {:type :set - :attr :component-file - :val nil} - {:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :component-root? - :val (:component-root? shape)} - {:type :set - :attr :component-id - :val (:component-id shape)} - {:type :set - :attr :component-file - :val (:component-file shape)} - {:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]})]])) + [[(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :component-root? + :val nil} + {:type :set + :attr :component-id + :val nil} + {:type :set + :attr :component-file + :val nil} + {:type :set + :attr :shape-ref + :val nil} + {:type :set-touched + :touched nil}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + [(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :component-root? + :val (:component-root? shape)} + {:type :set + :attr :component-id + :val (:component-id shape)} + {:type :set + :attr :component-file + :val (:component-file shape)} + {:type :set + :attr :shape-ref + :val (:shape-ref shape)} + {:type :set-touched + :touched (:touched shape)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]]) (defn- remove-ref [shape container] - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container))] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]})]])) + [[(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :shape-ref + :val nil} + {:type :set-touched + :touched nil}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + [(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set + :attr :shape-ref + :val (:shape-ref shape)} + {:type :set-touched + :touched (:touched shape)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]]) (defn- reset-touched [shape container] - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container))] - [[(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set-touched - :touched nil}]})] - [(d/without-nils {:type :mod-obj - :id (:id shape) - :page-id page-id - :component-id component-id - :operations [{:type :set-touched - :touched (:touched shape)}]})]])) + [[(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set-touched + :touched nil}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + [(as-> {:type :mod-obj + :id (:id shape) + :operations [{:type :set-touched + :touched (:touched shape)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]]) (defn- update-attrs "The main function that implements the sync algorithm. Copy @@ -920,13 +922,10 @@ (log/info :msg (str "SYNC " (:name origin-shape) " -> " - (if (cph/is-page container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name dest-shape))) - (let [page-id (when (cph/is-page container) (:id container)) - component-id (when (cph/is-component container) (:id container)) - - ; The position attributes need a special sync algorith, because we do + (let [; The position attributes need a special sync algorith, because we do ; not synchronize the absolute position, but the position relative of ; the container shape of the component. new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root) @@ -966,16 +965,18 @@ :else uoperations) - rchanges [(d/without-nils {:type :mod-obj - :id (:id dest-shape) - :page-id page-id - :component-id component-id - :operations roperations})] - uchanges [(d/without-nils {:type :mod-obj - :id (:id dest-shape) - :page-id page-id - :component-id component-id - :operations uoperations})]] + rchanges [(as-> {:type :mod-obj + :id (:id dest-shape) + :operations roperations} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + uchanges [(as-> {:type :mod-obj + :id (:id dest-shape) + :operations uoperations} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] [rchanges uchanges]) (if-not (contains? dest-shape attr) From 830d932eece395f4c21b517cf515d28ac3520779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 19 Nov 2020 11:59:20 +0100 Subject: [PATCH 067/195] :recycle: Add more debugging traces --- .../app/main/data/workspace/libraries_helpers.cljs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 46a70c2d56..3a6241d4be 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -560,7 +560,6 @@ ; ---- Operation generation helpers ---- - (defn- compare-children [children-inst children-master only-inst-cb only-master-cb both-cb moved-cb inverse?] (loop [children-inst (seq (or children-inst [])) @@ -764,6 +763,9 @@ (defn- remove-shape [shape container] + (log/info :msg (str "REMOVE-SHAPE " + (if (cph/page? container) "[P] " "[C] ") + (:name shape))) (let [objects (get container :objects) parents (cph/get-parents (:id shape) objects) children (cph/get-children (:id shape) objects) @@ -801,6 +803,7 @@ (defn- move-shape [shape index-before index-after container] (log/info :msg (str "MOVE " + (if (cph/page? container) "[P] " "[C] ") (:name shape) " " index-before @@ -824,6 +827,9 @@ (defn- remove-component-and-ref [shape container] + (log/info :msg (str "REMOVE-COMPONENT-AND-REF " + (if (cph/page? container) "[P] " "[C] ") + (:name shape))) [[(as-> {:type :mod-obj :id (:id shape) :operations [{:type :set @@ -865,6 +871,9 @@ (defn- remove-ref [shape container] + (log/info :msg (str "REMOVE-REF " + (if (cph/page? container) "[P] " "[C] ") + (:name shape))) [[(as-> {:type :mod-obj :id (:id shape) :operations [{:type :set @@ -888,6 +897,9 @@ (defn- reset-touched [shape container] + (log/info :msg (str "RESET-TOUCHED " + (if (cph/page? container) "[P] " "[C] ") + (:name shape))) [[(as-> {:type :mod-obj :id (:id shape) :operations [{:type :set-touched From 6db1a907c806a2998623875183c0d0ef78353e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 19 Nov 2020 15:35:34 +0100 Subject: [PATCH 068/195] :sparkles: Use touched flags when adding/deleting/moving shapes --- common/app/common/pages.cljc | 81 ++++- common/app/common/pages_helpers.cljc | 10 + frontend/src/app/main/data/workspace.cljs | 9 +- .../app/main/data/workspace/libraries.cljs | 4 +- .../data/workspace/libraries_helpers.cljs | 339 ++++++++++-------- 5 files changed, 270 insertions(+), 173 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 1d4e76fb31..0188a1eab4 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -340,6 +340,7 @@ :rx :radius-group :ry :radius-group :masked-group? :mask-group}) + ;; shapes-group is handled differently (s/def ::minimal-shape (s/keys :req-un [::type ::name] @@ -468,30 +469,52 @@ (s/def :internal.changes.add-obj/obj ::shape) +(defn- valid-container-id-frame? + [o] + (or (and (contains? o :page-id) + (not (contains? o :component-id)) + (some? (:frame-id o))) + (and (contains? o :component-id) + (not (contains? o :page-id)) + (nil? (:frame-id o))))) + +(defn- valid-container-id? + [o] + (or (and (contains? o :page-id) + (not (contains? o :component-id))) + (and (contains? o :component-id) + (not (contains? o :page-id))))) + (defmethod change-spec :add-obj [_] - (s/keys :req-un [::id (or ::page-id ::component-id) - :internal.changes.add-obj/obj] - :opt-un [::parent-id ::frame-id])) + (s/and (s/keys :req-un [::id :internal.changes.add-obj/obj] + :opt-un [::page-id ::component-id ::parent-id ::frame-id]) + valid-container-id-frame?)) (s/def ::operation (s/multi-spec operation-spec :type)) (s/def ::operations (s/coll-of ::operation)) (defmethod change-spec :mod-obj [_] - (s/keys :req-un [::id (or ::page-id ::component-id) ::operations])) + (s/and (s/keys :req-un [::id ::operations] + :opt-un [::page-id ::component-id]) + valid-container-id?)) (defmethod change-spec :del-obj [_] - (s/keys :req-un [::id (or ::page-id ::component-id)])) + (s/and (s/keys :req-un [::id] + :opt-un [::page-id ::component-id]) + valid-container-id?)) (s/def :internal.changes.reg-objects/shapes (s/coll-of uuid? :kind vector?)) (defmethod change-spec :reg-objects [_] - (s/keys :req-un [(or ::page-id ::component-id) - :internal.changes.reg-objects/shapes])) + (s/and (s/keys :req-un [:internal.changes.reg-objects/shapes] + :opt-un [::page-id ::component-id]) + valid-container-id?)) (defmethod change-spec :mov-objects [_] - (s/keys :req-un [(or ::page-id ::component-id) ::parent-id :internal.shape/shapes] - :opt-un [::index])) + (s/and (s/keys :req-un [::parent-id :internal.shape/shapes] + :opt-un [::page-id ::component-id ::index]) + valid-container-id?)) (defmethod change-spec :add-page [_] (s/or :empty (s/keys :req-un [::id ::name]) @@ -710,7 +733,8 @@ (assoc data :options (d/dissoc-in (:options data) path))))))) (defmethod process-change :add-obj - [data {:keys [id obj page-id component-id frame-id parent-id index] :as change}] + [data {:keys [id obj page-id component-id frame-id parent-id + index ignore-touched] :as change}] (let [update-fn (fn [data] (let [parent-id (or parent-id frame-id) objects (:objects data)] @@ -726,7 +750,13 @@ (cond (some #{id} shapes) shapes (nil? index) (conj shapes id) - :else (cph/insert-at-index shapes index [id])))))))))] + :else (cph/insert-at-index shapes index [id]))))) + (cond-> + (and (:shape-ref (get-in data [:objects parent-id])) + (not= parent-id frame-id) + (not ignore-touched)) + (update-in [:objects parent-id :touched] + cph/set-touched-group :shapes-group))))))] (if page-id (d/update-in-when data [:pages-index page-id] update-fn) (d/update-in-when data [:components component-id] update-fn)))) @@ -742,7 +772,7 @@ (d/update-in-when data [:components component-id :objects] update-fn)))) (defmethod process-change :del-obj - [data {:keys [page-id component-id id] :as change}] + [data {:keys [page-id component-id id ignore-touched] :as change}] (letfn [(delete-object [objects] (if-let [target (get objects id)] (let [parent-id (cph/get-parent id objects) @@ -754,6 +784,9 @@ (= :group (:type parent))) (update-in [parent-id :shapes] (fn [s] (filterv #(not= % id) s))) + (and (:shape-ref parent) (not ignore-touched)) + (update-in [parent-id :touched] cph/set-touched-group :shapes-group) + (contains? objects frame-id) (update-in [frame-id :shapes] (fn [s] (filterv #(not= % id) s))) @@ -813,7 +846,7 @@ (d/update-in-when data [:components component-id :objects] reg-objects)))) (defmethod process-change :mov-objects - [data {:keys [parent-id shapes index page-id component-id] :as change}] + [data {:keys [parent-id shapes index page-id component-id ignore-touched] :as change}] (letfn [(is-valid-move? [objects shape-id] (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] (and (not (invalid-targets parent-id)) @@ -840,6 +873,14 @@ (strip-id [coll id] (filterv #(not= % id) coll)) + (add-to-parent [parent index shapes] + (cond-> parent + true + (update :shapes check-insert-items parent index shapes) + + (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) + (update :touched cph/set-touched-group :shapes-group))) + (remove-from-old-parent [cpindex objects shape-id] (let [prev-parent-id (get cpindex shape-id)] ;; Do nothing if the parent id of the shape is the same as @@ -856,7 +897,15 @@ (recur pid (:parent-id obj) (dissoc objects pid)) - (update-in objects [pid :shapes] strip-id sid))))))) + (cond-> objects + true + (update-in [pid :shapes] strip-id sid) + + (and (:shape-ref obj) + (= (:type obj) :group) + (not ignore-touched)) + (update-in [pid :touched] + cph/set-touched-group :shapes-group)))))))) (update-parent-id [objects id] (update objects id assoc :parent-id parent-id)) @@ -888,7 +937,7 @@ (if valid? (as-> objects $ - (update-in $ [parent-id :shapes] check-insert-items parent index shapes) + (update $ parent-id #(add-to-parent % index shapes)) (reduce update-parent-id $ shapes) (reduce (partial remove-from-old-parent cpindex) $ shapes) (reduce (partial update-frame-ids frm-id) $ (get-in $ [parent-id :shapes]))) @@ -1016,7 +1065,7 @@ (cond-> shape (and shape-ref group (not ignore) (not= val (get shape attr))) - (update :touched #(conj (or % #{}) group)) + (update :touched cph/set-touched-group group) (nil? val) (dissoc attr) diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index ecc0dd463f..8c2f1e5619 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -49,6 +49,7 @@ (defn page? [container] + (assert (some? (:type container))) (= (:type container) :page)) (defn component? @@ -297,3 +298,12 @@ (d/seek #(gsh/has-point? % position)) :id) uuid/zero))) + +(defn set-touched-group + [touched group] + (conj (or touched #{}) group)) + +(defn touched-group? + [shape group] + ((or (:touched shape) #{}) group)) + diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f75a89a672..fbb8c9e3a7 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -711,6 +711,7 @@ (reduce (fn [res id] (let [children (cph/get-children id objects) parents (cph/get-parents id objects) + parent (get objects (first parents)) add-change (fn [id] (let [item (get objects id)] {:type :add-obj @@ -726,7 +727,13 @@ (map add-change children) [{:type :reg-objects :page-id page-id - :shapes (vec parents)}]))) + :shapes (vec parents)}] + (when (some? parent) + [{:type :mod-obj + :page-id page-id + :id (:id parent) + :operations [{:type :set-touched + :touched (:touched parent)}]}])))) [] ids) (map #(array-map diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 77d9879705..3eb8f60db7 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -398,13 +398,15 @@ :page-id page-id :frame-id (:frame-id obj) :parent-id (:parent-id obj) + :ignore-touched true :obj obj}) new-shapes) uchanges (map (fn [obj] {:type :del-obj :id (:id obj) - :page-id page-id}) + :page-id page-id + :ignore-touched true}) new-shapes)] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 3a6241d4be..bd6608a3b5 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -48,9 +48,7 @@ (declare add-shape-to-master) (declare remove-shape) (declare move-shape) -(declare remove-component-and-ref) -(declare remove-ref) -(declare reset-touched) +(declare change-touched) (declare update-attrs) (declare calc-new-pos) @@ -375,13 +373,18 @@ root-master {:omit-touched? (not reset?) :reset-touched? reset? - :set-touched? false}))) + :copy-touched? false}))) (defn- generate-sync-shape-direct-recursive - [container shape-inst component shape-master root-inst root-master options] - (log/trace :msg "Sync shape direct" + [container shape-inst component shape-master root-inst root-master + {:keys [omit-touched? reset-touched? copy-touched?] + :as options :or {omit-touched? false + reset-touched? false + copy-touched? false}}] + (log/trace :msg "Sync shape direct recursive" :shape (str (:name shape-inst)) - :component (:name component)) + :component (:name component) + :options options) (let [root-inst (if (:component-id shape-inst) shape-inst @@ -391,12 +394,17 @@ root-master) [rchanges uchanges] - (update-attrs shape-inst - shape-master - root-inst - root-master - container - options) + (concat-changes + (update-attrs shape-inst + shape-master + root-inst + root-master + container + options) + (change-touched shape-inst + shape-master + container + options)) children-inst (mapv #(cph/get-shape container %) (:shapes shape-inst)) @@ -405,21 +413,22 @@ only-inst (fn [shape-inst] (remove-shape shape-inst - container)) + container + omit-touched?)) only-master (fn [shape-master] (add-shape-to-instance shape-master component container root-inst - root-master)) + root-master + omit-touched?)) both (fn [shape-inst shape-master] (let [options (if-not (:component-id shape-inst) options {:omit-touched? false :reset-touched? false - :set-touched? false :copy-touched? true})] (generate-sync-shape-direct-recursive container @@ -435,7 +444,8 @@ shape-inst (d/index-of children-inst shape-inst) (d/index-of children-master shape-master) - container)) + container + omit-touched?)) [child-rchanges child-uchanges] (compare-children children-inst @@ -476,15 +486,20 @@ shape-master root-inst root-master - {:omit-touched? false - :reset-touched? false - :set-touched? true}))) + {:reset-touched? false + :set-touched? true + :copy-touched? false}))) (defn- generate-sync-shape-inverse-recursive - [container shape-inst component shape-master root-inst root-master options] - (log/trace :msg "Sync shape inverse" + [container shape-inst component shape-master root-inst root-master + {:keys [reset-touched? set-touched? copy-touched?] + :as options :or {reset-touched? false + set-touched? false + copy-touched? false}}] + (log/trace :msg "Sync shape inverse recursive" :shape (str (:name shape-inst)) - :component (:name component)) + :component (:name component) + :options options) (let [root-inst (if (:component-id shape-inst) shape-inst @@ -503,9 +518,14 @@ root-inst component-container options) - (if (:set-touched? options) - (reset-touched shape-inst container) - empty-changes)) + (concat-changes + (change-touched shape-master + shape-inst + component-container + options) + (if (:set-touched? options) + (change-touched shape-inst nil container {:reset-touched? true}) + empty-changes))) children-inst (mapv #(cph/get-shape container %) (:shapes shape-inst)) @@ -521,13 +541,13 @@ only-master (fn [shape-master] (remove-shape shape-master - component-container)) - + component-container + false)) + both (fn [shape-inst shape-master] (let [options (if-not (:component-id shape-inst) options - {:omit-touched? false - :reset-touched? false + {:reset-touched? false :set-touched? false :copy-touched? true})] @@ -544,7 +564,8 @@ shape-master (d/index-of children-master shape-master) (d/index-of children-inst shape-inst) - component-container)) + component-container + false)) [child-rchanges child-uchanges] (compare-children children-inst @@ -560,6 +581,7 @@ ; ---- Operation generation helpers ---- + (defn- compare-children [children-inst children-master only-inst-cb only-master-cb both-cb moved-cb inverse?] (loop [children-inst (seq (or children-inst [])) @@ -626,14 +648,14 @@ (d/concat uchanges1 uchanges2)]) (defn- add-shape-to-instance - [component-shape component page root-instance root-master] + [component-shape component container root-instance root-master omit-touched?] (log/info :msg (str "ADD [P] " (:name component-shape))) (let [component-parent-shape (cph/get-shape component (:parent-id component-shape)) parent-shape (d/seek #(cph/is-master-of component-parent-shape %) (cph/get-object-with-children (:id root-instance) - (:objects page))) + (:objects container))) all-parents (vec (cons (:id parent-shape) - (cph/get-parents parent-shape (:objects page)))) + (cph/get-parents parent-shape (:objects container)))) update-new-shape (fn [new-shape original-shape] (let [new-pos (calc-new-pos new-shape @@ -665,29 +687,43 @@ [new-shape new-shapes _] (cph/clone-object component-shape (:id parent-shape) - (get page :objects) + (get container :objects) update-new-shape update-original-shape) rchanges (d/concat (mapv (fn [shape'] - {:type :add-obj - :id (:id shape') - :page-id (:id page) - :parent-id (:parent-id shape') - :obj shape'}) + (as-> {:type :add-obj + :id (:id shape') + :parent-id (:parent-id shape') + :ignore-touched true + :obj shape'} $ + (cond-> $ + (:frame-id shape') + (assoc :frame-id (:frame-id shape'))) + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))) new-shapes) - [{:type :reg-objects - :page-id (:id page) - :shapes all-parents}]) + [(as-> {:type :reg-objects + :shapes all-parents} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]) - uchanges (mapv (fn [shape'] - {:type :del-obj - :id (:id shape') - :page-id (:id page)}) - new-shapes)] + uchanges (d/concat + (mapv (fn [shape'] + (as-> {:type :del-obj + :id (:id shape') + :ignore-touched true} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))) + new-shapes))] - [rchanges uchanges])) + (if (and (cph/touched-group? parent-shape :shapes-group) omit-touched?) + empty-changes + [rchanges uchanges]))) (defn- add-shape-to-master [shape component page root-instance root-master] @@ -716,7 +752,7 @@ [new-shape new-shapes updated-shapes] (cph/clone-object shape - (:shape-ref parent-shape) + (:id component-parent-shape) (get page :objects) update-new-shape update-original-shape) @@ -727,6 +763,7 @@ :id (:id shape') :component-id (:id component) :parent-id (:parent-id shape') + :ignore-touched true :obj shape'}) new-shapes) [{:type :reg-objects @@ -753,29 +790,40 @@ :val (:touched shape')}]}) updated-shapes)) - uchanges (mapv (fn [shape'] - {:type :del-obj - :id (:id shape') - :page-id (:id page)}) - new-shapes)] + uchanges (d/concat + (mapv (fn [shape'] + {:type :del-obj + :id (:id shape') + :page-id (:id page) + :ignore-touched true}) + new-shapes))] [rchanges uchanges])) (defn- remove-shape - [shape container] + [shape container omit-touched?] (log/info :msg (str "REMOVE-SHAPE " (if (cph/page? container) "[P] " "[C] ") (:name shape))) (let [objects (get container :objects) parents (cph/get-parents (:id shape) objects) + parent (first parents) children (cph/get-children (:id shape) objects) + rchanges [(as-> {:type :del-obj + :id (:id shape) + :ignore-touched true} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + add-change (fn [id] (let [shape' (get objects id)] (as-> {:type :add-obj :id id :index (cph/position-on-parent id objects) :parent-id (:parent-id shape') + :ignore-touched true :obj shape'} $ (cond-> $ (:frame-id shape') @@ -784,12 +832,6 @@ (assoc $ :page-id (:id container)) (assoc $ :component-id (:id container)))))) - rchanges [(as-> {:type :del-obj - :id (:id shape)} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))] - uchanges (d/concat [(add-change (:id shape))] (map add-change children) @@ -798,10 +840,13 @@ (if (cph/page? container) (assoc $ :page-id (:id container)) (assoc $ :component-id (:id container))))])] - [rchanges uchanges])) + + (if (and (cph/touched-group? parent :shapes-group) omit-touched?) + empty-changes + [rchanges uchanges]))) (defn- move-shape - [shape index-before index-after container] + [shape index-before index-after container omit-touched?] (log/info :msg (str "MOVE " (if (cph/page? container) "[P] " "[C] ") (:name shape) @@ -809,111 +854,93 @@ index-before " -> " index-after)) - (let [rchanges [(as-> {:type :mov-objects + (let [parent (cph/get-shape container (:parent-id shape)) + + rchanges [(as-> {:type :mov-objects :parent-id (:parent-id shape) :shapes [(:id shape)] - :index index-after} $ + :index index-after + :ignore-touched true} $ (if (cph/page? container) (assoc $ :page-id (:id container)) (assoc $ :component-id (:id container))))] uchanges [(as-> {:type :mov-objects :parent-id (:parent-id shape) :shapes [(:id shape)] - :index index-before} $ + :index index-before + :ignore-touched true} $ (if (cph/page? container) (assoc $ :page-id (:id container)) (assoc $ :component-id (:id container))))]] - [rchanges uchanges])) -(defn- remove-component-and-ref - [shape container] - (log/info :msg (str "REMOVE-COMPONENT-AND-REF " - (if (cph/page? container) "[P] " "[C] ") - (:name shape))) - [[(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :component-root? - :val nil} - {:type :set - :attr :component-id - :val nil} - {:type :set - :attr :component-file - :val nil} - {:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))] - [(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :component-root? - :val (:component-root? shape)} - {:type :set - :attr :component-id - :val (:component-id shape)} - {:type :set - :attr :component-file - :val (:component-file shape)} - {:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))]]) + (if (and (cph/touched-group? parent :shapes-group) omit-touched?) + empty-changes + [rchanges uchanges]))) -(defn- remove-ref - [shape container] - (log/info :msg (str "REMOVE-REF " - (if (cph/page? container) "[P] " "[C] ") - (:name shape))) - [[(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :shape-ref - :val nil} - {:type :set-touched - :touched nil}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))] - [(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set - :attr :shape-ref - :val (:shape-ref shape)} - {:type :set-touched - :touched (:touched shape)}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))]]) +(defn- change-touched + [dest-shape orig-shape container + {:keys [reset-touched? copy-touched?] + :as options :or {reset-touched? false + copy-touched? false}}] + (if (or (nil? (:shape-ref dest-shape)) + (not (or reset-touched? copy-touched?))) + empty-changes + (do + (log/info :msg (str "CHANGE-TOUCHED " + (if (cph/page? container) "[P] " "[C] ") + (:name dest-shape)) + :options options) + (let [rchanges [(as-> {:type :mod-obj + :id (:id dest-shape) + :operations + [{:type :set-touched + :touched + (cond reset-touched? + nil + copy-touched? + (:touched orig-shape))}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] -(defn- reset-touched + uchanges [(as-> {:type :mod-obj + :id (:id dest-shape) + :operations + [{:type :set-touched + :touched (:touched dest-shape)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] + [rchanges uchanges])))) + +(defn- set-touched-shapes-group [shape container] - (log/info :msg (str "RESET-TOUCHED " - (if (cph/page? container) "[P] " "[C] ") - (:name shape))) - [[(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set-touched - :touched nil}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))] - [(as-> {:type :mod-obj - :id (:id shape) - :operations [{:type :set-touched - :touched (:touched shape)}]} $ - (if (cph/page? container) - (assoc $ :page-id (:id container)) - (assoc $ :component-id (:id container))))]]) + (if-not (:shape-ref shape) + empty-changes + (do + (log/info :msg (str "SET-TOUCHED-SHAPES-GROUP " + (if (cph/page? container) "[P] " "[C] ") + (:name shape))) + (let [rchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations + [{:type :set-touched + :touched (cph/set-touched-group + (:touched shape) + :shapes-group)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))] + + uchanges [(as-> {:type :mod-obj + :id (:id shape) + :operations + [{:type :set-touched + :touched (:touched shape)}]} $ + (if (cph/page? container) + (assoc $ :page-id (:id container)) + (assoc $ :component-id (:id container))))]] + [rchanges uchanges])))) (defn- update-attrs "The main function that implements the sync algorithm. Copy @@ -923,7 +950,9 @@ If reset-touched? is true, the 'touched' flags will be cleared in the dest shape. If set-touched? is true, the corresponding 'touched' flags will be - set in dest shape if they are different than their current values." + set in dest shape if they are different than their current values. + If copy-touched? is true, the value of 'touched' flags in the + origin shape will be copied as is to the dest shape." [dest-shape origin-shape dest-root origin-root container {:keys [omit-touched? reset-touched? set-touched? copy-touched?] :as options :or {omit-touched? false From 02b3c6ac284782c532a146690585dcee0c6ed42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 25 Nov 2020 13:44:06 +0100 Subject: [PATCH 069/195] :bug: Ignore touched when duplicating shape --- frontend/src/app/main/data/workspace/selection.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index f2ef8af360..2d33d9e543 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -330,6 +330,7 @@ :old-id (:id obj) :frame-id frame-id :parent-id parent-id + :ignore-touched true :obj (dissoc reframed-obj :shapes)}] children-changes))) From 5c71601fcfb69758fd1a99484398ed1493677c5a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 25 Nov 2020 17:10:39 +0100 Subject: [PATCH 070/195] :sparkles: Improves path drawing --- .../styles/main/partials/workspace.scss | 1 + .../app/main/data/workspace/drawing/path.cljs | 349 +++++++++++------- frontend/src/app/main/exports.cljs | 27 +- .../app/main/ui/workspace/shapes/path.cljs | 145 +++++--- .../src/app/main/ui/workspace/viewport.cljs | 2 +- frontend/src/app/util/dom.cljs | 4 + frontend/src/app/util/geom/path.cljs | 142 ++++++- 7 files changed, 460 insertions(+), 210 deletions(-) diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index d6119cd4a4..3861a5d339 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -263,6 +263,7 @@ border-radius: 3px; svg { + pointer-events: none; width: 20px; height: 20px; } diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 024e6baeed..aed97a83e8 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -9,10 +9,11 @@ (ns app.main.data.workspace.drawing.path (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] [beicon.core :as rx] [potok.core :as ptk] [app.common.math :as mth] - [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.util.data :as ud] @@ -23,9 +24,50 @@ [app.main.data.workspace.drawing.common :as common] [app.common.geom.shapes.path :as gsp])) +;; SCHEMAS + +(s/def ::command #{:move-to + :line-to + :line-to-horizontal + :line-to-vertical + :curve-to + :smooth-curve-to + :quadratic-bezier-curve-to + :smooth-quadratic-bezier-curve-to + :elliptical-arc + :close-path}) + +(s/def :paths.params/x number?) +(s/def :paths.params/y number?) +(s/def :paths.params/c1x number?) +(s/def :paths.params/c1y number?) +(s/def :paths.params/c2x number?) +(s/def :paths.params/c2y number?) + +(s/def ::relative? boolean?) + +(s/def ::params + (s/keys :req-un [:path.params/x + :path.params/y] + :opt-un [:path.params/c1x + :path.params/c1y + :path.params/c2x + :path.params/c2y])) + +(s/def ::content-entry + (s/keys :req-un [::command] + :req-opt [::params + ::relative?])) +(s/def ::content + (s/coll-of ::content-entry :kind vector?)) + +(s/def ::path-shape + (s/keys :req-un [::content])) + + ;; CONSTANTS (defonce enter-keycode 13) - +(defonce drag-threshold 2) ;; PRIVATE METHODS @@ -89,26 +131,64 @@ (update opposite-index assoc ocx (- dx) ocy (- dy))))) (defn end-path-event? [{:keys [type shift] :as event}] - (or (= event ::end-path) + (or (= (ptk/type event) ::finish-path) (= (ptk/type event) :esc-pressed) (= event :interrupt) ;; ESC + (and (ms/mouse-double-click? event)) (and (ms/keyboard-event? event) (= type :down) ;; TODO: Enter now finish path but can finish drawing/editing as well (= enter-keycode (:key event))))) +(defn generate-path-changes [page-id shape-id old-content new-content] + (us/verify ::content old-content) + (us/verify ::content new-content) + (let [old-selrect (gsh/content->selrect old-content) + old-points (gsh/rect->points old-selrect) + new-selrect (gsh/content->selrect new-content) + new-points (gsh/rect->points new-selrect) + + rch [{:type :mod-obj + :id shape-id + :page-id page-id + :operations [{:type :set :attr :content :val new-content} + {:type :set :attr :selrect :val new-selrect} + {:type :set :attr :points :val new-points}]} + {:type :reg-objects + :page-id page-id + :shapes [shape-id]}] + + uch [{:type :mod-obj + :id shape-id + :page-id page-id + :operations [{:type :set :attr :content :val old-content} + {:type :set :attr :selrect :val old-selrect} + {:type :set :attr :points :val old-points}]} + {:type :reg-objects + :page-id page-id + :shapes [shape-id]}]] + [rch uch])) + +(defn clean-edit-state + [state] + (dissoc state :last-point :prev-handler :drag-handler :preview)) + +(defn dragging? [start zoom] + (fn [current] + (>= (gpt/distance start current) (/ drag-threshold zoom)))) ;; EVENTS -(defn init-path [id] +(defn init-path [] (ptk/reify ::init-path)) -(defn finish-path [id] +(defn finish-path [source] (ptk/reify ::finish-path ptk/UpdateEvent (update [_ state] - (-> state - (update-in [:workspace-local :edit-path id] dissoc :last-point :prev-handler :drag-handler :preview))))) + (let [id (get-path-id state)] + (-> state + (update-in [:workspace-local :edit-path id] clean-edit-state)))))) (defn preview-next-point [{:keys [x y]}] (ptk/reify ::preview-next-point @@ -118,7 +198,6 @@ position (gpt/point x y) shape (get-in state (get-path state)) {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id]) - command (next-node shape position last-point prev-handler)] (assoc-in state [:workspace-local :edit-path id :preview] command))))) @@ -129,10 +208,13 @@ (let [id (get-path-id state) position (gpt/point x y) {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id])] - (-> state - (assoc-in [:workspace-local :edit-path id :last-point] position) - (update-in [:workspace-local :edit-path id] dissoc :prev-handler) - (update-in (get-path state) append-node position last-point prev-handler)))))) + (if-not (= last-point position) + (-> state + (assoc-in [:workspace-local :edit-path id :last-point] position) + (update-in [:workspace-local :edit-path id] dissoc :prev-handler) + (update-in [:workspace-local :edit-path id] dissoc :preview) + (update-in (get-path state) append-node position last-point prev-handler)) + state))))) (defn start-drag-handler [] (ptk/reify ::start-drag-handler @@ -158,7 +240,6 @@ (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] - (let [id (get-path-id state) handler-position (gpt/point x y) shape (get-in state (get-path state)) @@ -194,24 +275,15 @@ ;; Update the preview because can be outdated after the dragging (rx/of (preview-next-point handler)))))) -(defn close-path [position] - (ptk/reify ::close-path - ptk/WatchEvent - (watch [_ state stream] - (rx/of (add-node position) - ::end-path)))) +(declare close-path-drag-end) (defn close-path-drag-start [position] (ptk/reify ::close-path-drag-start ptk/WatchEvent (watch [_ state stream] - (let [zoom (get-in state [:workspace-local :zoom]) - threshold (/ 5 zoom) - check-if-dragging - (fn [current-position] - (let [start (gpt/point position) - current (gpt/point current-position)] - (>= (gpt/distance start current) 100))) + (let [id (get-path-id state) + zoom (get-in state [:workspace-local :zoom]) + start-position @ms/mouse-position stop-stream (->> stream (rx/filter #(or (end-path-event? %) @@ -228,25 +300,39 @@ (rx/concat - (rx/of (close-path position)) + (rx/of (add-node position)) (->> position-stream - (rx/filter check-if-dragging) + (rx/filter (dragging? start-position zoom)) (rx/take 1) (rx/merge-map #(rx/concat (rx/of (start-drag-handler)) drag-events-stream - (rx/of (finish-drag)))))))))) + (rx/of (finish-drag)) + (rx/of (close-path-drag-end))))) + (rx/of (finish-path "close-path"))))))) -(defn close-path-drag-end [position] - (ptk/reify ::close-path-drag-end)) +(defn close-path-drag-end [] + (ptk/reify ::close-path-drag-end + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (update-in state [:workspace-local :edit-path id] dissoc :prev-handler))))) (defn path-pointer-enter [position] - (ptk/reify ::path-pointer-enter)) + (ptk/reify ::path-pointer-enter + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (update-in state [:workspace-local :edit-path id :hover-points] (fnil conj #{}) position))))) (defn path-pointer-leave [position] - (ptk/reify ::path-pointer-leave)) + (ptk/reify ::path-pointer-leave + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (update-in state [:workspace-local :edit-path id :hover-points] disj position))))) (defn start-path-from-point [position] (ptk/reify ::start-path-from-point @@ -261,8 +347,45 @@ (rx/concat (rx/of (add-node position)) (rx/of (start-drag-handler)) drag-events - (rx/of (finish-drag)))) - ))) + (rx/of (finish-drag))))))) + +(defn make-corner [] + (ptk/reify ::make-corner + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-path-id state) + page-id (:current-page-id state) + shape (get-in state (get-path state)) + selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) + new-content (reduce ugp/make-corner-point (:content shape) selected-points) + [rch uch] (generate-path-changes page-id id (:content shape) new-content)] + (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) + +(defn make-curve [] + (ptk/reify ::make-curve + ptk/WatchEvent + (watch [_ state stream] + (let [id (get-path-id state) + page-id (:current-page-id state) + shape (get-in state (get-path state)) + selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) + new-content (reduce ugp/make-curve-point (:content shape) selected-points) + [rch uch] (generate-path-changes page-id id (:content shape) new-content)] + (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) + +(defn path-handler-enter [index prefix] + (ptk/reify ::path-handler-enter + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (update-in state [:workspace-local :edit-path id :hover-handlers] (fnil conj #{}) [index prefix]))))) + +(defn path-handler-leave [index prefix] + (ptk/reify ::path-handler-leave + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (update-in state [:workspace-local :edit-path id :hover-handlers] disj [index prefix]))))) ;; EVENT STREAMS @@ -270,38 +393,35 @@ [stream down-event] (->> stream (rx/filter ms/mouse-click?) - (rx/debounce 200) + #_(rx/debounce 200) (rx/first) (rx/map #(add-node down-event)))) (defn make-drag-stream - [stream down-event] + [stream down-event zoom] (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) (ms/mouse-up? %)))) drag-events (->> ms/mouse-position (rx/take-until mouse-up) (rx/map #(drag-handler %)))] - (->> (rx/timer 400) - (rx/merge-map #(rx/concat - (rx/of (add-node down-event)) - (rx/of (start-drag-handler)) - drag-events - (rx/of (finish-drag))))))) -(defn make-dbl-click-stream - [stream down-event] - (->> stream - (rx/filter ms/mouse-double-click?) - (rx/first) - (rx/merge-map - #(rx/of (add-node down-event) - ::end-path)))) + (rx/concat + (rx/of (add-node down-event)) + + (->> ms/mouse-position + (rx/take-until mouse-up) + (rx/filter (dragging? (gpt/point down-event) zoom)) + (rx/take 1) + (rx/merge-map + #(rx/concat + (rx/of (start-drag-handler)) + drag-events + (rx/of (finish-drag)))))))) (defn make-node-events-stream [stream] - (->> (rx/merge - (->> stream (rx/filter (ptk/type? ::close-path))) - (->> stream (rx/filter (ptk/type? ::close-path-drag-start)))) + (->> stream + (rx/filter (ptk/type? ::close-path-drag-start)) (rx/take 1) (rx/merge-map #(rx/empty)))) @@ -318,35 +438,32 @@ ptk/WatchEvent (watch [_ state stream] - (let [mouse-down (->> stream (rx/filter ms/mouse-down?)) + (let [zoom (get-in state [:workspace-local :zoom]) + mouse-down (->> stream (rx/filter ms/mouse-down?)) end-path-events (->> stream (rx/filter end-path-event?)) ;; Mouse move preview mousemove-events (->> ms/mouse-position (rx/take-until end-path-events) - (rx/throttle 50) (rx/map #(preview-next-point %))) ;; From mouse down we can have: click, drag and double click mousedown-events (->> mouse-down (rx/take-until end-path-events) - (rx/throttle 50) (rx/with-latest merge ms/mouse-position) ;; We change to the stream that emits the first event (rx/switch-map #(rx/race (make-node-events-stream stream) - (make-click-stream stream %) - (make-drag-stream stream %) - (make-dbl-click-stream stream %))))] + (make-drag-stream stream % zoom))))] (rx/concat - (rx/of (init-path id)) + (rx/of (init-path)) (rx/merge mousemove-events mousedown-events) - (rx/of (finish-path id))))))) + (rx/of (finish-path "after-events"))))))) (defn stop-path-edit [] (ptk/reify ::stop-path-edit @@ -408,34 +525,12 @@ (ptk/reify ::apply-content-modifiers ptk/WatchEvent (watch [_ state stream] - (let [id (get-in state [:workspace-local :edition]) + (let [id (get-path-id state) page-id (:current-page-id state) - shape (get-in state [:workspace-data :pages-index page-id :objects id]) - {old-content :content old-selrect :selrect old-points :points} shape - content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers] {}) - new-content (ugp/apply-content-modifiers old-content content-modifiers) - new-selrect (gsh/content->selrect new-content) - new-points (gsh/rect->points new-selrect) - - rch [{:type :mod-obj - :id id - :page-id page-id - :operations [{:type :set :attr :content :val new-content} - {:type :set :attr :selrect :val new-selrect} - {:type :set :attr :points :val new-points}]} - {:type :reg-objects - :page-id page-id - :shapes [id]}] - - uch [{:type :mod-obj - :id id - :page-id page-id - :operations [{:type :set :attr :content :val old-content} - {:type :set :attr :selrect :val old-selrect} - {:type :set :attr :points :val old-points}]} - {:type :reg-objects - :page-id page-id - :shapes [id]}]] + shape (get-in state (get-path state)) + content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) + new-content (ugp/apply-content-modifiers (:content shape) content-modifiers) + [rch uch] (generate-path-changes page-id (:id shape) (:content shape) new-content)] (rx/of (dwc/commit-changes rch uch {:commit-local? true}) (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers))))))) @@ -445,33 +540,10 @@ ptk/WatchEvent (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) + shape (get-in state (get-path state)) page-id (:current-page-id state) old-content (get-in state [:workspace-local :edit-path id :old-content]) - old-selrect (gsh/content->selrect old-content) - old-points (gsh/rect->points old-content) - shape (get-in state [:workspace-data :pages-index page-id :objects id]) - {new-content :content new-selrect :selrect new-points :points} shape - - rch [{:type :mod-obj - :id id - :page-id page-id - :operations [{:type :set :attr :content :val new-content} - {:type :set :attr :selrect :val new-selrect} - {:type :set :attr :points :val new-points}]} - {:type :reg-objects - :page-id page-id - :shapes [id]}] - - uch [{:type :mod-obj - :id id - :page-id page-id - :operations [{:type :set :attr :content :val old-content} - {:type :set :attr :selrect :val old-selrect} - {:type :set :attr :points :val old-points}]} - {:type :reg-objects - :page-id page-id - :shapes [id]}]] - + [rch uch] (generate-path-changes page-id id old-content (:content shape))] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) (declare start-draw-mode) @@ -486,9 +558,9 @@ (cond (not= content old-content) (rx/of (save-path-content) - (start-draw-mode)) + (start-draw-mode)) (= mode :draw) (rx/of :interrupt) - :else (rx/of (finish-path id))))))) + :else (rx/of (finish-path "changed-content"))))))) (defn move-path-point [start-point end-point] (ptk/reify ::move-point @@ -506,7 +578,7 @@ (let [point (ugp/command->point command)] (= point start-point))) - point-indices (->> (d/enumerate content) + point-indices (->> (cd/enumerate content) (filter command-for-point) (map first)) @@ -533,14 +605,25 @@ [position] (ptk/reify ::start-move-path-point ptk/WatchEvent - ;; TODO REWRITE (watch [_ state stream] - (let [stopper (->> stream (rx/filter ms/mouse-up?))] - (rx/concat - (->> ms/mouse-position - (rx/take-until stopper) - (rx/map #(move-path-point position %))) - (rx/of (apply-content-modifiers))))))) + (let [start-position @ms/mouse-position + stopper (->> stream (rx/filter ms/mouse-up?)) + zoom (get-in state [:workspace-local :zoom]) + + move-point-stream + (fn [] (rx/concat + (->> ms/mouse-position + (rx/take-until stopper) + (rx/map #(move-path-point position %))) + (rx/of (apply-content-modifiers))))] + + (->> ms/mouse-position + (rx/take-until stopper) + (rx/filter (dragging? start-position zoom)) + (rx/take 1) + (rx/merge-map #(move-point-stream))) + + )))) (defn start-move-handler [index prefix] @@ -604,7 +687,7 @@ (watch [_ state stream] (let [id (get-path-id state)] (cond - (and id (= :move mode)) (rx/of ::end-path) + (and id (= :move mode)) (rx/of (finish-path "change-edit-mode")) (and id (= :draw mode)) (rx/of (start-draw-mode)) :else (rx/empty)))))) @@ -614,7 +697,7 @@ (update [_ state] (let [id (get-in state [:workspace-local :edition])] (-> state - (update-in [:workspace-local :edit-path id :selected] (fnil conj #{}) [index type])))))) + (update-in [:workspace-local :edit-path id :selected-handlers] (fnil conj #{}) [index type])))))) (defn select-node [position] (ptk/reify ::select-node @@ -622,7 +705,7 @@ (update [_ state] (let [id (get-in state [:workspace-local :edition])] (-> state - (update-in [:workspace-local :edit-path id :selected-node] (fnil conj #{}) position)))))) + (assoc-in [:workspace-local :edit-path id :selected-points] #{position})))))) (defn deselect-node [position] (ptk/reify ::deselect-node @@ -630,7 +713,7 @@ (update [_ state] (let [id (get-in state [:workspace-local :edition])] (-> state - (update-in [:workspace-local :edit-path id :selected-node] (fnil disj #{}) position)))))) + (update-in [:workspace-local :edit-path id :selected-points] (fnil disj #{}) position)))))) (defn add-to-selection-handler [index type] (ptk/reify ::add-to-selection-handler @@ -656,11 +739,21 @@ (update [_ state] state))) +(defn deselect-all [] + (ptk/reify ::deselect-all + ptk/UpdateEvent + (update [_ state] + (let [id (get-path-id state)] + (-> state + (assoc-in [:workspace-local :edit-path id :selected-handlers] #{}) + (assoc-in [:workspace-local :edit-path id :selected-points] #{})))))) + (defn handle-new-shape-result [shape-id] (ptk/reify ::handle-new-shape-result ptk/UpdateEvent (update [_ state] (let [content (get-in state [:workspace-drawing :object :content] [])] + (us/verify ::content content) (if (> (count content) 1) (assoc-in state [:workspace-drawing :object :initialized?] true) state))) diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 38721a84c2..6a85274e60 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -11,6 +11,7 @@ "The main logic for SVG export functionality." (:require [rumext.alpha :as mf] + [cuerdas.core :as str] [app.common.uuid :as uuid] [app.common.pages :as cp] [app.common.pages-helpers :as cph] @@ -42,10 +43,15 @@ (defn- calculate-dimensions [{:keys [objects] :as data} vport] - (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})] - (->> (gsh/selection-rect shapes) - (gal/adjust-to-viewport vport) - #_(gsh/fix-invalid-rect-values)))) + (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + to-finite (fn [val fallback] (if (not (mth/finite? val)) fallback val)) + rect (->> (gsh/selection-rect shapes) + (gal/adjust-to-viewport vport))] + (-> rect + (update :x to-finite 0) + (update :y to-finite 0) + (update :width to-finite 10000) + (update :height to-finite 10000)))) (declare shape-wrapper-factory) @@ -93,21 +99,20 @@ :group [:> group-wrapper {:shape shape :frame frame}] nil)]))))) +(defn get-viewbox [{:keys [x y width height] :or {x 0 y 0 width 100 height 100}}] + (str/fmt "%s %s %s %s" x y width height)) + (mf/defc page-svg {::mf/wrap [mf/memo]} [{:keys [data width height] :as props}] (let [objects (:objects data) - vport {:width width :height height} - - dim (calculate-dimensions data vport) root (get objects uuid/zero) shapes (->> (:shapes root) (map #(get objects %))) - vbox (str (:x dim 0) " " - (:y dim 0) " " - (:width dim 100) " " - (:height dim 100)) + vport {:width width :height height} + dim (calculate-dimensions data vport) + vbox (get-viewbox dim) background-color (get-in data [:options :background] default-color) frame-wrapper (mf/use-memo diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index d7330361ee..9106df8aed 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -10,6 +10,7 @@ (ns app.main.ui.workspace.shapes.path (:require [rumext.alpha :as mf] + [goog.events :as events] [okulary.core :as l] [app.util.data :as d] [app.util.dom :as dom] @@ -30,7 +31,8 @@ [app.util.geom.path :as ugp] [app.common.geom.point :as gpt] [app.main.ui.cursors :as cur] - [app.main.ui.icons :as i])) + [app.main.ui.icons :as i]) + (:import goog.events.EventType)) (def primary-color "#1FDEA7") (def secondary-color "#DB00FF") @@ -94,7 +96,7 @@ (mf/defc path-actions [{:keys [shape]}] (let [id (mf/deref refs/selected-edition) - {:keys [edit-mode selected snap-toggled] :as all} (mf/deref current-edit-path-ref)] + {:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref current-edit-path-ref)] [:div.path-actions [:div.viewport-actions-group [:div.viewport-actions-entry {:class (when (= edit-mode :draw) "is-toggled") @@ -102,24 +104,28 @@ [:div.viewport-actions-entry {:class (when (= edit-mode :move) "is-toggled") :on-click #(st/emit! (drp/change-edit-mode :move))} i/pointer-inner]] - [:div.viewport-actions-group + #_[:div.viewport-actions-group [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-add] [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-remove]] - [:div.viewport-actions-group + #_[:div.viewport-actions-group [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-merge] [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-join] [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-separate]] [:div.viewport-actions-group - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-corner] - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-curve]] + [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") + :on-click #(when-not (empty? selected-points) + (st/emit! (drp/make-corner)))} i/nodes-corner] + [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") + :on-click #(when-not (empty? selected-points) + (st/emit! (drp/make-curve)))} i/nodes-curve]] - [:div.viewport-actions-group + #_[:div.viewport-actions-group [:div.viewport-actions-entry {:class (when snap-toggled "is-toggled")} i/nodes-snap]]])) -(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path?]}] +(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}] (let [{:keys [x y]} position on-enter @@ -132,35 +138,37 @@ on-click (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) + (when-not last-p? + (do (dom/stop-propagation event) + (dom/prevent-default event) - (cond - (and (= edit-mode :move) (not selected?)) - (st/emit! (drp/select-node position)) + (cond + (and (= edit-mode :move) (not selected?)) + (st/emit! (drp/select-node position)) - (and (= edit-mode :move) selected?) - (st/emit! (drp/deselect-node position)))) + (and (= edit-mode :move) selected?) + (st/emit! (drp/deselect-node position)))))) on-mouse-down (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) + (when-not last-p? + (do (dom/stop-propagation event) + (dom/prevent-default event) - (cond - (= edit-mode :move) - (st/emit! (drp/start-move-path-point position)) + (cond + (= edit-mode :move) + (st/emit! (drp/start-move-path-point position)) - (and (= edit-mode :draw) start-path?) - (st/emit! (drp/start-path-from-point position)) + (and (= edit-mode :draw) start-path?) + (st/emit! (drp/start-path-from-point position)) - (and (= edit-mode :draw) (not start-path?)) - (st/emit! (drp/close-path-drag-start position))))] + (and (= edit-mode :draw) (not start-path?)) + (st/emit! (drp/close-path-drag-start position))))))] [:g.path-point [:circle.path-point {:cx x :cy y - :r (/ 3 zoom) + :r (if (or selected? hover?) (/ 3.5 zoom) (/ 3 zoom)) :style {:cursor (when (= edit-mode :draw) cur/pen-node) :stroke-width (/ 1 zoom) :stroke (cond (or selected? hover?) black-color @@ -173,11 +181,21 @@ :r (/ 10 zoom) :on-click on-click :on-mouse-down on-mouse-down + :on-mouse-enter on-enter + :on-mouse-leave on-leave :style {:fill "transparent"}}]])) (mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode]}] (when (and point handler) (let [{:keys [x y]} handler + on-enter + (fn [event] + (st/emit! (drp/path-handler-enter index prefix))) + + on-leave + (fn [event] + (st/emit! (drp/path-handler-leave index prefix))) + on-click (fn [event] (dom/stop-propagation event) @@ -201,7 +219,7 @@ :y1 (:y point) :x2 x :y2 y - :style {:stroke gray-color + :style {:stroke (if hover? black-color gray-color) :stroke-width (/ 1 zoom)}}] [:rect {:x (- x (/ 3 zoom)) @@ -220,6 +238,8 @@ :r (/ 10 zoom) :on-click on-click :on-mouse-down on-mouse-down + :on-mouse-enter on-enter + :on-mouse-leave on-leave :style {:fill "transparent"}}]]))) (mf/defc path-preview [{:keys [zoom command from]}] @@ -239,17 +259,40 @@ (mf/defc path-editor [{:keys [shape zoom]}] - (let [edit-path-ref (make-edit-path-ref (:id shape)) - {:keys [edit-mode selected drag-handler prev-handler preview content-modifiers last-point]} (mf/deref edit-path-ref) + (let [editor-ref (mf/use-ref nil) + edit-path-ref (make-edit-path-ref (:id shape)) + {:keys [edit-mode + drag-handler + prev-handler + preview + content-modifiers + last-point + selected-handlers + selected-points + hover-handlers + hover-points]} (mf/deref edit-path-ref) {:keys [content]} shape - selected (or selected #{}) content (ugp/apply-content-modifiers content content-modifiers) points (->> content ugp/content->points (into #{})) last-command (last content) last-p (->> content last ugp/command->point) - handlers (ugp/content->handlers content)] + handlers (ugp/content->handlers content) - [:g.path-editor + handle-click-outside + (fn [event] + (let [current (dom/get-target event) + editor-dom (mf/ref-val editor-ref)] + (when-not (or (.contains editor-dom current) + (dom/class? current "viewport-actions-entry")) + (st/emit! (drp/deselect-all)))))] + + (mf/use-layout-effect + (fn [] + (let [keys [(events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] + #(doseq [key keys] + (events/unlistenByKey key))))) + + [:g.path-editor {:ref editor-ref} (when (and preview (not drag-handler)) [:& path-preview {:command preview :from last-p @@ -257,43 +300,41 @@ (for [position points] [:g.path-node - [:& path-point {:position position - :selected? false - :zoom zoom - :edit-mode edit-mode - :start-path? (nil? last-point)}] - [:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")} (for [[index prefix] (get handlers position)] (let [command (get content index) x (get-in command [:params (d/prefix-keyword prefix :x)]) y (get-in command [:params (d/prefix-keyword prefix :y)]) handler-position (gpt/point x y)] - [:& path-handler {:point position - :handler handler-position - :index index - :prefix prefix - :zoom zoom - :selected? false - :hover? false - :preview? false - :edit-mode edit-mode}]))]]) + (when (not= position handler-position) + [:& path-handler {:point position + :handler handler-position + :index index + :prefix prefix + :zoom zoom + :selected? (contains? selected-handlers [index prefix]) + :hover? (contains? hover-handlers [index prefix]) + :edit-mode edit-mode}])))] + [:& path-point {:position position + :zoom zoom + :edit-mode edit-mode + :selected? (contains? selected-points position) + :hover? (contains? hover-points position) + :last-p? (= last-point position) + :start-path? (nil? last-point)}]]) (when prev-handler [:g.prev-handler {:pointer-events "none"} [:& path-handler {:point last-p :handler prev-handler - :zoom zoom - :selected false}]]) + :zoom zoom}]]) (when drag-handler [:g.drag-handler {:pointer-events "none"} (when (not= :move-to (:command last-command)) [:& path-handler {:point last-p :handler (ugp/opposite-handler last-p drag-handler) - :zoom zoom - :selected false}]) + :zoom zoom}]) [:& path-handler {:point last-p :handler drag-handler - :zoom zoom - :selected false}]])])) + :zoom zoom}]])])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index c469e240b5..de145248ab 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -294,7 +294,7 @@ on-double-click (mf/use-callback - (mf/deps edition edit-path) + (mf/deps drawing-path?) (fn [event] (dom/stop-propagation event) (let [ctrl? (kbd/ctrl? event) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index c5cdc9c094..11057bc296 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -236,3 +236,7 @@ (defn get-root [] (query js/document "#app")) + +(defn ^boolean class? [node class-name] + (let [class-list (.-classList ^js node)] + (.contains ^js class-list class-name))) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index 601c628748..4e150f7a5d 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -10,6 +10,7 @@ (ns app.util.geom.path (:require [cuerdas.core :as str] + [app.common.data :as cd] [app.util.data :as d] [app.common.data :as cd] [app.common.geom.point :as gpt] @@ -247,8 +248,10 @@ content))] (reduce apply-to-index content modifiers))) -(defn command->point [{{:keys [x y]} :params}] - (gpt/point x y)) +(defn command->point [command] + (when-not (nil? command) + (let [{{:keys [x y]} :params} command] + (gpt/point x y)))) (defn content->points [content] (->> content @@ -256,23 +259,37 @@ (remove nil?) (into []))) -(defn content->handlers [content] - (->> (d/with-prev content) ;; [cmd, prev] - (d/enumerate) ;; [idx [cmd, prev]] +(defn get-handler [{:keys [params] :as command} prefix] + (let [cx (d/prefix-keyword prefix :x) + cy (d/prefix-keyword prefix :y)] + (when (and command + (contains? params cx) + (contains? params cy)) + (gpt/point (get params cx) + (get params cy))))) - (mapcat (fn [[index [cur-cmd prev-cmd]]] - (if (and prev-cmd - (= :curve-to (:command cur-cmd))) +(defn content->handlers + "Retrieve a map where for every point will retrieve a list of + the handlers that are associated with that point. + point -> [[index, prefix]]" + [content] + (->> (d/with-prev content) + (d/enumerate) + + (mapcat (fn [[index [cur-cmd pre-cmd]]] + (if (and pre-cmd (= :curve-to (:command cur-cmd))) (let [cur-pos (command->point cur-cmd) - pre-pos (command->point prev-cmd)] - [[pre-pos [index :c1]] - [cur-pos [index :c2]]]) + pre-pos (command->point pre-cmd)] + (-> [[pre-pos [index :c1]] + [cur-pos [index :c2]]])) []))) (group-by first) (cd/mapm #(mapv second %2)))) -(defn opposite-index [content index prefix] +(defn opposite-index + "Calculate sthe opposite index given a prefix and an index" + [content index prefix] (let [point (if (= prefix :c2) (command->point (nth content index)) (command->point (nth content (dec index)))) @@ -280,10 +297,99 @@ handlers (-> (content->handlers content) (get point)) - opposite-prefix (if (= prefix :c1) :c2 :c1) + opposite-prefix (if (= prefix :c1) :c2 :c1)] + (when (<= (count handlers) 2) + (->> handlers + (d/seek (fn [[index prefix]] (= prefix opposite-prefix))) + (first))))) - result (when (<= (count handlers) 2) - (->> handlers - (d/seek (fn [[index prefix]] (= prefix opposite-prefix))) - (first)))] - result)) +(defn remove-line-curves + "Remove all curves that have both handlers in the same position that the + beggining and end points. This makes them really line-to commands" + [content] + (let [with-prev (d/enumerate (d/with-prev content)) + process-command + (fn [content [index [command prev]]] + + (let [cur-point (command->point command) + pre-point (command->point prev) + handler-c1 (get-handler command :c1) + handler-c2 (get-handler command :c2)] + (if (and (= :curve-to (:command command)) + (= cur-point handler-c2) + (= pre-point handler-c1)) + (assoc content index {:command :line-to + :params cur-point}) + content)))] + + (reduce process-command content with-prev))) + +(defn make-corner-point + "Changes the content to make a point a 'corner'" + [content point] + (let [handlers (-> (content->handlers content) + (get point)) + change-content + (fn [content [index prefix]] + (let [cx (d/prefix-keyword prefix :x) + cy (d/prefix-keyword prefix :y)] + (-> content + (assoc-in [index :params cx] (:x point)) + (assoc-in [index :params cy] (:y point)))))] + (as-> content $ + (reduce change-content $ handlers) + (remove-line-curves $)))) + +(defn make-curve-point + "Changes the content to make the point a 'curve'. The handlers will be positioned + in the same vector that results from te previous->next points but with fixed length." + [content point] + (let [content-next (d/enumerate (d/with-prev-next content)) + + make-curve + (fn [command previous] + (if (= :line-to (:command command)) + (let [cur-point (command->point command) + pre-point (command->point previous)] + (-> command + (assoc :command :curve-to) + (assoc :params (make-curve-params cur-point pre-point)))) + command)) + + update-handler + (fn [command prefix handler] + (if (= :curve-to (:command command)) + (let [cx (d/prefix-keyword prefix :x) + cy (d/prefix-keyword prefix :y)] + (-> command + (assoc-in [:params cx] (:x handler)) + (assoc-in [:params cy] (:y handler)))) + command)) + + calculate-vector + (fn [point next prev] + (let [base-vector (if (or (nil? next) (nil? prev)) + (-> (gpt/to-vec point (or next prev)) + (gpt/normal-left)) + (gpt/to-vec next prev))] + (-> base-vector + (gpt/unit) + (gpt/multiply (gpt/point 100))))) + + redfn (fn [content [index [command prev next]]] + (if (= point (command->point command)) + (let [prev-point (if (= :move-to (:command command)) nil (command->point prev)) + next-point (if (= :move-to (:command next)) nil (command->point next)) + handler-vector (calculate-vector point next-point prev-point) + handler (gpt/add point handler-vector) + handler-opposite (gpt/add point (gpt/negate handler-vector))] + (-> content + (cd/update-when index make-curve prev) + (cd/update-when index update-handler :c2 handler) + (cd/update-when (inc index) make-curve command) + (cd/update-when (inc index) update-handler :c1 handler-opposite))) + + content))] + (as-> content $ + (reduce redfn $ content-next) + (remove-line-curves $)))) From 89f0f24707f41d704c273c6e9653d066571b2b39 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 25 Nov 2020 22:08:04 +0100 Subject: [PATCH 071/195] :sparkles: Fixed angle with shift in paths --- common/app/common/geom/point.cljc | 5 + .../app/main/data/workspace/drawing/path.cljs | 164 ++++++++++-------- .../app/main/ui/workspace/left_toolbar.cljs | 2 +- .../app/main/ui/workspace/shapes/path.cljs | 14 +- 4 files changed, 107 insertions(+), 78 deletions(-) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index 1f97b31744..ef0139f211 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -55,6 +55,11 @@ ;;(assert (not (nil? y))) (Point. x y))) +(defn angle->point [{:keys [x y]} angle distance] + (point + (+ x (* distance (mth/cos angle))) + (- y (* distance (mth/sin angle))))) + (defn add "Returns the addition of the supplied value to both coordinates of the point as a new point." diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index aed97a83e8..9e31ee460d 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -20,6 +20,7 @@ [app.common.data :as cd] [app.util.geom.path :as ugp] [app.main.streams :as ms] + [app.main.store :as st] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.drawing.common :as common] [app.common.geom.shapes.path :as gsp])) @@ -67,7 +68,7 @@ ;; CONSTANTS (defonce enter-keycode 13) -(defonce drag-threshold 2) +(defonce drag-threshold 5) ;; PRIVATE METHODS @@ -96,6 +97,25 @@ points (gsh/rect->points selrect)] (assoc shape :points points :selrect selrect))) +(defn closest-angle [angle] + (cond + (or (> angle 337.5) (<= angle 22.5)) 0 + (and (> angle 22.5) (<= angle 67.5)) 45 + (and (> angle 67.5) (<= angle 112.5)) 90 + (and (> angle 112.5) (<= angle 157.5)) 135 + (and (> angle 157.5) (<= angle 202.5)) 180 + (and (> angle 202.5) (<= angle 247.5)) 225 + (and (> angle 247.5) (<= angle 292.5)) 270 + (and (> angle 292.5) (<= angle 337.5)) 315)) + +(defn position-fixed-angle [point from-point] + (if (and from-point point) + (let [angle (mod (+ 360 (- (gpt/angle point from-point))) 360) + to-angle (closest-angle angle) + distance (gpt/distance point from-point)] + (gpt/angle->point from-point (mth/radians to-angle) distance)) + point)) + (defn next-node "Calculates the next-node to be inserted." [shape position prev-point prev-handler] @@ -177,6 +197,21 @@ (fn [current] (>= (gpt/distance start current) (/ drag-threshold zoom)))) +(defn drag-stream [to-stream] + (let [start @ms/mouse-position + zoom (get-in @st/state [:workspace-local :zoom] 1) + mouse-up (->> st/stream (rx/filter #(ms/mouse-up? %)))] + (->> ms/mouse-position + (rx/take-until mouse-up) + (rx/filter (dragging? start zoom)) + (rx/take 1) + (rx/merge-map (fn [] to-stream))))) + +(defn position-stream [] + (->> ms/mouse-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? %)))))) + ;; EVENTS (defn init-path [] @@ -190,24 +225,31 @@ (-> state (update-in [:workspace-local :edit-path id] clean-edit-state)))))) -(defn preview-next-point [{:keys [x y]}] +(defn preview-next-point [{:keys [x y shift?]}] (ptk/reify ::preview-next-point ptk/UpdateEvent (update [_ state] (let [id (get-path-id state) - position (gpt/point x y) + fix-angle? shift? + last-point (get-in state [:workspace-local :edit-path id :last-point]) + position (cond-> (gpt/point x y) + fix-angle? (position-fixed-angle last-point)) + shape (get-in state (get-path state)) {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id]) command (next-node shape position last-point prev-handler)] (assoc-in state [:workspace-local :edit-path id :preview] command))))) -(defn add-node [{:keys [x y]}] +(defn add-node [{:keys [x y shift?]}] (ptk/reify ::add-node ptk/UpdateEvent (update [_ state] (let [id (get-path-id state) - position (gpt/point x y) - {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id])] + fix-angle? shift? + {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id]) + position (cond-> (gpt/point x y) + fix-angle? (position-fixed-angle last-point)) + ] (if-not (= last-point position) (-> state (assoc-in [:workspace-local :edit-path id :last-point] position) @@ -301,16 +343,12 @@ (rx/concat (rx/of (add-node position)) - - (->> position-stream - (rx/filter (dragging? start-position zoom)) - (rx/take 1) - (rx/merge-map - #(rx/concat - (rx/of (start-drag-handler)) - drag-events-stream - (rx/of (finish-drag)) - (rx/of (close-path-drag-end))))) + (drag-stream + (rx/concat + (rx/of (start-drag-handler)) + drag-events-stream + (rx/of (finish-drag)) + (rx/of (close-path-drag-end)))) (rx/of (finish-path "close-path"))))))) (defn close-path-drag-end [] @@ -338,16 +376,21 @@ (ptk/reify ::start-path-from-point ptk/WatchEvent (watch [_ state stream] - (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) + (let [start-point @ms/mouse-position + zoom (get-in state [:workspace-local :zoom]) + mouse-up (->> stream (rx/filter #(or (end-path-event? %) (ms/mouse-up? %)))) drag-events (->> ms/mouse-position (rx/take-until mouse-up) (rx/map #(drag-handler %)))] - (rx/concat (rx/of (add-node position)) - (rx/of (start-drag-handler)) - drag-events - (rx/of (finish-drag))))))) + (rx/concat + (rx/of (add-node position)) + (drag-stream + (rx/concat + (rx/of (start-drag-handler)) + drag-events + (rx/of (finish-drag))))))))) (defn make-corner [] (ptk/reify ::make-corner @@ -389,14 +432,6 @@ ;; EVENT STREAMS -(defn make-click-stream - [stream down-event] - (->> stream - (rx/filter ms/mouse-click?) - #_(rx/debounce 200) - (rx/first) - (rx/map #(add-node down-event)))) - (defn make-drag-stream [stream down-event zoom] (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) @@ -407,16 +442,11 @@ (rx/concat (rx/of (add-node down-event)) - - (->> ms/mouse-position - (rx/take-until mouse-up) - (rx/filter (dragging? (gpt/point down-event) zoom)) - (rx/take 1) - (rx/merge-map - #(rx/concat - (rx/of (start-drag-handler)) - drag-events - (rx/of (finish-drag)))))))) + (drag-stream + (rx/concat + (rx/of (start-drag-handler)) + drag-events + (rx/of (finish-drag))))))) (defn make-node-events-stream [stream] @@ -444,7 +474,7 @@ ;; Mouse move preview mousemove-events - (->> ms/mouse-position + (->> (position-stream) (rx/take-until end-path-events) (rx/map #(preview-next-point %))) @@ -452,7 +482,7 @@ mousedown-events (->> mouse-down (rx/take-until end-path-events) - (rx/with-latest merge ms/mouse-position) + (rx/with-latest merge (position-stream)) ;; We change to the stream that emits the first event (rx/switch-map @@ -608,22 +638,14 @@ (watch [_ state stream] (let [start-position @ms/mouse-position stopper (->> stream (rx/filter ms/mouse-up?)) - zoom (get-in state [:workspace-local :zoom]) + zoom (get-in state [:workspace-local :zoom])] - move-point-stream - (fn [] (rx/concat - (->> ms/mouse-position - (rx/take-until stopper) - (rx/map #(move-path-point position %))) - (rx/of (apply-content-modifiers))))] - - (->> ms/mouse-position - (rx/take-until stopper) - (rx/filter (dragging? start-position zoom)) - (rx/take 1) - (rx/merge-map #(move-point-stream))) - - )))) + (drag-stream + (rx/concat + (->> ms/mouse-position + (rx/take-until stopper) + (rx/map #(move-path-point position %))) + (rx/of (apply-content-modifiers)))))))) (defn start-move-handler [index prefix] @@ -636,21 +658,21 @@ start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers index cx] 0) start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers index cy] 0)] - (rx/concat - (->> ms/mouse-position - (rx/take-until (->> stream (rx/filter ms/mouse-up?))) - (rx/with-latest vector ms/mouse-position-alt) - (rx/map - (fn [[pos alt?]] - (modify-handler - id - index - prefix - (+ start-delta-x (- (:x pos) (:x start-point))) - (+ start-delta-y (- (:y pos) (:y start-point))) - (not alt?)))) - ) - (rx/concat (rx/of (apply-content-modifiers)))))))) + (drag-stream + (rx/concat + (->> ms/mouse-position + (rx/take-until (->> stream (rx/filter ms/mouse-up?))) + (rx/with-latest vector ms/mouse-position-alt) + (rx/map + (fn [[pos alt?]] + (modify-handler + id + index + prefix + (+ start-delta-x (- (:x pos) (:x start-point))) + (+ start-delta-y (- (:y pos) (:y start-point))) + (not alt?))))) + (rx/concat (rx/of (apply-content-modifiers))))))))) (defn start-draw-mode [] (ptk/reify ::start-draw-mode diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index d67f40e14c..9308a5a1e5 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -93,7 +93,7 @@ {:alt (t locale "workspace.toolbar.path") :class (when (= selected-drawtool :path) "selected") :on-click (partial select-drawtool :path)} - i/curve] + i/pen] [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.comments") diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 9106df8aed..72a327f362 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -169,8 +169,7 @@ {:cx x :cy y :r (if (or selected? hover?) (/ 3.5 zoom) (/ 3 zoom)) - :style {:cursor (when (= edit-mode :draw) cur/pen-node) - :stroke-width (/ 1 zoom) + :style {:stroke-width (/ 1 zoom) :stroke (cond (or selected? hover?) black-color preview? secondary-color :else primary-color) @@ -183,7 +182,10 @@ :on-mouse-down on-mouse-down :on-mouse-enter on-enter :on-mouse-leave on-leave - :style {:fill "transparent"}}]])) + :style {:cursor (cond + (and (not last-p?) (= edit-mode :draw)) cur/pen-node + (= edit-mode :move) cur/pointer-node) + :fill "transparent"}}]])) (mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode]}] (when (and point handler) @@ -227,8 +229,7 @@ :width (/ 6 zoom) :height (/ 6 zoom) - :style {:cursor cur/pointer-move - :stroke-width (/ 1 zoom) + :style {:stroke-width (/ 1 zoom) :stroke (cond (or selected? hover?) black-color :else primary-color) :fill (cond selected? primary-color @@ -240,7 +241,8 @@ :on-mouse-down on-mouse-down :on-mouse-enter on-enter :on-mouse-leave on-leave - :style {:fill "transparent"}}]]))) + :style {:cursor (when (= edit-mode :move) cur/pointer-move) + :fill "transparent"}}]]))) (mf/defc path-preview [{:keys [zoom command from]}] [:g.preview {:style {:pointer-events "none"}} From f8cf7103ca55085993d6dc81698460868712c9c3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 26 Nov 2020 10:50:24 +0100 Subject: [PATCH 072/195] :sparkles: Improved opposite handler management --- .../app/main/data/workspace/drawing/path.cljs | 72 +++++++++++-------- .../app/main/ui/workspace/shapes/path.cljs | 4 -- frontend/src/app/util/geom/path.cljs | 2 +- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 9e31ee460d..4599e903b0 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -62,9 +62,6 @@ (s/def ::content (s/coll-of ::content-entry :kind vector?)) -(s/def ::path-shape - (s/keys :req-un [::content])) - ;; CONSTANTS (defonce enter-keycode 13) @@ -234,7 +231,6 @@ last-point (get-in state [:workspace-local :edit-path id :last-point]) position (cond-> (gpt/point x y) fix-angle? (position-fixed-angle last-point)) - shape (get-in state (get-path state)) {:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id]) command (next-node shape position last-point prev-handler)] @@ -278,21 +274,22 @@ (= command :line-to) (update-in (get-path state :content index) make-curve)))))) -(defn drag-handler [{:keys [x y]}] +(defn drag-handler [{:keys [x y alt? shift?]}] (ptk/reify ::drag-handler ptk/UpdateEvent (update [_ state] (let [id (get-path-id state) - handler-position (gpt/point x y) shape (get-in state (get-path state)) content (:content shape) index (dec (count content)) node-position (ugp/command->point (nth content index)) + handler-position (cond-> (gpt/point x y) + shift? (position-fixed-angle node-position)) {dx :x dy :y} (gpt/subtract handler-position node-position) - match-opposite? true + match-opposite? (not alt?) modifiers (move-handler-modifiers content (inc index) :c1 match-opposite? dx dy)] (-> state - (assoc-in [:workspace-local :edit-path id :content-modifiers] modifiers) + (update-in [:workspace-local :edit-path id :content-modifiers] merge modifiers) (assoc-in [:workspace-local :edit-path id :prev-handler] handler-position) (assoc-in [:workspace-local :edit-path id :drag-handler] handler-position)))))) @@ -331,16 +328,11 @@ (->> stream (rx/filter #(or (end-path-event? %) (ms/mouse-up? %)))) - position-stream - (->> ms/mouse-position - (rx/take-until stop-stream) - (rx/throttle 50)) - drag-events-stream - (->> position-stream + (->> (position-stream) + (rx/take-until stop-stream) (rx/map #(drag-handler %)))] - (rx/concat (rx/of (add-node position)) (drag-stream @@ -436,7 +428,7 @@ [stream down-event zoom] (let [mouse-up (->> stream (rx/filter #(or (end-path-event? %) (ms/mouse-up? %)))) - drag-events (->> ms/mouse-position + drag-events (->> (position-stream) (rx/take-until mouse-up) (rx/map #(drag-handler %)))] @@ -567,6 +559,14 @@ (defn save-path-content [] (ptk/reify ::save-path-content + ptk/UpdateEvent + (update [_ state] + (let [content (get-in state (get-path state :content)) + content (if (= (-> content last :command) :move-to) + (into [] (take (dec (count content)) content)) + content)] + (assoc-in state (get-path state :content) content))) + ptk/WatchEvent (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) @@ -653,25 +653,39 @@ ptk/WatchEvent (watch [_ state stream] (let [id (get-in state [:workspace-local :edition]) - [cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y]) + cx (ud/prefix-keyword prefix :x) + cy (ud/prefix-keyword prefix :y) start-point @ms/mouse-position - start-delta-x (get-in state [:workspace-local :edit-path id :content-modifiers index cx] 0) - start-delta-y (get-in state [:workspace-local :edit-path id :content-modifiers index cy] 0)] + modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) + start-delta-x (get-in modifiers [index cx] 0) + start-delta-y (get-in modifiers [index cy] 0) + + content (get-in state (get-path state :content)) + opposite-index (ugp/opposite-index content index prefix) + opposite-prefix (if (= prefix :c1) :c2 :c1) + opposite-handler (-> content (get opposite-index) (ugp/get-handler opposite-prefix)) + + point (-> content (get (if (= prefix :c1) (dec index) index)) (ugp/command->point)) + handler (-> content (get index) (ugp/get-handler prefix)) + + current-distance (gpt/distance (ugp/opposite-handler point handler) opposite-handler) + match-opposite? (mth/almost-zero? current-distance)] (drag-stream (rx/concat - (->> ms/mouse-position + (->> (position-stream) (rx/take-until (->> stream (rx/filter ms/mouse-up?))) - (rx/with-latest vector ms/mouse-position-alt) (rx/map - (fn [[pos alt?]] - (modify-handler - id - index - prefix - (+ start-delta-x (- (:x pos) (:x start-point))) - (+ start-delta-y (- (:y pos) (:y start-point))) - (not alt?))))) + (fn [{:keys [x y alt? shift?]}] + (let [pos (cond-> (gpt/point x y) + shift? (position-fixed-angle point))] + (modify-handler + id + index + prefix + (+ start-delta-x (- (:x pos) (:x start-point))) + (+ start-delta-y (- (:y pos) (:y start-point))) + (and (not alt?) match-opposite?)))))) (rx/concat (rx/of (apply-content-modifiers))))))))) (defn start-draw-mode [] diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 72a327f362..09a3ab9b2d 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -333,10 +333,6 @@ (when drag-handler [:g.drag-handler {:pointer-events "none"} - (when (not= :move-to (:command last-command)) - [:& path-handler {:point last-p - :handler (ugp/opposite-handler last-p drag-handler) - :zoom zoom}]) [:& path-handler {:point last-p :handler drag-handler :zoom zoom}]])])) diff --git a/frontend/src/app/util/geom/path.cljs b/frontend/src/app/util/geom/path.cljs index 4e150f7a5d..5357563a78 100644 --- a/frontend/src/app/util/geom/path.cljs +++ b/frontend/src/app/util/geom/path.cljs @@ -368,7 +368,7 @@ calculate-vector (fn [point next prev] - (let [base-vector (if (or (nil? next) (nil? prev)) + (let [base-vector (if (or (nil? next) (nil? prev) (= next prev)) (-> (gpt/to-vec point (or next prev)) (gpt/normal-left)) (gpt/to-vec next prev))] From f314efdfdc8e986dd1b529008dfceaadca3179cc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 11:38:44 +0100 Subject: [PATCH 073/195] :bug: Fix shared token link creation. --- frontend/src/app/main/data/viewer.cljs | 93 +++++++++++---------- frontend/src/app/main/ui/viewer/header.cljs | 4 +- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 635c155690..bdff939da7 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -71,11 +71,14 @@ (ptk/reify ::initialize ptk/UpdateEvent (update [_ state] - (update state :viewer-local - (fn [lstate] - (if (nil? lstate) - default-local-state - lstate)))) + (-> state + (assoc :current-file-id file-id) + (assoc :current-page-id page-id) + (update :viewer-local + (fn [lstate] + (if (nil? lstate) + default-local-state + lstate))))) ptk/WatchEvent (watch [_ state stream] @@ -98,9 +101,35 @@ :file-id file-id} (string? token) (assoc :token token))] (->> (rp/query :viewer-bundle params) - (rx/first) (rx/map bundle-fetched)))))) +(defn- extract-frames + [objects] + (let [root (get objects uuid/zero)] + (into [] (comp (map #(get objects %)) + (filter #(= :frame (:type %)))) + (reverse (:shapes root))))) + +(defn bundle-fetched + [{:keys [project file page share-token token libraries users] :as bundle}] + (us/verify ::bundle bundle) + (ptk/reify ::file-fetched + ptk/UpdateEvent + (update [_ state] + (let [objects (:objects page) + frames (extract-frames objects) + users (map #(avatars/assoc-avatar % :fullname) users)] + (assoc state + :viewer-libraries (d/index-by :id libraries) + :viewer-data {:project project + :objects objects + :users (d/index-by :id users) + :file file + :page page + :frames frames + :token token + :share-token share-token}))))) + (defn fetch-comment-threads [{:keys [file-id page-id] :as params}] (letfn [(fetched [data state] @@ -135,56 +164,30 @@ (->> (rp/query :comments {:thread-id thread-id}) (rx/map #(partial fetched %))))))) -(defn- extract-frames - [objects] - (let [root (get objects uuid/zero)] - (->> (:shapes root) - (map #(get objects %)) - (filter #(= :frame (:type %))) - (reverse) - (vec)))) - -(defn bundle-fetched - [{:keys [project file page share-token token libraries users] :as bundle}] - (us/verify ::bundle bundle) - (ptk/reify ::file-fetched - ptk/UpdateEvent - (update [_ state] - (let [objects (:objects page) - frames (extract-frames objects) - users (map #(avatars/assoc-avatar % :fullname) users)] - (-> state - (assoc :viewer-libraries (d/index-by :id libraries) - :viewer-data {:project project - :objects objects - :users (d/index-by :id users) - :file file - :page page - :frames frames - :token token - :share-token share-token})))))) - -(def create-share-link +(defn create-share-link + [] (ptk/reify ::create-share-link ptk/WatchEvent (watch [_ state stream] - (let [file-id (get-in state [:viewer-local :file-id]) - page-id (get-in state [:viewer-local :page-id])] + (let [file-id (:current-file-id state) + page-id (:current-page-id state)] (->> (rp/mutation! :create-file-share-token {:file-id file-id :page-id page-id}) (rx/map (fn [{:keys [token]}] #(assoc-in % [:viewer-data :share-token] token)))))))) -(def delete-share-link +(defn delete-share-link + [] (ptk/reify ::delete-share-link ptk/WatchEvent (watch [_ state stream] - (let [file-id (get-in state [:viewer-local :file-id]) - page-id (get-in state [:viewer-local :page-id]) - token (get-in state [:viewer-data :share-token])] - (->> (rp/mutation :delete-file-share-token {:file-id file-id - :page-id page-id - :token token}) + (let [file-id (:current-file-id state) + page-id (:current-page-id state) + token (get-in state [:viewer-data :share-token]) + params {:file-id file-id + :page-id page-id + :token token}] + (->> (rp/mutation :delete-file-share-token params) (rx/map (fn [_] #(update % :viewer-data dissoc :share-token)))))))) ;; --- Zoom Management diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 3f23bd07c4..f0bd849f36 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -60,8 +60,8 @@ dropdown-ref (mf/use-ref) locale (mf/deref i18n/locale) - create #(st/emit! dv/create-share-link) - delete #(st/emit! dv/delete-share-link) + create (st/emitf (dv/create-share-link)) + delete (st/emitf (dv/delete-share-link)) href (.-href js/location) href (subs href 0 (str/index-of href "?")) From 81e909b961dc4e0bf73e5a930c0e2b595e122223 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 11:48:52 +0100 Subject: [PATCH 074/195] :sparkles: Create frames in reverse order of other shapes. --- common/app/common/pages.cljc | 50 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 0188a1eab4..eda4584d1d 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -735,28 +735,38 @@ (defmethod process-change :add-obj [data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched] :as change}] - (let [update-fn (fn [data] - (let [parent-id (or parent-id frame-id) - objects (:objects data)] - (let [obj (assoc obj - :frame-id frame-id - :parent-id parent-id - :id id)] - (-> data - (update :objects assoc id obj) - (update-in [:objects parent-id :shapes] - (fn [shapes] - (let [shapes (or shapes [])] - (cond - (some #{id} shapes) shapes - (nil? index) (conj shapes id) - :else (cph/insert-at-index shapes index [id]))))) - (cond-> - (and (:shape-ref (get-in data [:objects parent-id])) + (letfn [(update-fn [data] + (let [parent-id (or parent-id frame-id) + objects (:objects data)] + (let [obj (assoc obj + :frame-id frame-id + :parent-id parent-id + :id id)] + (if (and (contains? objects parent-id) + (contains? objects frame-id)) + (-> data + (update :objects assoc id obj) + (update-in [:objects parent-id :shapes] + (fn [shapes] + (let [shapes (or shapes [])] + (cond + (some #{id} shapes) + shapes + + (nil? index) + (if (= :frame (:type obj)) + (d/concat [id] shapes) + (conj shapes id)) + + :else + (cph/insert-at-index shapes index [id]))))) + + (cond-> (and (:shape-ref (get-in data [:objects parent-id])) (not= parent-id frame-id) (not ignore-touched)) - (update-in [:objects parent-id :touched] - cph/set-touched-group :shapes-group))))))] + (update-in [:objects parent-id :touched] + cph/set-touched-group :shapes-group))) + data))))] (if page-id (d/update-in-when data [:pages-index page-id] update-fn) (d/update-in-when data [:components component-id] update-fn)))) From be24e1fb71512f35215d306b9419881588cee2ea Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 12:57:02 +0100 Subject: [PATCH 075/195] :sparkles: Improve specs usage on messages. --- frontend/src/app/main/data/messages.cljs | 38 ++++++++++++++++-------- frontend/src/app/main/ui/messages.cljs | 18 +++-------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index c4837c0fbf..a688c756b8 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -9,32 +9,46 @@ (ns app.main.data.messages (:require - [beicon.core :as rx] - [cljs.spec.alpha :as s] - [potok.core :as ptk] [app.common.data :as d] [app.common.exceptions :as ex] [app.common.pages :as cp] [app.common.spec :as us] - [app.config :as cfg])) + [app.config :as cfg] + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [potok.core :as ptk])) (declare hide) (declare show) (def +animation-timeout+ 600) -(s/def ::message-type #{:success :error :info :warning}) -(s/def ::message-position #{:fixed :floating :inline}) -(s/def ::message-status #{:visible :hide}) -(s/def ::message-controls #{:none :close :inline-actions :bottom-actions}) -(s/def ::message-tag string?) -(s/def ::label string?) +(s/def ::type #{:success :error :info :warning}) +(s/def ::position #{:fixed :floating :inline}) +(s/def ::status #{:visible :hide}) +(s/def ::controls #{:none :close :inline-actions :bottom-actions}) + +(s/def ::tag ::us/string) +(s/def ::label ::us/string) (s/def ::callback fn?) -(s/def ::message-action (s/keys :req-un [::label ::callback])) -(s/def ::message-actions (s/nilable (s/coll-of ::message-action :kind vector?))) +(s/def ::action (s/keys :req-un [::label ::callback])) +(s/def ::actions (s/every ::message-action :kind vector?)) +(s/def ::timeout ::us/integer) +(s/def ::content ::us/string) + +(s/def ::message + (s/keys :req-un [::type] + :opt-un [::status + ::position + ::controls + ::tag + ::timeout + ::actions + ::status])) (defn show [data] + (us/verify ::message data) (ptk/reify ::show ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/ui/messages.cljs b/frontend/src/app/main/ui/messages.cljs index 0b41989bd9..fc6f092bd0 100644 --- a/frontend/src/app/main/ui/messages.cljs +++ b/frontend/src/app/main/ui/messages.cljs @@ -9,27 +9,17 @@ (ns app.main.ui.messages (:require - [rumext.alpha :as mf] - [clojure.spec.alpha :as s] - [app.common.uuid :as uuid] [app.common.spec :as us] - [app.main.ui.icons :as i] + [app.common.uuid :as uuid] [app.main.data.messages :as dm] [app.main.refs :as refs] [app.main.store :as st] - [app.util.data :refer [classnames]] + [app.main.ui.icons :as i] [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [t]] - [app.util.timers :as ts])) + [rumext.alpha :as mf])) (mf/defc banner [{:keys [type position status controls content actions on-close] :as props}] - (us/assert ::dm/message-type type) - (us/assert ::dm/message-position position) - (us/assert ::dm/message-status status) - (us/assert ::dm/message-controls controls) - (us/assert ::dm/message-actions actions) - (us/assert (s/nilable ::us/fn) on-close) [:div.banner {:class (dom/classnames :warning (= type :warning) :error (= type :error) @@ -62,7 +52,7 @@ (mf/defc notifications [] (let [message (mf/deref refs/message) - on-close #(st/emit! dm/hide)] + on-close (st/emitf dm/hide)] (when message [:& banner (assoc message :position (or (:position message) :fixed) From 6c07cfcd2553bc7f658ba926fd3987d3d6c873bb Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 15:40:33 +0100 Subject: [PATCH 076/195] :sparkles: Reuse transducers on points->rect transformation. --- common/app/common/geom/shapes/common.cljc | 13 +++++++++---- common/app/common/geom/shapes/rect.cljc | 11 ++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index ba3b83527e..75ea7df5a3 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -30,11 +30,16 @@ [selrect] (center-rect selrect)) +(def map-x-xf (comp (map :x) (remove nil?))) +(def map-y-xf (comp (map :y) (remove nil?))) + (defn center-points [points] - (let [minx (transduce (map :x) min ##Inf points) - miny (transduce (map :y) min ##Inf points) - maxx (transduce (map :x) max ##-Inf points) - maxy (transduce (map :y) max ##-Inf points)] + (let [ptx (into [] map-x-xf points) + pty (into [] map-y-xf points) + minx (reduce min ##Inf ptx) + miny (reduce min ##Inf pty) + maxx (reduce max ##-Inf ptx) + maxy (reduce max ##-Inf pty)] (gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2)))) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index bca71f3adb..330a54a8b4 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -23,11 +23,12 @@ (gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))]) -(defn points->rect [points] - (let [minx (transduce (comp (map :x) (remove nil?)) min ##Inf points) - miny (transduce (comp (map :y) (remove nil?)) min ##Inf points) - maxx (transduce (comp (map :x) (remove nil?)) max ##-Inf points) - maxy (transduce (comp (map :y) (remove nil?)) max ##-Inf points)] +(defn points->rect + [points] + (let [minx (transduce gco/map-x-xf min ##Inf points) + miny (transduce gco/map-y-xf min ##Inf points) + maxx (transduce gco/map-x-xf max ##-Inf points) + maxy (transduce gco/map-y-xf max ##-Inf points)] {:x minx :y miny :width (- maxx minx) From 76d8ca1e72d82462681dac4889b9204904502e74 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 16:30:30 +0100 Subject: [PATCH 077/195] :paperclip: Cosmetic changes on text shape component. --- frontend/src/app/main/ui/shapes/text.cljs | 49 ++++++------ .../app/main/ui/workspace/shapes/text.cljs | 80 ++++++++++--------- 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 3fbc1f972b..4a4513e019 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -2,24 +2,27 @@ ;; 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) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.ui.shapes.text (:require - [clojure.set :as set] - [promesa.core :as p] - [cuerdas.core :as str] - [rumext.alpha :as mf] + [app.common.data :as d] + [app.common.geom.matrix :as gmt] + [app.common.geom.shapes :as geom] [app.main.data.fetch :as df] [app.main.fonts :as fonts] [app.main.ui.context :as muc] [app.main.ui.shapes.group :refer [mask-id-ctx]] - [app.common.data :as d] - [app.common.geom.shapes :as geom] - [app.common.geom.matrix :as gmt] - [app.util.object :as obj] [app.util.color :as uc] - [app.util.text :as ut])) + [app.util.object :as obj] + [app.util.text :as ut] + [clojure.set :as set] + [cuerdas.core :as str] + [promesa.core :as p] + [rumext.alpha :as mf])) ;; --- Text Editor Rendering @@ -31,12 +34,12 @@ :width "100%" :display "flex"}] (cond-> base - (= valign "top") (obj/set! "alignItems" "flex-start") - (= valign "center") (obj/set! "alignItems" "center") - (= valign "bottom") (obj/set! "alignItems" "flex-end") - (= talign "left") (obj/set! "justifyContent" "flex-start") - (= talign "center") (obj/set! "justifyContent" "center") - (= talign "right") (obj/set! "justifyContent" "flex-end") + (= valign "top") (obj/set! "alignItems" "flex-start") + (= valign "center") (obj/set! "alignItems" "center") + (= valign "bottom") (obj/set! "alignItems" "flex-end") + (= talign "left") (obj/set! "justifyContent" "flex-start") + (= talign "center") (obj/set! "justifyContent" "center") + (= talign "right") (obj/set! "justifyContent" "flex-end") (= talign "justify") (obj/set! "justifyContent" "stretch")))) (defn- generate-paragraph-styles @@ -52,19 +55,19 @@ (defn- generate-text-styles [data] - (let [letter-spacing (obj/get data "letter-spacing") + (let [letter-spacing (obj/get data "letter-spacing") text-decoration (obj/get data "text-decoration") - text-transform (obj/get data "text-transform") - line-height (obj/get data "line-height") + text-transform (obj/get data "text-transform") + line-height (obj/get data "line-height") - font-id (obj/get data "font-id" (:font-id ut/default-text-attrs)) + font-id (obj/get data "font-id" (:font-id ut/default-text-attrs)) font-variant-id (obj/get data "font-variant-id") - font-family (obj/get data "font-family") - font-size (obj/get data "font-size") + font-family (obj/get data "font-family") + font-size (obj/get data "font-size") ;; Old properties for backwards compatibility - fill (obj/get data "fill") + fill (obj/get data "fill") opacity (obj/get data "opacity" 1) fill-color (obj/get data "fill-color" fill) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index c389583f50..2a9b1b24b3 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -11,32 +11,32 @@ (:require ["slate" :as slate] ["slate-react" :as rslate] - [goog.events :as events] - [goog.object :as gobj] - [cuerdas.core :as str] - [rumext.alpha :as mf] - [beicon.core :as rx] - [app.util.color :as color] - [app.util.dom :as dom] - [app.util.text :as ut] - [app.util.object :as obj] - [app.util.color :as uc] - [app.util.timers :as timers] [app.common.data :as d] [app.common.geom.shapes :as geom] - [app.main.refs :as refs] - [app.main.store :as st] - [app.main.fonts :as fonts] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.texts :as dwt] - [app.main.ui.cursors :as cur] - [app.main.ui.workspace.shapes.common :as common] - [app.main.ui.shapes.text :as text] - [app.main.ui.keyboard :as kbd] + [app.main.fonts :as fonts] + [app.main.refs :as refs] + [app.main.store :as st] [app.main.ui.context :as muc] + [app.main.ui.cursors :as cur] + [app.main.ui.keyboard :as kbd] [app.main.ui.shapes.filters :as filters] - [app.main.ui.shapes.shape :refer [shape-container]]) + [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.shapes.text :as text] + [app.main.ui.workspace.shapes.common :as common] + [app.util.color :as color] + [app.util.color :as uc] + [app.util.dom :as dom] + [app.util.object :as obj] + [app.util.text :as ut] + [app.util.timers :as timers] + [beicon.core :as rx] + [cuerdas.core :as str] + [goog.events :as events] + [goog.object :as gobj] + [rumext.alpha :as mf]) (:import goog.events.EventType goog.events.KeyCodes)) @@ -59,38 +59,40 @@ (mf/defc text-wrapper {::mf/wrap-props false} [props] - (let [{:keys [id x1 y1 content group grow-type width height ] :as shape} (unchecked-get props "shape") - selected-iref (mf/use-memo (mf/deps (:id shape)) - #(refs/make-selected-ref (:id shape))) - selected? (mf/deref selected-iref) - edition (mf/deref refs/selected-edition) + (let [shape (unchecked-get props "shape") + selected-iref (mf/use-memo (mf/deps (:id shape)) + #(refs/make-selected-ref (:id shape))) + selected? (mf/deref selected-iref) + edition (mf/deref refs/selected-edition) current-transform (mf/deref refs/current-transform) + render-editor (mf/use-state false) - render-editor (mf/use-state false) + edition? (= edition (:id shape)) - edition? (= edition id) + embed-resources? (mf/use-ctx muc/embed-ctx) - embed-resources? (mf/use-ctx muc/embed-ctx) - - on-mouse-down #(handle-mouse-down % shape) - on-context-menu #(common/on-context-menu % shape) + on-mouse-down #(handle-mouse-down % shape) + on-context-menu #(common/on-context-menu % shape) on-double-click (fn [event] (dom/stop-propagation event) (dom/prevent-default event) (when selected? - (st/emit! (dw/start-edition-mode (:id shape)))))] + (st/emit! (dw/start-edition-mode (:id shape))))) + + check? + (and (#{:auto-width :auto-height} (:grow-type shape)) + selected? + (not edition?) + (not embed-resources?) + (nil? current-transform))] (mf/use-effect - (mf/deps shape edition selected? current-transform) - (fn [] (let [check? (and (#{:auto-width :auto-height} (:grow-type shape)) - selected? - (not edition?) - (not embed-resources?) - (nil? current-transform)) - result (timers/schedule #(reset! render-editor check?))] - #(rx/dispose! result)))) + (mf/deps check?) + (fn [] + (let [sem (timers/schedule #(reset! render-editor check?))] + #(rx/dispose! sem)))) [:> shape-container {:shape shape :on-double-click on-double-click From 5a17237015f3a8bbe7c9750d0173f36f57f27681 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 17:03:30 +0100 Subject: [PATCH 078/195] :paperclip: Minor cosmetic fixes on workspace shape wrapper component. --- frontend/src/app/main/ui/workspace/shapes.cljs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 52cb950406..2652591d4a 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -90,23 +90,21 @@ on-mouse-enter (use-mouse-enter shape) on-mouse-leave (use-mouse-leave shape) + alt? (hooks/use-rxsub ms/keyboard-alt) + moving-iref (mf/use-memo (mf/deps (:id shape)) #(make-is-moving-ref (:id shape))) moving? (mf/deref moving-iref)] - (hooks/use-stream ms/keyboard-alt #(reset! alt? %)) - (mf/use-effect - (fn [] - (fn [] - (on-mouse-leave)))) + (constantly on-mouse-leave)) (when (and shape (or ghost? (not moving?)) (not (:hidden shape))) [:g.shape-wrapper {:on-mouse-enter on-mouse-enter :on-mouse-leave on-mouse-leave - :style {:cursor (if @alt? cur/duplicate nil)}} + :style {:cursor (if alt? cur/duplicate nil)}} (case (:type shape) :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] From 1d08bac4938feb76b9c561f44906383e3d761e37 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 19:51:01 +0100 Subject: [PATCH 079/195] :sparkles: Remove cl-format usage from cursors. --- frontend/src/app/main/ui/cursors.clj | 25 +++++++++------------- frontend/src/app/main/ui/cursors.cljs | 30 +++++++++++++++------------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/frontend/src/app/main/ui/cursors.clj b/frontend/src/app/main/ui/cursors.clj index d7ed83b71d..e816aed0f4 100644 --- a/frontend/src/app/main/ui/cursors.clj +++ b/frontend/src/app/main/ui/cursors.clj @@ -8,11 +8,10 @@ ;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.ui.cursors - (:import java.net.URLEncoder) - (:require [rumext.alpha] - [clojure.java.io :as io] - [lambdaisland.uri.normalize :as uri] - [cuerdas.core :as str])) + (:require + [clojure.java.io :as io] + [cuerdas.core :as str] + [lambdaisland.uri.normalize :as uri])) (def cursor-folder "images/cursors") @@ -55,22 +54,18 @@ (defn encode-svg-cursor [id rotation x y height] - (let [svg-path (str cursor-folder "/" (name id) ".svg") - data (-> svg-path io/resource slurp parse-svg uri/percent-encode) - transform (if rotation (str " transform='rotate(" rotation ")'") "") - data (clojure.pprint/cl-format - nil - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' height='~Apx'~A%3E~A%3C/svg%3E\") ~A ~A, auto" - height transform data x y )] - data)) + (let [svg-path (str cursor-folder "/" (name id) ".svg") + data (-> svg-path io/resource slurp parse-svg uri/percent-encode) + transform (if rotation (str " transform='rotate(" rotation ")'") "")] + (str "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' " + "height='" height "px' " transform "%3E" data "%3C/svg%3E\") " x " " y ", auto"))) (defmacro cursor-ref "Creates a static cursor given its name, rotation and x/y hotspot" ([id] (encode-svg-cursor id default-rotation default-hotspot-x default-hotspot-y default-height)) ([id rotation] (encode-svg-cursor id rotation default-hotspot-x default-hotspot-y default-height)) ([id rotation x y] (encode-svg-cursor id rotation x y default-height)) - ([id rotation x y height] (encode-svg-cursor id rotation x y height)) - ) + ([id rotation x y height] (encode-svg-cursor id rotation x y height))) (defmacro cursor-fn "Creates a dynamic cursor that can be rotated in runtime" diff --git a/frontend/src/app/main/ui/cursors.cljs b/frontend/src/app/main/ui/cursors.cljs index 24028c30f0..46a1b5d2e9 100644 --- a/frontend/src/app/main/ui/cursors.cljs +++ b/frontend/src/app/main/ui/cursors.cljs @@ -13,6 +13,8 @@ [cuerdas.core :as str] [app.util.timers :as ts])) +;; Static cursors +(def comments (cursor-ref :comments 0 2 20)) (def create-artboard (cursor-ref :create-artboard)) (def create-ellipse (cursor-ref :create-ellipse)) (def create-polygon (cursor-ref :create-polygon)) @@ -21,21 +23,23 @@ (def duplicate (cursor-ref :duplicate 0 0 0)) (def hand (cursor-ref :hand)) (def move-pointer (cursor-ref :move-pointer)) -(def pencil (cursor-ref :pencil 0 0 24)) (def pen (cursor-ref :pen 0 0 0)) -(def pointer-inner (cursor-ref :pointer-inner 0 0 0)) -(def resize-alt (cursor-ref :resize-alt)) -(def resize-nesw (cursor-fn :resize-h 45)) -(def resize-nwse (cursor-fn :resize-h 135)) -(def resize-ew (cursor-fn :resize-h 0)) -(def resize-ns (cursor-fn :resize-h 90)) -(def rotate (cursor-fn :rotate 90)) -(def text (cursor-ref :text)) -(def picker (cursor-ref :picker 0 0 24)) -(def pointer-node (cursor-ref :pointer-node 0 0 10 32)) -(def pointer-move (cursor-ref :pointer-move 0 0 10 42)) (def pen-node (cursor-ref :pen-node 0 0 10 36)) -(def comments (cursor-ref :comments 0 2 20)) +(def pencil (cursor-ref :pencil 0 0 24)) +(def picker (cursor-ref :picker 0 0 24)) +(def pointer-inner (cursor-ref :pointer-inner 0 0 0)) +(def pointer-move (cursor-ref :pointer-move 0 0 10 42)) +(def pointer-node (cursor-ref :pointer-node 0 0 10 32)) +(def resize-alt (cursor-ref :resize-alt)) +(def text (cursor-ref :text)) + +;; Dynamic cursors +(def resize-ew (cursor-fn :resize-h 0)) +(def resize-nesw (cursor-fn :resize-h 45)) +(def resize-ns (cursor-fn :resize-h 90)) +(def resize-nwse (cursor-fn :resize-h 135)) +(def rotate (cursor-fn :rotate 90)) + (mf/defc debug-preview {::mf/wrap-props false} From b0fbc86ca7d9c3f35c1036dbdcb4be8afab847e3 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 20:08:19 +0100 Subject: [PATCH 080/195] :bug: Don't show pointer when no interactions on viewer. --- frontend/src/app/main/ui/viewer/shapes.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 211c50b1fd..f3dcd254ad 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -58,7 +58,7 @@ [:> shape-container {:shape shape :on-mouse-down on-mouse-down - :cursor (when (:interactions shape) "pointer")} + :cursor (when (seq (:interactions shape)) "pointer")} [:& component {:shape shape :frame frame :childs childs From 29669b8b0f550f51a9ddc6ee345428010b687c13 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 25 Nov 2020 20:08:39 +0100 Subject: [PATCH 081/195] :bug: Don't navigate when no frame/index found on viewer. --- common/app/common/data.cljc | 2 +- frontend/src/app/main/data/viewer.cljs | 3 ++- frontend/src/app/main/ui/viewer/shapes.cljs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index 18cfe35dc4..be573163bd 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -87,7 +87,7 @@ (defn index-of-pred [coll pred] - (loop [c (first coll) + (loop [c (first coll) coll (rest coll) index 0] (if (nil? c) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index bdff939da7..cf06925ecc 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -322,7 +322,8 @@ (watch [_ state stream] (let [frames (get-in state [:viewer-data :frames]) index (d/index-of-pred frames #(= (:id %) frame-id))] - (rx/of (go-to-frame-by-index index)))))) + (when index + (rx/of (go-to-frame-by-index index))))))) (defn set-current-frame [frame-id] (ptk/reify ::current-frame diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index f3dcd254ad..9ec1931e2d 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -38,6 +38,7 @@ :navigate (let [frame-id (:destination interaction)] (st/emit! (dv/go-to-frame frame-id))) + nil))) (defn generic-wrapper-factory From 78a8d20e04fee17ad738179c12e4b5d6e3579650 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 26 Nov 2020 09:32:04 +0100 Subject: [PATCH 082/195] :sparkles: Prevent unexpected alt? state persistence on window blur. Caused by using `ctrl+alt` kind of shortcuts that makes keyboard-alt stream registring the key pressed but on bluring the window (unfocus) the key down is never arrived. --- frontend/src/app/main/streams.cljs | 19 +++++++++++++++---- .../src/app/main/ui/workspace/shapes.cljs | 1 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index 597f89223a..54b633d0e9 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -101,13 +101,24 @@ (rx/subscribe-with ob sub) sub)) + +(defonce window-blur + (->> (rx/from-event js/window "blur") + (rx/share))) + (defonce keyboard-alt (let [sub (rx/behavior-subject nil) - ob (->> st/stream - (rx/filter keyboard-event?) - (rx/map :alt) + ob (->> (rx/merge + (->> st/stream + (rx/filter keyboard-event?) + (rx/map :alt)) + ;; Fix a situation caused by using `ctrl+alt` kind of shortcuts, + ;; that makes keyboard-alt stream registring the key pressed but + ;; on bluring the window (unfocus) the key down is never arrived. + (->> window-blur + (rx/map (constantly false)))) (rx/dedupe))] - (rx/subscribe-with ob sub) + (rx/subscribe-with ob sub) sub)) (defn mouse-position-deltas diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 2652591d4a..bb6e9603fb 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -86,7 +86,6 @@ (geom/translate-to-frame frame)) opts #js {:shape shape :frame frame} - alt? (mf/use-state false) on-mouse-enter (use-mouse-enter shape) on-mouse-leave (use-mouse-leave shape) From 1e49ddab8babada862b892f9a8e6e17b380d12ae Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 26 Nov 2020 09:44:46 +0100 Subject: [PATCH 083/195] :fire: Remove unused code. --- frontend/src/app/main/ui/workspace.cljs | 1 - .../src/app/main/ui/workspace/scroll.cljs | 73 ------------------- 2 files changed, 74 deletions(-) delete mode 100644 frontend/src/app/main/ui/workspace/scroll.cljs diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index dfca190994..3995887af4 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -27,7 +27,6 @@ [app.main.ui.workspace.left-toolbar :refer [left-toolbar]] [app.main.ui.workspace.libraries] [app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]] - [app.main.ui.workspace.scroll :as scroll] [app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]] [app.main.ui.workspace.viewport :refer [viewport viewport-actions coordinates]] [app.util.dom :as dom] diff --git a/frontend/src/app/main/ui/workspace/scroll.cljs b/frontend/src/app/main/ui/workspace/scroll.cljs deleted file mode 100644 index 29070de8c7..0000000000 --- a/frontend/src/app/main/ui/workspace/scroll.cljs +++ /dev/null @@ -1,73 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) 2015-2017 Andrey Antukh -;; Copyright (c) 2015-2017 Juan de la Cruz - -(ns app.main.ui.workspace.scroll - "Workspace scroll events handling." - (:require [beicon.core :as rx] - [potok.core :as ptk] - [app.main.refs :as refs] - [app.util.dom :as dom] - [app.common.geom.point :as gpt])) - -;; FIXME: revisit this ns in order to find a better location for its functions -;; TODO: this need a good refactor (probably move to events with access to the state) - -(defn set-scroll-position - [dom position] - (set! (.-scrollLeft dom) (:x position)) - (set! (.-scrollTop dom) (:y position))) - -(defn set-scroll-center - [dom center] - (let [viewport-width (.-offsetWidth dom) - viewport-height (.-offsetHeight dom) - position-x (- (* (:x center) 1 #_@refs/selected-zoom) (/ viewport-width 2)) - position-y (- (* (:y center) 1 #_@refs/selected-zoom) (/ viewport-height 2)) - position (gpt/point position-x position-y)] - (set-scroll-position dom position))) - -(defn scroll-to-page-center - [dom page] - (let [page-width (get-in page [:metadata :width]) - page-height (get-in page [:metadata :height]) - center (gpt/point (+ 1200 (/ page-width 2)) (+ 1200 (/ page-height 2)))] - (set-scroll-center dom center))) - -(defn get-current-center - [dom] - (let [viewport-width (.-offsetWidth dom) - viewport-height (.-offsetHeight dom) - scroll-left (.-scrollLeft dom) - scroll-top (.-scrollTop dom)] - (gpt/point - (+ (/ viewport-width 2) scroll-left) - (+ (/ viewport-height 2) scroll-top)))) - -(defn get-current-center-absolute - [dom] - (gpt/divide (get-current-center dom) (gpt/point @refs/selected-zoom))) - -(defn get-current-position - "Get the coordinates of the currently visible point at top left of viewport" - [dom] - (let [scroll-left (.-scrollLeft dom) - scroll-top (.-scrollTop dom)] - (gpt/point scroll-left scroll-top))) - -(defn get-current-position-absolute - [dom] - (let [current-position (get-current-position dom)] - (gpt/divide (get-current-position dom) (gpt/point @refs/selected-zoom)))) - -(defn scroll-to-point - [dom point position] - (let [viewport-offset (gpt/subtract point position) - selected-zoom (gpt/point @refs/selected-zoom) - new-scroll-position (gpt/subtract - (gpt/multiply point selected-zoom) - (gpt/multiply viewport-offset selected-zoom))] - (set-scroll-position dom new-scroll-position))) From 55d8afd98551bd44d36ddd915e32d7083e39a153 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 26 Nov 2020 09:54:44 +0100 Subject: [PATCH 084/195] :bug: Fix wrong undo handling on masking objects. On undo a mask operation the created group does not disappear; this commit fixes this. --- frontend/src/app/main/data/workspace.cljs | 2 +- .../app/main/ui/workspace/context_menu.cljs | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index fbb8c9e3a7..af45f24169 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1429,7 +1429,7 @@ :page-id page-id :shapes [(:id group)]}]) - uchanges (conj rchanges + uchanges (conj uchanges {:type :mod-obj :page-id page-id :id (:id group) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 5928fc1788..4e98368eeb 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -10,21 +10,21 @@ (ns app.main.ui.workspace.context-menu "A workspace specific context menu (mouse right click)." (:require - [beicon.core :as rx] - [okulary.core :as l] - [potok.core :as ptk] - [rumext.alpha :as mf] - [app.main.store :as st] - [app.main.refs :as refs] - [app.main.streams :as ms] - [app.main.ui.icons :as i] - [app.util.dom :as dom] - [app.util.i18n :refer [t] :as i18n] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.libraries :as dwl] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.streams :as ms] + [app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.hooks :refer [use-rxsub]] - [app.main.ui.components.dropdown :refer [dropdown]])) + [app.main.ui.icons :as i] + [app.util.dom :as dom] + [app.util.i18n :refer [t] :as i18n] + [beicon.core :as rx] + [okulary.core :as l] + [potok.core :as ptk] + [rumext.alpha :as mf])) (def menu-ref (l/derived :context-menu refs/workspace-local)) From cd97735c3fba8de24952a6a0fe2aebc7379e3a8d Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Tue, 24 Nov 2020 16:10:30 +0100 Subject: [PATCH 085/195] :tada: Fix comments visual issues --- .../styles/main/partials/comments.scss | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss index 59e46351d8..e249d52f53 100644 --- a/frontend/resources/styles/main/partials/comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -40,11 +40,11 @@ box-sizing: border-box; box-shadow: 0px 2px 8px rgba($color-black, 0.25); border-radius: 2px; - min-width: 250px; - max-width: 250px; + min-width: 280px; + max-width: 280px; .comments { - max-height: 320px; + max-height: 420px; min-height: 105px; overflow-y: auto; } @@ -52,7 +52,7 @@ hr { border: 0; height: 1px; - background-color: #e3e3e3; + background-color: $color-gray-20; margin: 0px 10px; } } @@ -86,7 +86,7 @@ input { margin: 0px; - font-size: $fs12; + font-size: $fs14; &:not(:last-child) { margin-right: 6px; @@ -102,7 +102,7 @@ .comment { display: flex; flex-direction: column; - padding: 10px; + padding: $medium $small; .author { display: flex; @@ -118,15 +118,15 @@ .fullname { font-weight: 700; color: $color-gray-60; - font-size: $fs10; + font-size: $fs13; @include text-ellipsis; - width: 150px; + width: 174px; } .timeago { margin-top: -2px; - font-size: $fs10; + font-size: $fs12; color: $color-gray-30; } } @@ -139,8 +139,8 @@ img { border-radius: 50%; flex-shrink: 0; - height: 20px; - width: 20px; + height: 24px; + width: 24px; } } @@ -162,8 +162,8 @@ .options { position: absolute; - right: 0px; - top: 0px; + right: -2px; + top: 2px; height: 16px; display: flex; align-items: center; @@ -171,8 +171,8 @@ .options-icon { svg { - width: 10px; - height: 10px; + width: 14px; + height: 14px; fill: $color-black; } } @@ -181,11 +181,11 @@ } .content { - margin: 10px 0; - font-size: $fs10; + margin: $medium 0; + font-size: $fs14; color: $color-black; .text { - margin-left: 26px; + margin: 0 $small 0 26px; white-space: pre-wrap; display: inline-block; } @@ -248,7 +248,7 @@ hr { border: 0; height: 1px; - background-color: #1f1f2f; + background-color: $color-gray-30; margin: 0px 0px; } } @@ -283,8 +283,8 @@ .thread-bubble { position: unset; transform: unset; - width: 20px; - height: 20px; + width: 24px; + height: 24px; margin-right: 6px; box-shadow: unset; } @@ -292,15 +292,13 @@ .comment { cursor: pointer; .author { - margin-bottom: 10px; + margin-bottom: $medium; .name { display: flex; - flex-direction: row; - align-items: center; .fullname { width: unset; - max-width: 100px; + max-width: 170px; color: $color-gray-20; padding-right: 3px; } @@ -316,7 +314,7 @@ color: $color-white; &.replies { - margin-left: 26px; + margin: 0 $small 0 26px; display: flex; .total-replies { margin-right: 9px; @@ -392,7 +390,7 @@ } .dropdown { - width: 233px; + width: 280px; bottom: 35px; left: 0px; border-radius: 3px; @@ -407,7 +405,7 @@ h3 { font-weight: 400; color: $color-black; - font-size: $fs12; + font-size: $fs14; line-height: $fs18; flex-grow: 1; } From 1e30d001894d95cb75992c8da279c08d765b6c8d Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Wed, 25 Nov 2020 10:35:33 +0100 Subject: [PATCH 086/195] :sparkles: Change email rrss accounts --- backend/resources/emails-mjml/change-email/en.mjml | 8 ++++---- backend/resources/emails-mjml/invite-to-team/en.mjml | 8 ++++---- backend/resources/emails-mjml/password-recovery/en.mjml | 8 ++++---- backend/resources/emails-mjml/register/en.mjml | 8 ++++---- backend/resources/emails/change-email/en.html | 4 ++-- backend/resources/emails/invite-to-team/en.html | 4 ++-- backend/resources/emails/password-recovery/en.html | 4 ++-- backend/resources/emails/register/en.html | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/backend/resources/emails-mjml/change-email/en.mjml b/backend/resources/emails-mjml/change-email/en.mjml index fc9a7f438c..ae388201aa 100644 --- a/backend/resources/emails-mjml/change-email/en.mjml +++ b/backend/resources/emails-mjml/change-email/en.mjml @@ -45,10 +45,10 @@ - - - - + + + + diff --git a/backend/resources/emails-mjml/invite-to-team/en.mjml b/backend/resources/emails-mjml/invite-to-team/en.mjml index dbef7afe5f..48af2706af 100644 --- a/backend/resources/emails-mjml/invite-to-team/en.mjml +++ b/backend/resources/emails-mjml/invite-to-team/en.mjml @@ -38,10 +38,10 @@ - - - - + + + + diff --git a/backend/resources/emails-mjml/password-recovery/en.mjml b/backend/resources/emails-mjml/password-recovery/en.mjml index fe2fa20487..36f323dc10 100644 --- a/backend/resources/emails-mjml/password-recovery/en.mjml +++ b/backend/resources/emails-mjml/password-recovery/en.mjml @@ -47,10 +47,10 @@ - - - - + + + + diff --git a/backend/resources/emails-mjml/register/en.mjml b/backend/resources/emails-mjml/register/en.mjml index 28d1249e69..d3a12f2562 100644 --- a/backend/resources/emails-mjml/register/en.mjml +++ b/backend/resources/emails-mjml/register/en.mjml @@ -44,10 +44,10 @@ - - - - + + + + diff --git a/backend/resources/emails/change-email/en.html b/backend/resources/emails/change-email/en.html index 7aa3fd6136..547e73e9ba 100644 --- a/backend/resources/emails/change-email/en.html +++ b/backend/resources/emails/change-email/en.html @@ -330,7 +330,7 @@ @@ -370,7 +370,7 @@
- +
diff --git a/backend/resources/emails/invite-to-team/en.html b/backend/resources/emails/invite-to-team/en.html index 0f85d5a463..d9754903d3 100644 --- a/backend/resources/emails/invite-to-team/en.html +++ b/backend/resources/emails/invite-to-team/en.html @@ -320,7 +320,7 @@
- +
@@ -360,7 +360,7 @@
- +
diff --git a/backend/resources/emails/password-recovery/en.html b/backend/resources/emails/password-recovery/en.html index 2262325079..4ae4036b07 100644 --- a/backend/resources/emails/password-recovery/en.html +++ b/backend/resources/emails/password-recovery/en.html @@ -325,7 +325,7 @@
- +
@@ -365,7 +365,7 @@
- +
diff --git a/backend/resources/emails/register/en.html b/backend/resources/emails/register/en.html index dd2f7a69fe..6b8c5cc83a 100644 --- a/backend/resources/emails/register/en.html +++ b/backend/resources/emails/register/en.html @@ -320,7 +320,7 @@
- +
@@ -360,7 +360,7 @@
- +
From 62c727e2534b084f480159ca4790a17455594326 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Wed, 25 Nov 2020 10:47:37 +0100 Subject: [PATCH 087/195] :sparkles: Add new comments placeholder --- frontend/resources/locales.json | 2 +- .../resources/styles/main/partials/comments.scss | 14 +++++++++++++- frontend/src/app/main/ui/dashboard/comments.cljs | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 1954e34091..7cdd3bdaa7 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -1426,7 +1426,7 @@ "labels.no-comments-available" : { "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:104" ], "translations" : { - "en" : "No comments" + "en" : "You have no pending comment notifications" } }, "labels.old-password" : { diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss index e249d52f53..8c903dfad1 100644 --- a/frontend/resources/styles/main/partials/comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -424,7 +424,19 @@ } .thread-groups-placeholder { - padding: 16px; + align-items: center; + display: flex; + flex-direction: column; + font-size: $fs14; + padding: $big; + text-align: center; + + svg { + fill: $color-gray-20; + height: 24px; + margin-bottom: $small; + width: 24px; + } } .thread-group { diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index 81aeb1c1c5..dfc404556b 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -92,4 +92,5 @@ :key (:page-id tgroup)}]])] [:div.thread-groups-placeholder + i/chat (tr "labels.no-comments-available")])]]])) From 56861e8d01de2c0251d3ca63af0dfc70c822b02e Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Wed, 25 Nov 2020 14:53:58 +0100 Subject: [PATCH 088/195] :tada: Create placeholder at comments sidebar --- .../styles/main/partials/comments.scss | 34 +++++++++---------- .../src/app/main/ui/workspace/comments.cljs | 8 +++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/frontend/resources/styles/main/partials/comments.scss b/frontend/resources/styles/main/partials/comments.scss index 8c903dfad1..161c109bbc 100644 --- a/frontend/resources/styles/main/partials/comments.scss +++ b/frontend/resources/styles/main/partials/comments.scss @@ -423,28 +423,12 @@ } } - .thread-groups-placeholder { - align-items: center; - display: flex; - flex-direction: column; - font-size: $fs14; - padding: $big; - text-align: center; - - svg { - fill: $color-gray-20; - height: 24px; - margin-bottom: $small; - width: 24px; - } - } - .thread-group { .section-title { color: $color-black; } } - + .comment { .author .name .fullname { color: $color-gray-40; @@ -455,3 +439,19 @@ } } +.thread-groups-placeholder { + align-items: center; + display: flex; + flex-direction: column; + font-size: $fs12; + padding: $big; + text-align: center; + + svg { + fill: $color-gray-20; + height: 24px; + margin-bottom: $big; + width: 24px; + } +} + diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index f7cc52b524..8475ab4d26 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -166,7 +166,7 @@ :on-close #(reset! options? false)} [:& sidebar-options {:local local}]]] - (when (seq tgroups) + (if (seq tgroups) [:div.thread-groups [:& cmt/comment-thread-group {:group (first tgroups) @@ -179,6 +179,10 @@ {:group tgroup :on-thread-click on-thread-click :users users - :key (:page-id tgroup)}]])])])) + :key (:page-id tgroup)}]])] + + [:div.thread-groups-placeholder + i/chat + (tr "labels.no-comments-available")])])) From 40240d294ac0955a74856b036b03f47a961e7ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 25 Nov 2020 15:22:19 +0100 Subject: [PATCH 089/195] :bug: Fix synchronization of geometry changes --- common/app/common/pages.cljc | 29 +++++--- .../data/workspace/libraries_helpers.cljs | 68 ++++++++----------- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index eda4584d1d..8e2c58bb20 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -294,8 +294,6 @@ :internal.shape/proportion-lock :internal.shape/rx :internal.shape/ry - :internal.shape/cx - :internal.shape/cy :internal.shape/x :internal.shape/y :internal.shape/exports @@ -319,7 +317,7 @@ :fill-color-ref-file :fill-group :fill-color-ref-id :fill-group :fill-opacity :fill-group - :content :text-content-group + :content :content-group :font-family :text-font-group :font-size :text-font-group :font-style :text-font-group @@ -334,11 +332,19 @@ :stroke-style :stroke-group :stroke-width :stroke-group :stroke-alignment :stroke-group - :width :size-group - :height :size-group - :proportion :size-group - :rx :radius-group - :ry :radius-group + :selrect :geometry-group + :points :geometry-group + :locked :geometry-group + :proportion :geometry-group + :proportion-lock :geometry-group + :rx :geometry-group + :ry :geometry-group + :x :geometry-group + :y :geometry-group + :width :geometry-group + :height :geometry-group + :transform :geometry-group + :transform-inverse :geometry-group :masked-group? :mask-group}) ;; shapes-group is handled differently @@ -1074,7 +1080,12 @@ group (get component-sync-attrs attr)] (cond-> shape - (and shape-ref group (not ignore) (not= val (get shape attr))) + (and shape-ref group (not ignore) (not= val (get shape attr)) + ;; FIXME: it's difficult to tell if the geometry changes affect + ;; an individual shape inside the component, or are for + ;; the whole component (in which case we shouldn't set + ;; touched). For the moment we disable geometry touched. + (not= group :geometry-group)) (update :touched cph/set-touched-group group) (nil? val) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index bd6608a3b5..0d539806e9 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -14,6 +14,7 @@ [app.common.data :as d] [app.common.pages-helpers :as cph] [app.common.geom.point :as gpt] + [app.common.geom.shapes :as geom] [app.common.pages :as cp] [app.util.logging :as log] [app.util.text :as ut])) @@ -50,7 +51,7 @@ (declare move-shape) (declare change-touched) (declare update-attrs) -(declare calc-new-pos) +(declare reposition-shape) ;; ---- Create a new component ---- @@ -658,16 +659,13 @@ (cph/get-parents parent-shape (:objects container)))) update-new-shape (fn [new-shape original-shape] - (let [new-pos (calc-new-pos new-shape - original-shape - root-instance - root-master)] + (let [new-shape (reposition-shape new-shape + root-master + root-instance)] (cond-> new-shape true (assoc :shape-ref (:id original-shape) - :frame-id (:frame-id parent-shape) - :x (:x new-pos) - :y (:y new-pos)) + :frame-id (:frame-id parent-shape)) (:component-id original-shape) (assoc :component-id (:component-id original-shape)) @@ -736,13 +734,9 @@ (cph/get-parents component-parent-shape (:objects component)))) update-new-shape (fn [new-shape original-shape] - (let [new-pos (calc-new-pos new-shape - original-shape - root-master - root-instance)] - (assoc new-shape - :x (:x new-pos) - :y (:y new-pos)))) + (reposition-shape new-shape + root-instance + root-master)) update-original-shape (fn [original-shape new-shape] (if-not (:shape-ref original-shape) @@ -966,23 +960,17 @@ (if (cph/page? container) "[P] " "[C] ") (:name dest-shape))) - (let [; The position attributes need a special sync algorith, because we do - ; not synchronize the absolute position, but the position relative of - ; the container shape of the component. - new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root) - touched (get dest-shape :touched #{})] + (let [; To synchronize geometry attributes we need to make a prior + ; operation, because coordinates are absolute, but we need to + ; sync only the position relative to the origin of the component. + ; We solve this by moving the origin shape so it is aligned with + ; the dest root before syncing. + origin-shape (reposition-shape origin-shape origin-root dest-root) + touched (get dest-shape :touched #{})] - (loop [attrs (seq (keys (dissoc cp/component-sync-attrs :x :y))) - roperations (if (or (not= (:x new-pos) (:x dest-shape)) - (not= (:y new-pos) (:y dest-shape))) - [{:type :set :attr :x :val (:x new-pos)} - {:type :set :attr :y :val (:y new-pos)}] - []) - uoperations (if (or (not= (:x new-pos) (:x dest-shape)) - (not= (:y new-pos) (:y dest-shape))) - [{:type :set :attr :x :val (:x dest-shape)} - {:type :set :attr :y :val (:y dest-shape)}] - [])] + (loop [attrs (seq (keys cp/component-sync-attrs)) + roperations [] + uoperations []] (let [attr (first attrs)] (if (nil? attr) @@ -1042,13 +1030,13 @@ (conj roperations roperation) (conj uoperations uoperation)))))))))) -(defn- calc-new-pos - [dest-shape origin-shape dest-root origin-root] - (let [root-pos (gpt/point (:x dest-root) (:y dest-root)) - origin-root-pos (gpt/point (:x origin-root) (:y origin-root)) - origin-pos (gpt/point (:x origin-shape) (:y origin-shape)) - delta (gpt/subtract origin-pos origin-root-pos) - shape-pos (gpt/point (:x dest-shape) (:y dest-shape)) - new-pos (gpt/add root-pos delta)] - new-pos)) +(defn- reposition-shape + [shape origin-root dest-root] + (let [shape-pos (fn [shape] + (gpt/point (get-in shape [:selrect :x]) + (get-in shape [:selrect :y]))) + origin-root-pos (shape-pos origin-root) + dest-root-pos (shape-pos dest-root) + delta (gpt/subtract dest-root-pos origin-root-pos)] + (geom/move shape delta))) From 4c1150bf785c5aa974f656cf8c0cc22d6d6f662f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 26 Nov 2020 15:09:01 +0100 Subject: [PATCH 090/195] :sparkles: Switch team clicking in the whole selector --- .../resources/styles/main/partials/dashboard-sidebar.scss | 2 +- frontend/src/app/main/ui/dashboard/sidebar.cljs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/resources/styles/main/partials/dashboard-sidebar.scss b/frontend/resources/styles/main/partials/dashboard-sidebar.scss index 658411737d..1b649be296 100644 --- a/frontend/resources/styles/main/partials/dashboard-sidebar.scss +++ b/frontend/resources/styles/main/partials/dashboard-sidebar.scss @@ -77,6 +77,7 @@ } .current-team { + cursor: pointer; display: flex; flex-grow: 1; font-size: $fs14; @@ -118,7 +119,6 @@ .switch-icon { display: flex; align-items: center; - cursor: pointer; svg { width: 10px; diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 73554a5146..193c72b3b8 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -322,7 +322,7 @@ [:div.sidebar-team-switch [:div.switch-content - [:div.current-team + [:div.current-team {:on-click #(reset! show-teams-ddwn? true)} (if (:is-default team) [:div.team-name [:span.team-icon i/logo-icon] @@ -332,7 +332,7 @@ [:img {:src (cfg/resolve-media-path (:photo team))}]] [:span.team-text {:title (:name team)} (:name team)]]) - [:span.switch-icon {:on-click #(reset! show-teams-ddwn? true)} + [:span.switch-icon i/arrow-down]] (when-not (:is-default team) From ddf0e75a113dc932122033f1e3730268d1237f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 26 Nov 2020 14:55:55 +0100 Subject: [PATCH 091/195] :sparkles: Open artboard at the sidebar when dropping shapes into it --- .../src/app/main/data/workspace/common.cljs | 23 +++++++++++++++++++ .../app/main/data/workspace/transforms.cljs | 3 ++- .../app/main/ui/workspace/sidebar/layers.cljs | 7 +++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 594c00f03e..78e69567dc 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -188,6 +188,29 @@ (recur (inc counter)) candidate))))) +;; --- Shape attrs (Layers Sidebar) + +(defn toggle-collapse + [id] + (ptk/reify ::toggle-collapse + ptk/UpdateEvent + (update [_ state] + (update-in state [:workspace-local :expanded id] not)))) + +(defn expand-collapse + [id] + (ptk/reify ::expand-collapse + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:workspace-local :expanded id] true)))) + +(def collapse-all + (ptk/reify ::collapse-all + ptk/UpdateEvent + (update [_ state] + (update state :workspace-local dissoc :expanded)))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Undo / Redo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 6c203d6432..c74221e316 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -266,7 +266,8 @@ (when-not (empty? rch) (rx/of dwc/pop-undo-into-transaction (dwc/commit-changes rch uch {:commit-local? true}) - dwc/commit-undo-transaction)))))) + dwc/commit-undo-transaction + (dwc/expand-collapse frame-id))))))) (defn start-move ([from-position] (start-move from-position nil)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 9bf8287152..bd9e012af9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -14,6 +14,7 @@ [app.common.pages-helpers :as cph] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] + [app.main.data.workspace.common :as dwc] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.hooks :as hooks] @@ -112,8 +113,8 @@ (fn [event] (dom/stop-propagation event) (if (and expanded? (kbd/shift? event)) - (st/emit! dw/collapse-all) - (st/emit! (dw/toggle-collapse id)))) + (st/emit! dwc/collapse-all) + (st/emit! (dwc/toggle-collapse id)))) toggle-blocking (fn [event] @@ -173,7 +174,7 @@ on-hold (fn [] (when-not expanded? - (st/emit! (dw/toggle-collapse (:id item))))) + (st/emit! (dwc/toggle-collapse (:id item))))) [dprops dref] (hooks/use-sortable :data-type "app/layer" From 1f92237b199833d841f035c5b6482f4447e2b895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 27 Nov 2020 07:55:54 +0100 Subject: [PATCH 092/195] :fire: Remove some unused code --- frontend/src/app/main/data/workspace.cljs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index af45f24169..5c49f56094 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1053,21 +1053,6 @@ (rx/of (dwt/set-modifiers [id] {:displacement displ}) (dwt/apply-modifiers [id])))))) -;; --- Shape attrs (Layers Sidebar) - -(defn toggle-collapse - [id] - (ptk/reify ::toggle-collapse - ptk/UpdateEvent - (update [_ state] - (update-in state [:workspace-local :expanded id] not)))) - -(def collapse-all - (ptk/reify ::collapse-all - ptk/UpdateEvent - (update [_ state] - (update state :workspace-local dissoc :expanded)))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Navigation From b67b3243bbe3d76e8c4802ede66c3df3944dc310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 27 Nov 2020 07:49:39 +0100 Subject: [PATCH 093/195] :sparkles: Open library by cliking in the whole selector --- .../styles/main/partials/sidebar-assets.scss | 5 ++++- .../src/app/main/ui/workspace/sidebar/assets.cljs | 11 +++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-assets.scss b/frontend/resources/styles/main/partials/sidebar-assets.scss index f19b1a2976..b2915448ee 100644 --- a/frontend/resources/styles/main/partials/sidebar-assets.scss +++ b/frontend/resources/styles/main/partials/sidebar-assets.scss @@ -108,13 +108,16 @@ .collapse-library { margin-right: $small; - cursor: pointer; &.open svg { transform: rotate(90deg); } } + .library-bar { + cursor: pointer; + } + .asset-group { background-color: $color-gray-60; border-top: 1px solid $color-gray-50; diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 4d9f56b846..4094eeee12 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -557,10 +557,10 @@ components (apply-filters (mf/deref components-ref) filters)] [:div.tool-window - [:div.tool-window-bar + [:div.tool-window-bar.library-bar + {:on-click toggle-open} [:div.collapse-library - {:class (dom/classnames :open @open?) - :on-click toggle-open} + {:class (dom/classnames :open @open?)} i/arrow-slide] (if local? @@ -571,7 +571,10 @@ [:* [:span (:name file)] [:span.tool-link.tooltip.tooltip-left {:alt "Open library file"} - [:a {:href (str "#" url) :target "_blank"} i/chain]]])] + [:a {:href (str "#" url) + :target "_blank" + :on-click dom/stop-propagation} + i/chain]]])] (when @open? (let [show-components? (and (or (= (:box filters) :all) From 2a17f0e5070e69ac8e9991c95a3cb75d779248c7 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 27 Nov 2020 07:30:12 +0100 Subject: [PATCH 094/195] :recycle: Refactor the text size calculations --- frontend/deps.edn | 2 +- frontend/src/app/main/data/workspace.cljs | 2 +- .../src/app/main/data/workspace/common.cljs | 52 +- frontend/src/app/main/fonts.cljs | 5 + frontend/src/app/main/ui/shapes/text.cljs | 233 ++------ .../src/app/main/ui/shapes/text/embed.cljs | 75 +++ .../src/app/main/ui/shapes/text/styles.cljs | 119 ++++ .../src/app/main/ui/workspace/drawarea.cljs | 2 +- .../src/app/main/ui/workspace/effects.cljs | 78 +++ .../src/app/main/ui/workspace/selection.cljs | 2 +- .../src/app/main/ui/workspace/shapes.cljs | 24 +- .../app/main/ui/workspace/shapes/common.cljs | 70 +-- .../app/main/ui/workspace/shapes/frame.cljs | 99 ++-- .../app/main/ui/workspace/shapes/group.cljs | 54 +- .../app/main/ui/workspace/shapes/path.cljs | 330 +---------- .../ui/workspace/shapes/path/actions.cljs | 47 ++ .../main/ui/workspace/shapes/path/common.cljs | 39 ++ .../main/ui/workspace/shapes/path/editor.cljs | 235 ++++++++ .../app/main/ui/workspace/shapes/text.cljs | 515 ++++-------------- .../main/ui/workspace/shapes/text/editor.cljs | 256 +++++++++ .../src/app/main/ui/workspace/viewport.cljs | 2 +- 21 files changed, 1128 insertions(+), 1113 deletions(-) create mode 100644 frontend/src/app/main/ui/shapes/text/embed.cljs create mode 100644 frontend/src/app/main/ui/shapes/text/styles.cljs create mode 100644 frontend/src/app/main/ui/workspace/effects.cljs create mode 100644 frontend/src/app/main/ui/workspace/shapes/path/actions.cljs create mode 100644 frontend/src/app/main/ui/workspace/shapes/path/common.cljs create mode 100644 frontend/src/app/main/ui/workspace/shapes/path/editor.cljs create mode 100644 frontend/src/app/main/ui/workspace/shapes/text/editor.cljs diff --git a/frontend/deps.edn b/frontend/deps.edn index 072351097e..2e79e6972f 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -16,7 +16,7 @@ funcool/okulary {:mvn/version "2020.04.14-0"} funcool/potok {:mvn/version "2020.08.10-2"} funcool/promesa {:mvn/version "6.0.0"} - funcool/rumext {:mvn/version "2020.10.14-1"} + funcool/rumext {:mvn/version "2020.11.27-0"} lambdaisland/uri {:mvn/version "1.4.54" :exclusions [org.clojure/data.json]} diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 5c49f56094..3cc6bb702f 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1014,7 +1014,7 @@ (ptk/reify ::update-dimensions ptk/WatchEvent (watch [_ state stream] - (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value)))))) + (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) ;; --- Shape Proportions diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 78e69567dc..69a50ad6a4 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -382,33 +382,33 @@ (ptk/reify ::update-shapes ptk/WatchEvent (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (lookup-page-objects state page-id)] - (loop [ids (seq ids) - rch [] - uch []] - (if (nil? ids) - (rx/of (commit-changes - (cond-> rch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)})) - (cond-> uch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)})) - {:commit-local? true})) + (let [page-id (:current-page-id state) + objects (lookup-page-objects state page-id)] + (loop [ids (seq ids) + rch [] + uch []] + (if (nil? ids) + (rx/of (commit-changes + (cond-> rch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)})) + (cond-> uch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)})) + {:commit-local? true})) - (let [id (first ids) - obj1 (get objects id) - obj2 (f obj1) - rch-operations (generate-operations obj1 obj2) - uch-operations (generate-operations obj2 obj1 true) - rchg {:type :mod-obj - :page-id page-id - :operations rch-operations - :id id} - uchg {:type :mod-obj - :page-id page-id - :operations uch-operations - :id id}] - (recur (next ids) - (if (empty? rch-operations) rch (conj rch rchg)) - (if (empty? uch-operations) uch (conj uch uchg))))))))))) + (let [id (first ids) + obj1 (get objects id) + obj2 (f obj1) + rch-operations (generate-operations obj1 obj2) + uch-operations (generate-operations obj2 obj1 true) + rchg {:type :mod-obj + :page-id page-id + :operations rch-operations + :id id} + uchg {:type :mod-obj + :page-id page-id + :operations uch-operations + :id id}] + (recur (next ids) + (if (empty? rch-operations) rch (conj rch rchg)) + (if (empty? uch-operations) uch (conj uch uchg))))))))))) (defn update-shapes-recursive diff --git a/frontend/src/app/main/fonts.cljs b/frontend/src/app/main/fonts.cljs index a20d94d6e1..61e7045377 100644 --- a/frontend/src/app/main/fonts.cljs +++ b/frontend/src/app/main/fonts.cljs @@ -170,3 +170,8 @@ (or (d/seek #(or (= (:id %) "regular") (= (:name %) "regular")) variants) (first variants))) + +(defn fetch-font [font-id font-variant-id] + (let [font-url (font-url font-id font-variant-id)] + (-> (js/fetch font-url) + (p/then (fn [res] (.text res)))))) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 4a4513e019..2d36fe781c 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -9,201 +9,56 @@ (ns app.main.ui.shapes.text (:require - [app.common.data :as d] - [app.common.geom.matrix :as gmt] - [app.common.geom.shapes :as geom] - [app.main.data.fetch :as df] - [app.main.fonts :as fonts] + [cuerdas.core :as str] + [rumext.alpha :as mf] [app.main.ui.context :as muc] [app.main.ui.shapes.group :refer [mask-id-ctx]] - [app.util.color :as uc] + [app.common.data :as d] + [app.common.geom.shapes :as geom] + [app.common.geom.matrix :as gmt] [app.util.object :as obj] - [app.util.text :as ut] - [clojure.set :as set] - [cuerdas.core :as str] - [promesa.core :as p] - [rumext.alpha :as mf])) - -;; --- Text Editor Rendering - -(defn- generate-root-styles - [data] - (let [valign (obj/get data "vertical-align" "top") - talign (obj/get data "text-align" "flex-start") - base #js {:height "100%" - :width "100%" - :display "flex"}] - (cond-> base - (= valign "top") (obj/set! "alignItems" "flex-start") - (= valign "center") (obj/set! "alignItems" "center") - (= valign "bottom") (obj/set! "alignItems" "flex-end") - (= talign "left") (obj/set! "justifyContent" "flex-start") - (= talign "center") (obj/set! "justifyContent" "center") - (= talign "right") (obj/set! "justifyContent" "flex-end") - (= talign "justify") (obj/set! "justifyContent" "stretch")))) - -(defn- generate-paragraph-styles - [data] - (let [base #js {:fontSize "14px" - :margin "inherit" - :lineHeight "1.2"} - lh (obj/get data "line-height") - ta (obj/get data "text-align")] - (cond-> base - ta (obj/set! "textAlign" ta) - lh (obj/set! "lineHeight" lh)))) - -(defn- generate-text-styles - [data] - (let [letter-spacing (obj/get data "letter-spacing") - text-decoration (obj/get data "text-decoration") - text-transform (obj/get data "text-transform") - line-height (obj/get data "line-height") - - font-id (obj/get data "font-id" (:font-id ut/default-text-attrs)) - font-variant-id (obj/get data "font-variant-id") - - font-family (obj/get data "font-family") - font-size (obj/get data "font-size") - - ;; Old properties for backwards compatibility - fill (obj/get data "fill") - opacity (obj/get data "opacity" 1) - - fill-color (obj/get data "fill-color" fill) - fill-opacity (obj/get data "fill-opacity" opacity) - fill-color-gradient (obj/get data "fill-color-gradient" nil) - fill-color-gradient (when fill-color-gradient - (-> (js->clj fill-color-gradient :keywordize-keys true) - (update :type keyword))) - - fill-color-ref-id (obj/get data "fill-color-ref-id") - fill-color-ref-file (obj/get data "fill-color-ref-file") - - [r g b a] (uc/hex->rgba fill-color fill-opacity) - background (if fill-color-gradient - (uc/gradient->css (js->clj fill-color-gradient)) - (str/format "rgba(%s, %s, %s, %s)" r g b a)) - - fontsdb (deref fonts/fontsdb) - - base #js {:textDecoration text-decoration - :textTransform text-transform - :lineHeight (or line-height "inherit") - "--text-color" background}] - - (when (and (string? letter-spacing) - (pos? (alength letter-spacing))) - (obj/set! base "letterSpacing" (str letter-spacing "px"))) - - (when (and (string? font-size) - (pos? (alength font-size))) - (obj/set! base "fontSize" (str font-size "px"))) - - (when (and (string? font-id) - (pos? (alength font-id))) - (let [font (get fontsdb font-id)] - (fonts/ensure-loaded! font-id) - (let [font-family (or (:family font) - (obj/get data "fontFamily")) - font-variant (d/seek #(= font-variant-id (:id %)) - (:variants font)) - font-style (or (:style font-variant) - (obj/get data "fontStyle")) - font-weight (or (:weight font-variant) - (obj/get data "fontWeight"))] - (obj/set! base "fontFamily" font-family) - (obj/set! base "fontStyle" font-style) - (obj/set! base "fontWeight" font-weight)))) - - base)) - -(defn get-all-fonts [node] - (let [current-font (if (not (nil? (:font-id node))) - #{(select-keys node [:font-id :font-variant-id])} - #{}) - children-font (map get-all-fonts (:children node))] - (reduce set/union (conj children-font current-font)))) - - -(defn fetch-font [font-id font-variant-id] - (let [font-url (fonts/font-url font-id font-variant-id)] - (-> (js/fetch font-url) - (p/then (fn [res] (.text res)))))) - -(defonce font-face-template " -/* latin */ -@font-face { - font-family: '$0'; - font-style: $3; - font-weight: $2; - font-display: block; - src: url(/fonts/%(0)s-$1.woff) format('woff'); -} -") - -(defn get-local-font-css [font-id font-variant-id] - (let [{:keys [family variants]} (get @fonts/fontsdb font-id) - {:keys [name weight style]} (->> variants (filter #(= (:id %) font-variant-id)) first) - css-str (str/format font-face-template [family name weight style])] - (p/resolved css-str))) - -(defn embed-font [{:keys [font-id font-variant-id] :or {font-variant-id "regular"}}] - (let [{:keys [backend]} (get @fonts/fontsdb font-id)] - (p/let [font-text (case backend - :google (fetch-font font-id font-variant-id) - (get-local-font-css font-id font-variant-id)) - url-to-data (->> font-text - (re-seq #"url\(([^)]+)\)") - (map second) - (map df/fetch-as-data-uri) - (p/all))] - (reduce (fn [text [url data]] (str/replace text url data)) font-text url-to-data)) - )) + [app.util.color :as uc] + [app.main.ui.shapes.text.styles :as sts] + [app.main.ui.shapes.text.embed :as ste])) +;; -- Text nodes (mf/defc text-node - [{:keys [node index] :as props}] + [{:keys [node index shape] :as props}] (let [embed-resources? (mf/use-ctx muc/embed-ctx) - embeded-fonts (mf/use-state nil) - {:keys [type text children]} node] + {:keys [type text children]} node - (mf/use-effect - (mf/deps node) - (fn [] - (when (and embed-resources? (= type "root")) - (let [font-to-embed (get-all-fonts node) - font-to-embed (if (empty? font-to-embed) #{ut/default-text-attrs} font-to-embed) - embeded (map embed-font font-to-embed)] - (-> (p/all embeded) - (p/then (fn [result] (reset! embeded-fonts (str/join "\n" result))))))))) + render-node + (fn [index node] + (mf/element text-node {:index index + :node node + :key index + :shape shape}))] (if (string? text) - (let [style (generate-text-styles (clj->js node))] + (let [style (sts/generate-text-styles (clj->js node))] [:span.text-node {:style style} (if (= text "") "\u00A0" text)]) - (let [children (map-indexed (fn [index node] - (mf/element text-node {:index index :node node :key index})) - children)] + + (let [children (map-indexed render-node children)] (case type "root" - (let [style (generate-root-styles (clj->js node))] - + (let [style (sts/generate-root-styles (clj->js node) #js {:shape shape})] [:div.root.rich-text {:key index :style style :xmlns "http://www.w3.org/1999/xhtml"} [:* [:style ".text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] - (when (not (nil? @embeded-fonts)) - [:style @embeded-fonts])] + (when embed-resources? + [ste/embed-fontfaces-style {:node node}])] children]) "paragraph-set" - (let [style #js {:display "inline-block"}] - [:div.paragraphs {:key index :style style} children]) + (let [style (sts/generate-paragraph-set-styles (clj->js node))] + [:div.paragraph-set {:key index :style style} children]) "paragraph" - (let [style (generate-paragraph-styles (clj->js node))] - [:p {:key index :style style} children]) + (let [style (sts/generate-paragraph-styles (clj->js node))] + [:p.paragraph {:key index :style style} children]) nil))))) @@ -211,31 +66,37 @@ {::mf/wrap-props false ::mf/wrap [mf/memo]} [props] - (let [root (obj/get props "content")] - [:& text-node {:index 0 :node root}])) + (let [root (obj/get props "content") + shape (obj/get props "shape")] + [:& text-node {:index 0 + :node root + :shape shape}])) (defn- retrieve-colors [shape] - (let [colors (into #{} (comp (map :fill) - (filter string?)) - (tree-seq map? :children (:content shape)))] + (let [colors (->> shape :content + (tree-seq map? :children) + (into #{} (comp (map :fill) (filter string?))))] (if (empty? colors) "#000000" (apply str (interpose "," colors))))) (mf/defc text-shape - {::mf/wrap-props false} - [props] + {::mf/wrap-props false + ::mf/forward-ref true} + [props ref] (let [shape (unchecked-get props "shape") selected? (unchecked-get props "selected?") - mask-id (mf/use-ctx mask-id-ctx) - {:keys [id x y width height rotation content]} shape] + grow-type (:grow-type shape) + mask-id (mf/use-ctx mask-id-ctx) + {:keys [id x y width height content]} shape] [:foreignObject {:x x :y y :data-colors (retrieve-colors shape) :transform (geom/transform-matrix shape) - :width width - :height height - :mask mask-id} - [:& text-content {:content (:content shape)}]])) - + :width (if (#{:auto-width} grow-type) 10000 width) + :height (if (#{:auto-height :auto-width} grow-type) 10000 height) + :mask mask-id + :ref ref} + [:& text-content {:shape shape + :content (:content shape)}]])) diff --git a/frontend/src/app/main/ui/shapes/text/embed.cljs b/frontend/src/app/main/ui/shapes/text/embed.cljs new file mode 100644 index 0000000000..9d41810f03 --- /dev/null +++ b/frontend/src/app/main/ui/shapes/text/embed.cljs @@ -0,0 +1,75 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.shapes.text.embed + (:require + [clojure.set :as set] + [promesa.core :as p] + [cuerdas.core :as str] + [rumext.alpha :as mf] + [app.main.data.fetch :as df] + [app.main.fonts :as fonts] + [app.util.text :as ut])) + +(defonce font-face-template " +/* latin */ +@font-face { + font-family: '$0'; + font-style: $3; + font-weight: $2; + font-display: block; + src: url(/fonts/%(0)s-$1.woff) format('woff'); +} +") + +;; -- Embed fonts into styles +(defn get-node-fonts [node] + (let [current-font (if (not (nil? (:font-id node))) + #{(select-keys node [:font-id :font-variant-id])} + #{}) + children-font (map get-node-fonts (:children node))] + (reduce set/union (conj children-font current-font)))) + + +(defn get-local-font-css [font-id font-variant-id] + (let [{:keys [family variants]} (get @fonts/fontsdb font-id) + {:keys [name weight style]} (->> variants (filter #(= (:id %) font-variant-id)) first) + css-str (str/format font-face-template [family name weight style])] + (p/resolved css-str))) + +(defn get-text-font-data [text] + (->> text + (re-seq #"url\(([^)]+)\)") + (map second) + (map df/fetch-as-data-uri) + (p/all))) + +(defn embed-font [{:keys [font-id font-variant-id] :or {font-variant-id "regular"}}] + (let [{:keys [backend]} (get @fonts/fontsdb font-id)] + (p/let [font-text (case backend + :google (fonts/fetch-font font-id font-variant-id) + (get-local-font-css font-id font-variant-id)) + url-to-data (get-text-font-data font-text) + replace-text (fn [text [url data]] (str/replace text url data))] + (reduce replace-text font-text url-to-data)))) + +(mf/defc embed-fontfaces-style [{:keys [node]}] + (let [embeded-fonts (mf/use-state nil)] + (mf/use-effect + (mf/deps node) + (fn [] + (let [font-to-embed (get-node-fonts node) + font-to-embed (if (empty? font-to-embed) #{ut/default-text-attrs} font-to-embed) + embeded (map embed-font font-to-embed)] + (-> (p/all embeded) + (p/then (fn [result] (reset! embeded-fonts (str/join "\n" result)))))))) + + + (when (not (nil? @embeded-fonts)) + [:style @embeded-fonts]))) diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs new file mode 100644 index 0000000000..1dfaef189a --- /dev/null +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -0,0 +1,119 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.shapes.text.styles + (:require + [cuerdas.core :as str] + [app.main.fonts :as fonts] + [app.common.data :as d] + [app.util.object :as obj] + [app.util.color :as uc] + [app.util.text :as ut])) + +(defn generate-root-styles + [data props] + (let [valign (obj/get data "vertical-align" "top") + talign (obj/get data "text-align" "flex-start") + shape (obj/get props "shape") + base #js {:height (or (:height shape) "100%") + :width (or (:width shape) "100%") + :display "flex"}] + (cond-> base + (= valign "top") (obj/set! "alignItems" "flex-start") + (= valign "center") (obj/set! "alignItems" "center") + (= valign "bottom") (obj/set! "alignItems" "flex-end") + + (= talign "left") (obj/set! "justifyContent" "flex-start") + (= talign "center") (obj/set! "justifyContent" "center") + (= talign "right") (obj/set! "justifyContent" "flex-end") + (= talign "justify") (obj/set! "justifyContent" "stretch")))) + +(defn generate-paragraph-set-styles + [data] + ;; The position absolute is used so the paragraph is "outside" + ;; the normal layout and can grow outside its parent + ;; We use this element to measure the size of the text + (let [base #js {:display "inline-block" + :position "absolute"}] + base)) + +(defn generate-paragraph-styles + [data] + (let [base #js {:fontSize "14px" + :margin "inherit" + :lineHeight "1.2"} + lh (obj/get data "line-height") + ta (obj/get data "text-align")] + (cond-> base + ta (obj/set! "textAlign" ta) + lh (obj/set! "lineHeight" lh)))) + +(defn generate-text-styles + [data] + (let [letter-spacing (obj/get data "letter-spacing") + text-decoration (obj/get data "text-decoration") + text-transform (obj/get data "text-transform") + line-height (obj/get data "line-height") + + font-id (obj/get data "font-id" (:font-id ut/default-text-attrs)) + font-variant-id (obj/get data "font-variant-id") + + font-family (obj/get data "font-family") + font-size (obj/get data "font-size") + + ;; Old properties for backwards compatibility + fill (obj/get data "fill") + opacity (obj/get data "opacity" 1) + + fill-color (obj/get data "fill-color" fill) + fill-opacity (obj/get data "fill-opacity" opacity) + fill-color-gradient (obj/get data "fill-color-gradient" nil) + fill-color-gradient (when fill-color-gradient + (-> (js->clj fill-color-gradient :keywordize-keys true) + (update :type keyword))) + + fill-color-ref-id (obj/get data "fill-color-ref-id") + fill-color-ref-file (obj/get data "fill-color-ref-file") + + [r g b a] (uc/hex->rgba fill-color fill-opacity) + background (if fill-color-gradient + (uc/gradient->css (js->clj fill-color-gradient)) + (str/format "rgba(%s, %s, %s, %s)" r g b a)) + + fontsdb (deref fonts/fontsdb) + + base #js {:textDecoration text-decoration + :textTransform text-transform + :lineHeight (or line-height "inherit") + "--text-color" background}] + + (when (and (string? letter-spacing) + (pos? (alength letter-spacing))) + (obj/set! base "letterSpacing" (str letter-spacing "px"))) + + (when (and (string? font-size) + (pos? (alength font-size))) + (obj/set! base "fontSize" (str font-size "px"))) + + (when (and (string? font-id) + (pos? (alength font-id))) + (let [font (get fontsdb font-id)] + (let [font-family (or (:family font) + (obj/get data "fontFamily")) + font-variant (d/seek #(= font-variant-id (:id %)) + (:variants font)) + font-style (or (:style font-variant) + (obj/get data "fontStyle")) + font-weight (or (:weight font-variant) + (obj/get data "fontWeight"))] + (obj/set! base "fontFamily" font-family) + (obj/set! base "fontStyle" font-style) + (obj/set! base "fontWeight" font-weight)))) + + base)) diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index 5cb7523419..c89a4e691d 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -12,7 +12,7 @@ [app.main.data.workspace.drawing :as dd] [app.main.store :as st] [app.main.ui.workspace.shapes :as shapes] - [app.main.ui.workspace.shapes.path :refer [path-editor]] + [app.main.ui.workspace.shapes.path.editor :refer [path-editor]] [app.common.geom.shapes :as gsh] [app.common.data :as d] [app.util.dom :as dom] diff --git a/frontend/src/app/main/ui/workspace/effects.cljs b/frontend/src/app/main/ui/workspace/effects.cljs new file mode 100644 index 0000000000..4cf4346748 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/effects.cljs @@ -0,0 +1,78 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.effects + (:require + [rumext.alpha :as mf] + [app.util.dom :as dom] + [app.main.data.workspace.selection :as dws] + [app.main.store :as st] + [app.main.data.workspace :as dw] + [app.main.refs :as refs] + [app.main.ui.keyboard :as kbd])) + +(defn use-pointer-enter + [{:keys [id]}] + (mf/use-callback + (mf/deps id) + (fn [] + (st/emit! (dws/change-hover-state id true))))) + +(defn use-pointer-leave + [{:keys [id]}] + (mf/use-callback + (mf/deps id) + (fn [] + (st/emit! (dws/change-hover-state id false))))) + +(defn use-context-menu + [shape] + (mf/use-callback + (mf/deps shape) + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (let [position (dom/get-client-position event)] + (st/emit! (dw/show-shape-context-menu {:position position :shape shape})))))) + +(defn use-mouse-down + [{:keys [id type blocked]}] + (mf/use-callback + (mf/deps id type blocked) + (fn [event] + (let [selected @refs/selected-shapes + edition @refs/selected-edition + selected? (contains? selected id) + drawing? @refs/selected-drawing-tool + button (.-which (.-nativeEvent event))] + (when-not blocked + (cond + (not= 1 button) + nil + + drawing? + nil + + (= type :frame) + (do (dom/stop-propagation event) + (st/emit! (dw/start-move-selected))) + + :else + (do + (dom/stop-propagation event) + (if selected? + (when (kbd/shift? event) + (st/emit! (dw/select-shape id true))) + (do + (when-not (or (empty? selected) (kbd/shift? event)) + (st/emit! (dw/deselect-all))) + (st/emit! (dw/select-shape id)))) + + (when (not= edition id) + (st/emit! (dw/start-move-selected)))))))))) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 54787f1e9a..5ea3d5ea73 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -32,7 +32,7 @@ [app.util.debug :refer [debug?]] [app.main.ui.workspace.shapes.outline :refer [outline]] [app.main.ui.measurements :as msr] - [app.main.ui.workspace.shapes.path :refer [path-editor]])) + [app.main.ui.workspace.shapes.path.editor :refer [path-editor]])) (def rotation-handler-size 25) (def resize-point-radius 4) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index bb6e9603fb..a8d65e2e97 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -19,7 +19,6 @@ [app.main.ui.shapes.rect :as rect] [app.main.ui.shapes.circle :as circle] [app.main.ui.shapes.image :as image] - [app.main.data.workspace.selection :as dws] [app.main.store :as st] [app.main.refs :as refs] @@ -54,20 +53,6 @@ (and (identical? n-shape o-shape) (identical? n-frame o-frame))))) -(defn use-mouse-enter - [{:keys [id] :as shape}] - (mf/use-callback - (mf/deps id) - (fn [] - (st/emit! (dws/change-hover-state id true))))) - -(defn use-mouse-leave - [{:keys [id] :as shape}] - (mf/use-callback - (mf/deps id) - (fn [] - (st/emit! (dws/change-hover-state id false))))) - (defn make-is-moving-ref [id] (let [check-moving (fn [local] @@ -86,8 +71,6 @@ (geom/translate-to-frame frame)) opts #js {:shape shape :frame frame} - on-mouse-enter (use-mouse-enter shape) - on-mouse-leave (use-mouse-leave shape) alt? (hooks/use-rxsub ms/keyboard-alt) @@ -95,15 +78,10 @@ #(make-is-moving-ref (:id shape))) moving? (mf/deref moving-iref)] - (mf/use-effect - (constantly on-mouse-leave)) - (when (and shape (or ghost? (not moving?)) (not (:hidden shape))) - [:g.shape-wrapper {:on-mouse-enter on-mouse-enter - :on-mouse-leave on-mouse-leave - :style {:cursor (if alt? cur/duplicate nil)}} + [:g.shape-wrapper {:style {:cursor (if alt? cur/duplicate nil)}} (case (:type shape) :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] diff --git a/frontend/src/app/main/ui/workspace/shapes/common.cljs b/frontend/src/app/main/ui/workspace/shapes/common.cljs index af268cd692..168bd0dd64 100644 --- a/frontend/src/app/main/ui/workspace/shapes/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/common.cljs @@ -9,73 +9,19 @@ (ns app.main.ui.workspace.shapes.common (:require - [rumext.alpha :as mf] - [app.main.data.workspace :as dw] - [app.main.refs :as refs] - [app.main.store :as st] - [app.main.ui.keyboard :as kbd] - [app.util.dom :as dom] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.geom.shapes :as geom] - [app.main.ui.shapes.shape :refer [shape-container]])) - -(defn- on-mouse-down - [event {:keys [id type] :as shape}] - (let [selected @refs/selected-shapes - edition @refs/selected-edition - selected? (contains? selected id) - drawing? @refs/selected-drawing-tool - button (.-which (.-nativeEvent event))] - (when-not (:blocked shape) - (cond - (not= 1 button) - nil - - drawing? - nil - - (= type :frame) - (do (dom/stop-propagation event) - (st/emit! (dw/start-move-selected))) - - :else - (do - (dom/stop-propagation event) - (if selected? - (when (kbd/shift? event) - (st/emit! (dw/select-shape id true))) - (do - (when-not (or (empty? selected) (kbd/shift? event)) - (st/emit! (dw/deselect-all))) - (st/emit! (dw/select-shape id)))) - - (when (not= edition id) - (st/emit! (dw/start-move-selected)))))))) - -(defn on-context-menu - [event shape] - (dom/prevent-default event) - (dom/stop-propagation event) - (let [position (dom/get-client-position event)] - (st/emit! (dw/show-shape-context-menu {:position position :shape shape})))) + [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.workspace.effects :as we] + [rumext.alpha :as mf])) (defn generic-wrapper-factory [component] (mf/fnc generic-wrapper {::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") - on-mouse-down (mf/use-callback - (mf/deps shape) - #(on-mouse-down % shape)) - on-context-menu (mf/use-callback - (mf/deps shape) - #(on-context-menu % shape))] - + (let [shape (unchecked-get props "shape")] [:> shape-container {:shape shape - :on-mouse-down on-mouse-down - :on-context-menu on-context-menu} + :on-mouse-down (we/use-mouse-down shape) + :on-context-menu (we/use-context-menu shape) + :on-pointer-enter (we/use-pointer-enter shape) + :on-pointer-leave (we/use-pointer-leave shape)} [:& component {:shape shape}]]))) - - diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 1d84fa6203..d092b48d98 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -9,23 +9,18 @@ (ns app.main.ui.workspace.shapes.frame (:require - [okulary.core :as l] - [rumext.alpha :as mf] - [app.common.data :as d] - [app.main.constants :as c] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.workspace.shapes.common :as common] - [app.main.data.workspace.selection :as dws] [app.main.ui.shapes.frame :as frame] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.geom.shapes :as geom] + [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.workspace.effects :as we] [app.util.dom :as dom] - [app.main.streams :as ms] [app.util.timers :as ts] - [app.main.ui.shapes.shape :refer [shape-container]])) + [okulary.core :as l] + [rumext.alpha :as mf])) (defn- frame-wrapper-factory-equals? [np op] @@ -45,29 +40,41 @@ (recur (first ids) (rest ids)) false)))))) +(defn use-select-shape [{:keys [id]}] + (mf/use-callback + (mf/deps id) + (fn [event] + (dom/prevent-default event) + (st/emit! (dw/deselect-all) + (dw/select-shape id))))) + +;; Ensure that the label has always the same font +;; size, regardless of zoom +;; https://css-tricks.com/transforms-on-svg-elements/ +(defn text-transform + [{:keys [x y]} zoom] + (let [inv-zoom (/ 1 zoom)] + (str + "scale(" inv-zoom ", " inv-zoom ") " + "translate(" (* zoom x) ", " (* zoom y) ")"))) + (mf/defc frame-title - [{:keys [frame on-double-click on-mouse-over on-mouse-out]}] + [{:keys [frame]}] (let [zoom (mf/deref refs/selected-zoom) - inv-zoom (/ 1 zoom) {:keys [width x y]} frame - label-pos (gpt/point x (- y (/ 10 zoom)))] + label-pos (gpt/point x (- y (/ 10 zoom))) + handle-click (use-select-shape frame) + handle-pointer-enter (we/use-pointer-enter frame) + handle-pointer-leave (we/use-pointer-leave frame)] [:text {:x 0 :y 0 :width width :height 20 :class "workspace-frame-label" - ;; Ensure that the label has always the same font - ;; size, regardless of zoom - ;; https://css-tricks.com/transforms-on-svg-elements/ - :transform (str - "scale(" inv-zoom ", " inv-zoom ") " - "translate(" (* zoom (:x label-pos)) ", " - (* zoom (:y label-pos)) - ")") - ;; User may also select the frame with single click in the label - :on-click on-double-click - :on-mouse-over on-mouse-over - :on-mouse-out on-mouse-out} + :transform (text-transform label-pos zoom) + :on-click handle-click + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave} (:name frame)])) (defn make-is-moving-ref @@ -97,47 +104,23 @@ #(refs/make-selected-ref (:id shape))) selected? (mf/deref selected-iref) - on-mouse-down (mf/use-callback (mf/deps shape) - #(common/on-mouse-down % shape)) - on-context-menu (mf/use-callback (mf/deps shape) - #(common/on-context-menu % shape)) - - shape (geom/transform-shape shape) + shape (gsh/transform-shape shape) children (mapv #(get objects %) (:shapes shape)) ds-modifier (get-in shape [:modifiers :displacement]) - on-double-click - (mf/use-callback - (mf/deps (:id shape)) - (fn [event] - (dom/prevent-default event) - (st/emit! (dw/deselect-all) - (dw/select-shape (:id shape))))) - - on-mouse-over - (mf/use-callback - (mf/deps (:id shape)) - (fn [] - (st/emit! (dws/change-hover-state (:id shape) true)))) - - on-mouse-out - (mf/use-callback - (mf/deps (:id shape)) - (fn [] - (st/emit! (dws/change-hover-state (:id shape) false))))] + handle-context-menu (we/use-context-menu shape) + handle-double-click (use-select-shape shape) + handle-mouse-down (we/use-mouse-down shape)] (when (and shape (or ghost? (not moving?)) (not (:hidden shape))) [:g {:class (when selected? "selected") - :on-context-menu on-context-menu - ;; :on-double-click on-double-click - :on-mouse-down on-mouse-down} + :on-context-menu handle-context-menu + :on-double-click handle-double-click + :on-mouse-down handle-mouse-down} - [:& frame-title {:frame shape - :on-context-menu on-context-menu - :on-double-click on-double-click - :on-mouse-down on-mouse-down}] + [:& frame-title {:frame shape}] [:> shape-container {:shape shape} [:& frame-shape diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index bb91982dd3..3e265d25cb 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -9,18 +9,15 @@ (ns app.main.ui.workspace.shapes.group (:require - [rumext.alpha :as mf] - [app.common.data :as d] - [app.main.constants :as c] [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] - [app.main.ui.workspace.shapes.common :as common] - [app.main.ui.shapes.shape :refer [shape-container]] - [app.main.ui.shapes.group :as group] - [app.util.dom :as dom] [app.main.streams :as ms] - [app.util.timers :as ts])) + [app.main.ui.shapes.group :as group] + [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.workspace.effects :as we] + [app.util.dom :as dom] + [rumext.alpha :as mf])) (defn- group-wrapper-factory-equals? [np op] @@ -31,6 +28,14 @@ (and (= n-frame o-frame) (= n-shape o-shape)))) +(defn use-double-click [{:keys [id]}] + (mf/use-callback + (mf/deps id) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (dw/select-inside-group id @ms/mouse-position))))) + (defn group-wrapper-factory [shape-wrapper] (let [group-shape (group/group-shape shape-wrapper)] @@ -41,14 +46,8 @@ (let [shape (unchecked-get props "shape") frame (unchecked-get props "frame") - on-mouse-down - (mf/use-callback (mf/deps shape) #(common/on-mouse-down % shape)) - - on-context-menu - (mf/use-callback (mf/deps shape) #(common/on-context-menu % shape)) - - childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) - childs (mf/deref childs-ref) + childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) + childs (mf/deref childs-ref) is-child-selected-ref (mf/use-memo (mf/deps (:id shape)) #(refs/is-child-selected? (:id shape))) @@ -59,24 +58,23 @@ mask-id (when (:masked-group? shape) (first (:shapes shape))) is-mask-selected-ref - (mf/use-memo (mf/deps mask-id) - #(refs/make-selected-ref mask-id)) + (mf/use-memo (mf/deps mask-id) #(refs/make-selected-ref mask-id)) is-mask-selected? (mf/deref is-mask-selected-ref) - on-double-click - (mf/use-callback - (mf/deps (:id shape)) - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (dw/select-inside-group (:id shape) @ms/mouse-position))))] + handle-mouse-down (we/use-mouse-down shape) + handle-context-menu (we/use-context-menu shape) + handle-pointer-enter (we/use-pointer-enter shape) + handle-pointer-leave (we/use-pointer-leave shape) + handle-double-click (use-double-click shape)] [:> shape-container {:shape shape - :on-mouse-down on-mouse-down - :on-context-menu on-context-menu - :on-double-click on-double-click} + :on-mouse-down handle-mouse-down + :on-context-menu handle-context-menu + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :on-double-click handle-double-click} [:& group-shape {:frame frame :shape shape diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 09a3ab9b2d..4205101787 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -9,330 +9,48 @@ (ns app.main.ui.workspace.shapes.path (:require - [rumext.alpha :as mf] - [goog.events :as events] - [okulary.core :as l] - [app.util.data :as d] - [app.util.dom :as dom] - [app.util.timers :as ts] - [app.main.refs :as refs] - [app.main.streams :as ms] - [app.main.constants :as c] + [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] - [app.main.data.workspace :as dw] - [app.main.data.workspace.drawing :as dr] - [app.main.data.workspace.drawing.path :as drp] - [app.main.ui.keyboard :as kbd] [app.main.ui.shapes.path :as path] - [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] - [app.main.ui.workspace.shapes.common :as common] + [app.main.ui.workspace.effects :as we] + [app.main.ui.workspace.shapes.path.common :as pc] + [app.util.dom :as dom] [app.util.geom.path :as ugp] - [app.common.geom.point :as gpt] - [app.main.ui.cursors :as cur] - [app.main.ui.icons :as i]) - (:import goog.events.EventType)) + [rumext.alpha :as mf])) -(def primary-color "#1FDEA7") -(def secondary-color "#DB00FF") -(def black-color "#000000") -(def white-color "#FFFFFF") -(def gray-color "#B1B2B5") - -(def current-edit-path-ref - (let [selfn (fn [local] - (let [id (:edition local)] - (get-in local [:edit-path id])))] - (l/derived selfn refs/workspace-local))) - -(defn make-edit-path-ref [id] - (mf/use-memo +(defn use-double-click [{:keys [id]}] + (mf/use-callback (mf/deps id) - (let [selfn #(get-in % [:edit-path id])] - #(l/derived selfn refs/workspace-local)))) - -(defn make-content-modifiers-ref [id] - (mf/use-memo - (mf/deps id) - (let [selfn #(get-in % [:edit-path id :content-modifiers])] - #(l/derived selfn refs/workspace-local)))) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (dw/start-edition-mode id) + (dw/start-path-edit id))))) (mf/defc path-wrapper {::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") hover? (or (mf/deref refs/current-hover) #{}) - - on-mouse-down (mf/use-callback - (mf/deps shape) - #(common/on-mouse-down % shape)) - on-context-menu (mf/use-callback - (mf/deps shape) - #(common/on-context-menu % shape)) - - on-double-click (mf/use-callback - (mf/deps shape) - (fn [event] - (when (not (::dr/initialized? shape)) - (do - (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (dw/start-edition-mode (:id shape)) - (dw/start-path-edit (:id shape))))))) - content-modifiers-ref (make-content-modifiers-ref (:id shape)) + content-modifiers-ref (pc/make-content-modifiers-ref (:id shape)) content-modifiers (mf/deref content-modifiers-ref) editing-id (mf/deref refs/selected-edition) editing? (= editing-id (:id shape)) - shape (update shape :content ugp/apply-content-modifiers content-modifiers)] + shape (update shape :content ugp/apply-content-modifiers content-modifiers) + handle-mouse-down (we/use-mouse-down shape) + handle-context-menu (we/use-context-menu shape) + handle-pointer-enter (we/use-pointer-enter shape) + handle-pointer-leave (we/use-pointer-leave shape) + handle-double-click (use-double-click shape)] [:> shape-container {:shape shape :pointer-events (when editing? "none") - :on-double-click on-double-click - :on-mouse-down on-mouse-down - :on-context-menu on-context-menu} + :on-mouse-down handle-mouse-down + :on-context-menu handle-context-menu + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :on-double-click handle-double-click} [:& path/path-shape {:shape shape :background? true}]])) - -(mf/defc path-actions [{:keys [shape]}] - (let [id (mf/deref refs/selected-edition) - {:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref current-edit-path-ref)] - [:div.path-actions - [:div.viewport-actions-group - [:div.viewport-actions-entry {:class (when (= edit-mode :draw) "is-toggled") - :on-click #(st/emit! (drp/change-edit-mode :draw))} i/pen] - [:div.viewport-actions-entry {:class (when (= edit-mode :move) "is-toggled") - :on-click #(st/emit! (drp/change-edit-mode :move))} i/pointer-inner]] - - #_[:div.viewport-actions-group - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-add] - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-remove]] - - #_[:div.viewport-actions-group - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-merge] - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-join] - [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-separate]] - - [:div.viewport-actions-group - [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") - :on-click #(when-not (empty? selected-points) - (st/emit! (drp/make-corner)))} i/nodes-corner] - [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") - :on-click #(when-not (empty? selected-points) - (st/emit! (drp/make-curve)))} i/nodes-curve]] - - #_[:div.viewport-actions-group - [:div.viewport-actions-entry {:class (when snap-toggled "is-toggled")} i/nodes-snap]]])) - - -(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}] - (let [{:keys [x y]} position - - on-enter - (fn [event] - (st/emit! (drp/path-pointer-enter position))) - - on-leave - (fn [event] - (st/emit! (drp/path-pointer-leave position))) - - on-click - (fn [event] - (when-not last-p? - (do (dom/stop-propagation event) - (dom/prevent-default event) - - (cond - (and (= edit-mode :move) (not selected?)) - (st/emit! (drp/select-node position)) - - (and (= edit-mode :move) selected?) - (st/emit! (drp/deselect-node position)))))) - - on-mouse-down - (fn [event] - (when-not last-p? - (do (dom/stop-propagation event) - (dom/prevent-default event) - - (cond - (= edit-mode :move) - (st/emit! (drp/start-move-path-point position)) - - (and (= edit-mode :draw) start-path?) - (st/emit! (drp/start-path-from-point position)) - - (and (= edit-mode :draw) (not start-path?)) - (st/emit! (drp/close-path-drag-start position))))))] - [:g.path-point - [:circle.path-point - {:cx x - :cy y - :r (if (or selected? hover?) (/ 3.5 zoom) (/ 3 zoom)) - :style {:stroke-width (/ 1 zoom) - :stroke (cond (or selected? hover?) black-color - preview? secondary-color - :else primary-color) - :fill (cond selected? primary-color - :else white-color)}}] - [:circle {:cx x - :cy y - :r (/ 10 zoom) - :on-click on-click - :on-mouse-down on-mouse-down - :on-mouse-enter on-enter - :on-mouse-leave on-leave - :style {:cursor (cond - (and (not last-p?) (= edit-mode :draw)) cur/pen-node - (= edit-mode :move) cur/pointer-node) - :fill "transparent"}}]])) - -(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode]}] - (when (and point handler) - (let [{:keys [x y]} handler - on-enter - (fn [event] - (st/emit! (drp/path-handler-enter index prefix))) - - on-leave - (fn [event] - (st/emit! (drp/path-handler-leave index prefix))) - - on-click - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (cond - (= edit-mode :move) - (drp/select-handler index prefix))) - - on-mouse-down - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - - (cond - (= edit-mode :move) - (st/emit! (drp/start-move-handler index prefix))))] - - [:g.handler {:pointer-events (when (= edit-mode :draw))} - [:line - {:x1 (:x point) - :y1 (:y point) - :x2 x - :y2 y - :style {:stroke (if hover? black-color gray-color) - :stroke-width (/ 1 zoom)}}] - [:rect - {:x (- x (/ 3 zoom)) - :y (- y (/ 3 zoom)) - :width (/ 6 zoom) - :height (/ 6 zoom) - - :style {:stroke-width (/ 1 zoom) - :stroke (cond (or selected? hover?) black-color - :else primary-color) - :fill (cond selected? primary-color - :else white-color)}}] - [:circle {:cx x - :cy y - :r (/ 10 zoom) - :on-click on-click - :on-mouse-down on-mouse-down - :on-mouse-enter on-enter - :on-mouse-leave on-leave - :style {:cursor (when (= edit-mode :move) cur/pointer-move) - :fill "transparent"}}]]))) - -(mf/defc path-preview [{:keys [zoom command from]}] - [:g.preview {:style {:pointer-events "none"}} - (when (not= :move-to (:command command)) - [:path {:style {:fill "transparent" - :stroke secondary-color - :stroke-width (/ 1 zoom)} - :d (ugp/content->path [{:command :move-to - :params {:x (:x from) - :y (:y from)}} - command])}]) - [:& path-point {:position (:params command) - :preview? true - :zoom zoom}]]) - -(mf/defc path-editor - [{:keys [shape zoom]}] - - (let [editor-ref (mf/use-ref nil) - edit-path-ref (make-edit-path-ref (:id shape)) - {:keys [edit-mode - drag-handler - prev-handler - preview - content-modifiers - last-point - selected-handlers - selected-points - hover-handlers - hover-points]} (mf/deref edit-path-ref) - {:keys [content]} shape - content (ugp/apply-content-modifiers content content-modifiers) - points (->> content ugp/content->points (into #{})) - last-command (last content) - last-p (->> content last ugp/command->point) - handlers (ugp/content->handlers content) - - handle-click-outside - (fn [event] - (let [current (dom/get-target event) - editor-dom (mf/ref-val editor-ref)] - (when-not (or (.contains editor-dom current) - (dom/class? current "viewport-actions-entry")) - (st/emit! (drp/deselect-all)))))] - - (mf/use-layout-effect - (fn [] - (let [keys [(events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] - #(doseq [key keys] - (events/unlistenByKey key))))) - - [:g.path-editor {:ref editor-ref} - (when (and preview (not drag-handler)) - [:& path-preview {:command preview - :from last-p - :zoom zoom}]) - - (for [position points] - [:g.path-node - [:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")} - (for [[index prefix] (get handlers position)] - (let [command (get content index) - x (get-in command [:params (d/prefix-keyword prefix :x)]) - y (get-in command [:params (d/prefix-keyword prefix :y)]) - handler-position (gpt/point x y)] - (when (not= position handler-position) - [:& path-handler {:point position - :handler handler-position - :index index - :prefix prefix - :zoom zoom - :selected? (contains? selected-handlers [index prefix]) - :hover? (contains? hover-handlers [index prefix]) - :edit-mode edit-mode}])))] - [:& path-point {:position position - :zoom zoom - :edit-mode edit-mode - :selected? (contains? selected-points position) - :hover? (contains? hover-points position) - :last-p? (= last-point position) - :start-path? (nil? last-point)}]]) - - (when prev-handler - [:g.prev-handler {:pointer-events "none"} - [:& path-handler {:point last-p - :handler prev-handler - :zoom zoom}]]) - - (when drag-handler - [:g.drag-handler {:pointer-events "none"} - [:& path-handler {:point last-p - :handler drag-handler - :zoom zoom}]])])) diff --git a/frontend/src/app/main/ui/workspace/shapes/path/actions.cljs b/frontend/src/app/main/ui/workspace/shapes/path/actions.cljs new file mode 100644 index 0000000000..4f41e9d57e --- /dev/null +++ b/frontend/src/app/main/ui/workspace/shapes/path/actions.cljs @@ -0,0 +1,47 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.shapes.path.actions + (:require + [app.main.data.workspace.drawing.path :as drp] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.ui.icons :as i] + [app.main.ui.workspace.shapes.path.common :as pc] + [rumext.alpha :as mf])) + +(mf/defc path-actions [{:keys [shape]}] + (let [id (mf/deref refs/selected-edition) + {:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref pc/current-edit-path-ref)] + [:div.path-actions + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class (when (= edit-mode :draw) "is-toggled") + :on-click #(st/emit! (drp/change-edit-mode :draw))} i/pen] + [:div.viewport-actions-entry {:class (when (= edit-mode :move) "is-toggled") + :on-click #(st/emit! (drp/change-edit-mode :move))} i/pointer-inner]] + + #_[:div.viewport-actions-group + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-add] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-remove]] + + #_[:div.viewport-actions-group + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-merge] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-join] + [:div.viewport-actions-entry {:class "is-disabled"} i/nodes-separate]] + + [:div.viewport-actions-group + [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") + :on-click #(when-not (empty? selected-points) + (st/emit! (drp/make-corner)))} i/nodes-corner] + [:div.viewport-actions-entry {:class (when (empty? selected-points) "is-disabled") + :on-click #(when-not (empty? selected-points) + (st/emit! (drp/make-curve)))} i/nodes-curve]] + + #_[:div.viewport-actions-group + [:div.viewport-actions-entry {:class (when snap-toggled "is-toggled")} i/nodes-snap]]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/path/common.cljs b/frontend/src/app/main/ui/workspace/shapes/path/common.cljs new file mode 100644 index 0000000000..b5f408c92e --- /dev/null +++ b/frontend/src/app/main/ui/workspace/shapes/path/common.cljs @@ -0,0 +1,39 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.shapes.path.common + (:require + [app.main.refs :as refs] + [okulary.core :as l] + [rumext.alpha :as mf])) + +(def primary-color "#1FDEA7") +(def secondary-color "#DB00FF") +(def black-color "#000000") +(def white-color "#FFFFFF") +(def gray-color "#B1B2B5") + +(def current-edit-path-ref + (let [selfn (fn [local] + (let [id (:edition local)] + (get-in local [:edit-path id])))] + (l/derived selfn refs/workspace-local))) + +(defn make-edit-path-ref [id] + (mf/use-memo + (mf/deps id) + (let [selfn #(get-in % [:edit-path id])] + #(l/derived selfn refs/workspace-local)))) + +(defn make-content-modifiers-ref [id] + (mf/use-memo + (mf/deps id) + (let [selfn #(get-in % [:edit-path id :content-modifiers])] + #(l/derived selfn refs/workspace-local)))) + diff --git a/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs new file mode 100644 index 0000000000..1cefba76aa --- /dev/null +++ b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs @@ -0,0 +1,235 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.shapes.path.editor + (:require + [app.common.geom.point :as gpt] + [app.main.data.workspace.drawing.path :as drp] + [app.main.store :as st] + [app.main.ui.cursors :as cur] + [app.main.ui.workspace.shapes.path.common :as pc] + [app.util.data :as d] + [app.util.dom :as dom] + [app.util.geom.path :as ugp] + [goog.events :as events] + [rumext.alpha :as mf]) + (:import goog.events.EventType)) + +(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}] + (let [{:keys [x y]} position + + on-enter + (fn [event] + (st/emit! (drp/path-pointer-enter position))) + + on-leave + (fn [event] + (st/emit! (drp/path-pointer-leave position))) + + on-click + (fn [event] + (when-not last-p? + (do (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (and (= edit-mode :move) (not selected?)) + (st/emit! (drp/select-node position)) + + (and (= edit-mode :move) selected?) + (st/emit! (drp/deselect-node position)))))) + + on-mouse-down + (fn [event] + (when-not last-p? + (do (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (= edit-mode :move) + (st/emit! (drp/start-move-path-point position)) + + (and (= edit-mode :draw) start-path?) + (st/emit! (drp/start-path-from-point position)) + + (and (= edit-mode :draw) (not start-path?)) + (st/emit! (drp/close-path-drag-start position))))))] + [:g.path-point + [:circle.path-point + {:cx x + :cy y + :r (if (or selected? hover?) (/ 3.5 zoom) (/ 3 zoom)) + :style {:stroke-width (/ 1 zoom) + :stroke (cond (or selected? hover?) pc/black-color + preview? pc/secondary-color + :else pc/primary-color) + :fill (cond selected? pc/primary-color + :else pc/white-color)}}] + [:circle {:cx x + :cy y + :r (/ 10 zoom) + :on-click on-click + :on-mouse-down on-mouse-down + :on-mouse-enter on-enter + :on-mouse-leave on-leave + :style {:cursor (cond + (and (not last-p?) (= edit-mode :draw)) cur/pen-node + (= edit-mode :move) cur/pointer-node) + :fill "transparent"}}]])) + +(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode]}] + (when (and point handler) + (let [{:keys [x y]} handler + on-enter + (fn [event] + (st/emit! (drp/path-handler-enter index prefix))) + + on-leave + (fn [event] + (st/emit! (drp/path-handler-leave index prefix))) + + on-click + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (cond + (= edit-mode :move) + (drp/select-handler index prefix))) + + on-mouse-down + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + + (cond + (= edit-mode :move) + (st/emit! (drp/start-move-handler index prefix))))] + + [:g.handler {:pointer-events (when (= edit-mode :draw))} + [:line + {:x1 (:x point) + :y1 (:y point) + :x2 x + :y2 y + :style {:stroke (if hover? pc/black-color pc/gray-color) + :stroke-width (/ 1 zoom)}}] + [:rect + {:x (- x (/ 3 zoom)) + :y (- y (/ 3 zoom)) + :width (/ 6 zoom) + :height (/ 6 zoom) + + :style {:stroke-width (/ 1 zoom) + :stroke (cond (or selected? hover?) pc/black-color + :else pc/primary-color) + :fill (cond selected? pc/primary-color + :else pc/white-color)}}] + [:circle {:cx x + :cy y + :r (/ 10 zoom) + :on-click on-click + :on-mouse-down on-mouse-down + :on-mouse-enter on-enter + :on-mouse-leave on-leave + :style {:cursor (when (= edit-mode :move) cur/pointer-move) + :fill "transparent"}}]]))) + +(mf/defc path-preview [{:keys [zoom command from]}] + [:g.preview {:style {:pointer-events "none"}} + (when (not= :move-to (:command command)) + [:path {:style {:fill "transparent" + :stroke pc/secondary-color + :stroke-width (/ 1 zoom)} + :d (ugp/content->path [{:command :move-to + :params {:x (:x from) + :y (:y from)}} + command])}]) + [:& path-point {:position (:params command) + :preview? true + :zoom zoom}]]) + +(mf/defc path-editor + [{:keys [shape zoom]}] + + (let [editor-ref (mf/use-ref nil) + edit-path-ref (pc/make-edit-path-ref (:id shape)) + {:keys [edit-mode + drag-handler + prev-handler + preview + content-modifiers + last-point + selected-handlers + selected-points + hover-handlers + hover-points]} (mf/deref edit-path-ref) + {:keys [content]} shape + content (ugp/apply-content-modifiers content content-modifiers) + points (->> content ugp/content->points (into #{})) + last-command (last content) + last-p (->> content last ugp/command->point) + handlers (ugp/content->handlers content) + + handle-click-outside + (fn [event] + (let [current (dom/get-target event) + editor-dom (mf/ref-val editor-ref)] + (when-not (or (.contains editor-dom current) + (dom/class? current "viewport-actions-entry")) + (st/emit! (drp/deselect-all)))))] + + (mf/use-layout-effect + (fn [] + (let [keys [(events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] + #(doseq [key keys] + (events/unlistenByKey key))))) + + [:g.path-editor {:ref editor-ref} + (when (and preview (not drag-handler)) + [:& path-preview {:command preview + :from last-p + :zoom zoom}]) + + (for [position points] + [:g.path-node + [:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")} + (for [[index prefix] (get handlers position)] + (let [command (get content index) + x (get-in command [:params (d/prefix-keyword prefix :x)]) + y (get-in command [:params (d/prefix-keyword prefix :y)]) + handler-position (gpt/point x y)] + (when (not= position handler-position) + [:& path-handler {:point position + :handler handler-position + :index index + :prefix prefix + :zoom zoom + :selected? (contains? selected-handlers [index prefix]) + :hover? (contains? hover-handlers [index prefix]) + :edit-mode edit-mode}])))] + [:& path-point {:position position + :zoom zoom + :edit-mode edit-mode + :selected? (contains? selected-points position) + :hover? (contains? hover-points position) + :last-p? (= last-point position) + :start-path? (nil? last-point)}]]) + + (when prev-handler + [:g.prev-handler {:pointer-events "none"} + [:& path-handler {:point last-p + :handler prev-handler + :zoom zoom}]]) + + (when drag-handler + [:g.drag-handler {:pointer-events "none"} + [:& path-handler {:point last-p + :handler drag-handler + :zoom zoom}]])])) + diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 2a9b1b24b3..f6b08211d5 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -9,455 +9,132 @@ (ns app.main.ui.workspace.shapes.text (:require - ["slate" :as slate] - ["slate-react" :as rslate] - [app.common.data :as d] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.texts :as dwt] - [app.main.fonts :as fonts] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.context :as muc] - [app.main.ui.cursors :as cur] - [app.main.ui.keyboard :as kbd] - [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.text :as text] + [app.main.ui.workspace.effects :as we] [app.main.ui.workspace.shapes.common :as common] - [app.util.color :as color] - [app.util.color :as uc] + [app.main.ui.workspace.shapes.text.editor :as editor] [app.util.dom :as dom] [app.util.object :as obj] - [app.util.text :as ut] [app.util.timers :as timers] [beicon.core :as rx] - [cuerdas.core :as str] - [goog.events :as events] - [goog.object :as gobj] - [rumext.alpha :as mf]) - (:import - goog.events.EventType - goog.events.KeyCodes)) + [rumext.alpha :as mf])) ;; --- Events -(defn handle-mouse-down - [event {:keys [id group] :as shape}] - (if (and (not (:blocked shape)) - (or @refs/selected-drawing-tool - @refs/selected-edition)) - (dom/stop-propagation event) - (common/on-mouse-down event shape))) +(defn use-double-click [{:keys [id]} selected?] + (mf/use-callback + (mf/deps id selected?) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (when selected? + (st/emit! (dw/start-edition-mode id)))))) ;; --- Text Wrapper for workspace -(declare text-shape-edit) -(declare text-shape) +(defn handle-shape-resize [{:keys [name id selrect grow-type overflow-text]} new-width new-height] + (let [{shape-width :width shape-height :height} selrect + undo-transaction (get-in @st/state [:workspace-undo :transaction])] + (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) + (when (and (> new-width 0) + (> new-height 0) + (or (not= shape-width new-width) + (not= shape-height new-height))) + (cond + (and overflow-text (not= :fixed grow-type)) + (st/emit! (dwt/update-overflow-text id false)) + + (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) + (st/emit! (dwt/update-overflow-text id true)) + + (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) + (st/emit! (dwt/update-overflow-text id false)) + + (= grow-type :auto-width) + (st/emit! (dw/update-dimensions [id] :width new-width) + (dw/update-dimensions [id] :height new-height)) + + (= grow-type :auto-height) + (st/emit! (dw/update-dimensions [id] :height new-height)))) + (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))) + +(defn resize-observer [shape root query] + (mf/use-effect + (mf/deps shape root query) + (fn [] + (let [on-change (fn [entries] + (when (seq entries) + ;; RequestAnimationFrame so the "loop limit error" error is not thrown + ;; https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded + (timers/raf + #(let [width (obj/get-in entries [0 "contentRect" "width"]) + height (obj/get-in entries [0 "contentRect" "height"])] + (handle-shape-resize shape width height))))) + observer (js/ResizeObserver. on-change) + node (when root (dom/query root query))] + (when node (.observe observer node)) + #(.disconnect observer))))) (mf/defc text-wrapper {::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") - selected-iref (mf/use-memo (mf/deps (:id shape)) - #(refs/make-selected-ref (:id shape))) - selected? (mf/deref selected-iref) - edition (mf/deref refs/selected-edition) + (let [{:keys [id x y width height] :as shape} (unchecked-get props "shape") + selected-iref (mf/use-memo (mf/deps (:id shape)) + #(refs/make-selected-ref (:id shape))) + selected? (mf/deref selected-iref) + edition (mf/deref refs/selected-edition) current-transform (mf/deref refs/current-transform) - render-editor (mf/use-state false) - edition? (= edition (:id shape)) + render-editor (mf/use-state false) - embed-resources? (mf/use-ctx muc/embed-ctx) + edition? (= edition id) - on-mouse-down #(handle-mouse-down % shape) - on-context-menu #(common/on-context-menu % shape) + embed-resources? (mf/use-ctx muc/embed-ctx) - on-double-click - (fn [event] - (dom/stop-propagation event) - (dom/prevent-default event) - (when selected? - (st/emit! (dw/start-edition-mode (:id shape))))) + handle-mouse-down (we/use-mouse-down shape) + handle-context-menu (we/use-context-menu shape) + handle-pointer-enter (we/use-pointer-enter shape) + handle-pointer-leave (we/use-pointer-leave shape) + handle-double-click (use-double-click shape selected?) - check? - (and (#{:auto-width :auto-height} (:grow-type shape)) - selected? - (not edition?) - (not embed-resources?) - (nil? current-transform))] + text-ref (mf/use-ref nil) + text-node (mf/ref-val text-ref) + edit-text-ref (mf/use-ref nil) + edit-text-node (mf/ref-val edit-text-ref)] - (mf/use-effect - (mf/deps check?) - (fn [] - (let [sem (timers/schedule #(reset! render-editor check?))] - #(rx/dispose! sem)))) + (resize-observer shape text-node ".paragraph-set") + (resize-observer shape edit-text-node ".paragraph-set") - [:> shape-container {:shape shape - :on-double-click on-double-click - :on-mouse-down on-mouse-down - :on-context-menu on-context-menu} - (when @render-editor - [:g {:opacity 0 - :style {:pointer-events "none"}} - ;; We only render the component for its side-effect - [:& text-shape-edit {:shape shape - :read-only? true}]]) + [:> shape-container {:shape shape} + [:& text/text-shape {:key "text-shape" + :ref text-ref + :shape shape + :selected? selected? + :style {:display (when edition? "none")}}] + (when edition? + [:& editor/text-shape-edit {:key "editor" + :ref edit-text-ref + :shape shape}]) - (if edition? - [:& text-shape-edit {:shape shape}] - [:& text/text-shape {:shape shape - :selected? selected?}])])) + (when-not edition? + [:rect.text-actions + {:x x + :y y + :width width + :height height + :style {:fill "transparent"} + :on-mouse-down handle-mouse-down + :on-context-menu handle-context-menu + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :on-double-click handle-double-click + :transform (gsh/transform-matrix shape)}])])) -;; --- Text Editor Rendering - -(defn- generate-root-styles - [data props] - (let [valign (obj/get data "vertical-align" "top") - talign (obj/get data "text-align") - shape (obj/get props "shape") - base #js {:height "100%" - :width (:width shape) - :display "flex"}] - (cond-> base - (= valign "top") (obj/set! "alignItems" "flex-start") - (= valign "center") (obj/set! "alignItems" "center") - (= valign "bottom") (obj/set! "alignItems" "flex-end") - (= talign "left") (obj/set! "justifyContent" "flex-start") - (= talign "center") (obj/set! "justifyContent" "center") - (= talign "right") (obj/set! "justifyContent" "flex-end") - (= talign "justify") (obj/set! "justifyContent" "stretch")))) - -(defn- generate-paragraph-styles - [data] - (let [base #js {:fontSize "14px" - :margin "inherit" - :lineHeight "1.2"} - lh (obj/get data "line-height") - ta (obj/get data "text-align")] - (cond-> base - ta (obj/set! "textAlign" ta) - lh (obj/set! "lineHeight" lh)))) - -(defn- generate-text-styles - [data] - (let [letter-spacing (obj/get data "letter-spacing") - text-decoration (obj/get data "text-decoration") - text-transform (obj/get data "text-transform") - line-height (obj/get data "line-height") - - font-id (obj/get data "font-id" (:font-id ut/default-text-attrs)) - font-variant-id (obj/get data "font-variant-id") - - font-family (obj/get data "font-family") - font-size (obj/get data "font-size") - - ;; Old properties for backwards compatibility - fill (obj/get data "fill") - opacity (obj/get data "opacity" 1) - - fill-color (obj/get data "fill-color" fill) - fill-opacity (obj/get data "fill-opacity" opacity) - fill-color-gradient (obj/get data "fill-color-gradient" nil) - fill-color-gradient (when fill-color-gradient - (-> (js->clj fill-color-gradient :keywordize-keys true) - (update :type keyword))) - - fill-color-ref-id (obj/get data "fill-color-ref-id") - fill-color-ref-file (obj/get data "fill-color-ref-file") - - [r g b a] (uc/hex->rgba fill-color fill-opacity) - background (if fill-color-gradient - (uc/gradient->css (js->clj fill-color-gradient)) - (str/format "rgba(%s, %s, %s, %s)" r g b a)) - - fontsdb (deref fonts/fontsdb) - - base #js {:textDecoration text-decoration - :textTransform text-transform - :lineHeight (or line-height "inherit") - "--text-color" background}] - - (when (and (string? letter-spacing) - (pos? (alength letter-spacing))) - (obj/set! base "letterSpacing" (str letter-spacing "px"))) - - (when (and (string? font-size) - (pos? (alength font-size))) - (obj/set! base "fontSize" (str font-size "px"))) - - (when (and (string? font-id) - (pos? (alength font-id))) - (let [font (get fontsdb font-id)] - (let [font-family (or (:family font) - (obj/get data "fontFamily")) - font-variant (d/seek #(= font-variant-id (:id %)) - (:variants font)) - font-style (or (:style font-variant) - (obj/get data "fontStyle")) - font-weight (or (:weight font-variant) - (obj/get data "fontWeight"))] - (obj/set! base "fontFamily" font-family) - (obj/set! base "fontStyle" font-style) - (obj/set! base "fontWeight" font-weight)))) - - base)) - -(mf/defc editor-root-node - {::mf/wrap-props false - ::mf/wrap [mf/memo]} - [props] - (let [attrs (obj/get props "attributes") - childs (obj/get props "children") - data (obj/get props "element") - type (obj/get data "type") - style (generate-root-styles data props) - attrs (obj/set! attrs "style" style) - attrs (obj/set! attrs "className" type)] - [:> :div attrs childs])) - -(mf/defc editor-paragraph-set-node - {::mf/wrap-props false} - [props] - (let [attrs (obj/get props "attributes") - childs (obj/get props "children") - data (obj/get props "element") - type (obj/get data "type") - shape (obj/get props "shape") - - ;; The position absolute is used so the paragraph is "outside" - ;; the normal layout and can grow outside its parent - ;; We use this element to measure the size of the text - style #js {:display "inline-block" - :position "absolute"} - attrs (obj/set! attrs "style" style) - attrs (obj/set! attrs "className" type)] - [:> :div attrs childs])) - -(mf/defc editor-paragraph-node - {::mf/wrap-props false} - [props] - (let [attrs (obj/get props "attributes") - childs (obj/get props "children") - data (obj/get props "element") - style (generate-paragraph-styles data) - attrs (obj/set! attrs "style" style)] - [:> :p attrs childs])) - -(mf/defc editor-text-node - {::mf/wrap-props false} - [props] - (let [attrs (obj/get props "attributes") - childs (obj/get props "children") - data (obj/get props "leaf") - style (generate-text-styles data) - attrs (-> attrs - (obj/set! "style" style) - (obj/set! "className" "text-node"))] - [:> :span attrs childs])) - -(defn- render-element - [shape props] - (mf/html - (let [element (obj/get props "element") - props (obj/merge! props #js {:shape shape})] - (case (obj/get element "type") - "root" [:> editor-root-node props] - "paragraph-set" [:> editor-paragraph-set-node props] - "paragraph" [:> editor-paragraph-node props] - nil)))) - -(defn- render-text - [props] - (mf/html - [:> editor-text-node props])) - -;; --- Text Shape Edit - -(defn- initial-text - [text] - (clj->js - [{:type "root" - :children [{:type "paragraph-set" - :children [{:type "paragraph" - :children [{:text (or text "")}]}]}]}])) -(defn- parse-content - [content] - (cond - (string? content) (initial-text content) - (map? content) (clj->js [content]) - :else (initial-text ""))) - -(defn- content-size - [node] - (let [current (count (:text node)) - children-count (->> node :children (map content-size) (reduce +))] - (+ current children-count))) - -(defn fix-gradients - "Fix for the gradient types that need to be keywords" - [content] - (let [fix-node - (fn [node] - (d/update-in-when node [:fill-color-gradient :type] keyword))] - (ut/map-node fix-node content))) - -(mf/defc text-shape-edit - {::mf/wrap [mf/memo]} - [{:keys [shape read-only?] :or {read-only? false} :as props}] - (let [{:keys [id x y width height content grow-type]} shape - zoom (mf/deref refs/selected-zoom) - state (mf/use-state #(parse-content content)) - editor (mf/use-memo #(dwt/create-editor)) - self-ref (mf/use-ref) - selecting-ref (mf/use-ref) - measure-ref (mf/use-ref) - - content-var (mf/use-var content) - - on-close - (fn [] - (when (not read-only?) - (st/emit! dw/clear-edition-mode)) - (when (= 0 (content-size @content-var)) - (st/emit! (dw/delete-shapes [id])))) - - on-click-outside - (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - - - (let [sidebar (dom/get-element "settings-bar") - assets (dom/get-element-by-class "assets-bar") - cpicker (dom/get-element-by-class "colorpicker-tooltip") - self (mf/ref-val self-ref) - target (dom/get-target event) - selecting? (mf/ref-val selecting-ref)] - (when-not (or (and sidebar (.contains sidebar target)) - (and assets (.contains assets target)) - (and self (.contains self target)) - (and cpicker (.contains cpicker target))) - (if selecting? - (mf/set-ref-val! selecting-ref false) - (on-close))))) - - on-mouse-down - (fn [event] - (mf/set-ref-val! selecting-ref true)) - - on-mouse-up - (fn [event] - (mf/set-ref-val! selecting-ref false)) - - on-key-up - (fn [event] - (dom/stop-propagation event) - (when (= (.-keyCode event) 27) ; ESC - (do - (st/emit! :interrupt) - (on-close)))) - - on-mount - (fn [] - (when (not read-only?) - (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click-outside) - lkey2 (events/listen (dom/get-root) EventType.KEYUP on-key-up)] - (st/emit! (dwt/assign-editor id editor) - dwc/start-undo-transaction) - - #(do - (st/emit! (dwt/assign-editor id nil) - dwc/commit-undo-transaction) - (events/unlistenByKey lkey1) - (events/unlistenByKey lkey2))))) - - on-focus - (fn [event] - (when (not read-only?) - (dwt/editor-select-all! editor))) - - on-change - (mf/use-callback - (fn [val] - (when (not read-only?) - (let [content (js->clj val :keywordize-keys true) - content (first content) - content (fix-gradients content)] - ;; Append timestamp so we can react to cursor change events - (st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))})) - (reset! state val) - (reset! content-var content)))))] - - (mf/use-effect on-mount) - - (mf/use-effect - (mf/deps content) - (fn [] - (reset! state (parse-content content)) - (reset! content-var content))) - - ;; Checks the size of the wrapper to update if it were necesary - (mf/use-effect - (mf/deps shape) - - (fn [] - (fonts/ready - #(let [self-node (mf/ref-val self-ref) - paragraph-node (when self-node (dom/query self-node ".paragraph-set"))] - (when paragraph-node - (let [ - {bb-w :width bb-h :height} (dom/get-bounding-rect paragraph-node) - width (max (/ bb-w zoom) 7) - height (max (/ bb-h zoom) 16) - undo-transaction (get-in @st/state [:workspace-undo :transaction])] - (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) - (when (or (not= (:width shape) width) - (not= (:height shape) height)) - (cond - (and (:overflow-text shape) (not= :fixed (:grow-type shape))) - (st/emit! (dwt/update-overflow-text id false)) - - (and (= :fixed (:grow-type shape)) (not (:overflow-text shape)) (> height (:height shape))) - (st/emit! (dwt/update-overflow-text id true)) - - (and (= :fixed (:grow-type shape)) (:overflow-text shape) (<= height (:height shape))) - (st/emit! (dwt/update-overflow-text id false)) - - (= grow-type :auto-width) - (st/emit! (dw/update-dimensions [id] :width width) - (dw/update-dimensions [id] :height height)) - - (= grow-type :auto-height) - (st/emit! (dw/update-dimensions [id] :height height)) - )) - (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))))))) - - [:foreignObject {:ref self-ref - :transform (geom/transform-matrix shape) - :x x :y y - :width (if (= :auto-width grow-type) 10000 width) - :height height} - [:style "span { line-height: inherit; } - .text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] - [:> rslate/Slate {:editor editor - :value @state - :on-change on-change} - [:> rslate/Editable - {:auto-focus (when (not read-only?) "true") - :spell-check "false" - :on-focus on-focus - :class "rich-text" - :style {:cursor cur/text - :width (:width shape)} - :render-element #(render-element shape %) - :render-leaf render-text - :on-mouse-up on-mouse-up - :on-mouse-down on-mouse-down - :on-blur (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - ;; WARN: monky patch - (obj/set! slate/Transforms "deselect" (constantly nil))) - :placeholder (when (= :fixed grow-type) "Type some text here...")}]]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs new file mode 100644 index 0000000000..7aa43d8e6d --- /dev/null +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -0,0 +1,256 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.shapes.text.editor + (:require + ["slate" :as slate] + ["slate-react" :as rslate] + [goog.events :as events] + [rumext.alpha :as mf] + [app.common.data :as d] + [app.common.geom.shapes :as gsh] + [app.util.dom :as dom] + [app.util.text :as ut] + [app.util.object :as obj] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.fonts :as fonts] + [app.main.data.workspace :as dw] + [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.texts :as dwt] + [app.main.ui.cursors :as cur] + [app.main.ui.shapes.text.styles :as sts]) + (:import + goog.events.EventType + goog.events.KeyCodes)) + +;; --- Data functions + +(defn- initial-text + [text] + (clj->js + [{:type "root" + :children [{:type "paragraph-set" + :children [{:type "paragraph" + :children [{:text (or text "")}]}]}]}])) +(defn- parse-content + [content] + (cond + (string? content) (initial-text content) + (map? content) (clj->js [content]) + :else (initial-text ""))) + +(defn- content-size + [node] + (let [current (count (:text node)) + children-count (->> node :children (map content-size) (reduce +))] + (+ current children-count))) + +(defn- fix-gradients + "Fix for the gradient types that need to be keywords" + [content] + (let [fix-node + (fn [node] + (d/update-in-when node [:fill-color-gradient :type] keyword))] + (ut/map-node fix-node content))) + +;; --- Text Editor Rendering + +(mf/defc editor-root-node + {::mf/wrap-props false + ::mf/wrap [mf/memo]} + [props] + (let [ + childs (obj/get props "children") + data (obj/get props "element") + type (obj/get data "type") + style (sts/generate-root-styles data props) + attrs (-> (obj/get props "attributes") + (obj/set! "style" style) + (obj/set! "className" type))] + [:> :div attrs childs])) + +(mf/defc editor-paragraph-set-node + {::mf/wrap-props false} + [props] + (let [childs (obj/get props "children") + data (obj/get props "element") + type (obj/get data "type") + shape (obj/get props "shape") + style (sts/generate-paragraph-set-styles data) + attrs (-> (obj/get props "attributes") + (obj/set! "style" style) + (obj/set! "className" type))] + [:> :div attrs childs])) + +(mf/defc editor-paragraph-node + {::mf/wrap-props false} + [props] + (let [ + childs (obj/get props "children") + data (obj/get props "element") + type (obj/get data "type") + style (sts/generate-paragraph-styles data) + attrs (-> (obj/get props "attributes") + (obj/set! "style" style) + (obj/set! "className" type))] + [:> :p attrs childs])) + +(mf/defc editor-text-node + {::mf/wrap-props false} + [props] + (let [childs (obj/get props "children") + data (obj/get props "leaf") + style (sts/generate-text-styles data) + attrs (-> (obj/get props "attributes") + (obj/set! "style" style) + (obj/set! "className" "text-node"))] + [:> :span attrs childs])) + +(defn- render-element + [shape props] + (mf/html + (let [element (obj/get props "element") + props (obj/merge! props #js {:shape shape})] + (case (obj/get element "type") + "root" [:> editor-root-node props] + "paragraph-set" [:> editor-paragraph-set-node props] + "paragraph" [:> editor-paragraph-node props] + nil)))) + +(defn- render-text + [props] + (mf/html + [:> editor-text-node props])) + +;; --- Text Shape Edit + +(mf/defc text-shape-edit + {::mf/wrap [mf/memo] + ::mf/wrap-props false + ::mf/forward-ref true} + [props ref] + (let [shape (unchecked-get props "shape") + node-ref (unchecked-get props "node-ref") + ;; read-only? (or (unchecked-get props "read-only?") false) + + {:keys [id x y width height content grow-type]} shape + zoom (mf/deref refs/selected-zoom) + state (mf/use-state #(parse-content content)) + editor (mf/use-memo #(dwt/create-editor)) + ;;self-ref (mf/use-ref) + selecting-ref (mf/use-ref) + measure-ref (mf/use-ref) + + content-var (mf/use-var content) + + on-close + (fn [] + (st/emit! dw/clear-edition-mode) + (when (= 0 (content-size @content-var)) + (st/emit! (dw/delete-shapes [id])))) + + on-click-outside + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + + (let [sidebar (dom/get-element "settings-bar") + assets (dom/get-element-by-class "assets-bar") + cpicker (dom/get-element-by-class "colorpicker-tooltip") + self (when node-ref (mf/ref-val node-ref)) + target (dom/get-target event) + selecting? (mf/ref-val selecting-ref)] + (when-not (or (and sidebar (.contains sidebar target)) + (and assets (.contains assets target)) + (and self (.contains self target)) + (and cpicker (.contains cpicker target))) + (if selecting? + (mf/set-ref-val! selecting-ref false) + (on-close))))) + + on-mouse-down + (fn [event] + (mf/set-ref-val! selecting-ref true)) + + on-mouse-up + (fn [event] + (mf/set-ref-val! selecting-ref false)) + + on-key-up + (fn [event] + (dom/stop-propagation event) + (when (= (.-keyCode event) 27) ; ESC + (do + (st/emit! :interrupt) + (on-close)))) + + on-mount + (fn [] + (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click-outside) + lkey2 (events/listen (dom/get-root) EventType.KEYUP on-key-up)] + (st/emit! (dwt/assign-editor id editor) + dwc/start-undo-transaction) + + #(do + (st/emit! (dwt/assign-editor id nil) + dwc/commit-undo-transaction) + (events/unlistenByKey lkey1) + (events/unlistenByKey lkey2)))) + + on-focus + (fn [event] + (dwt/editor-select-all! editor)) + + on-change + (mf/use-callback + (fn [val] + (let [content (js->clj val :keywordize-keys true) + content (first content) + content (fix-gradients content)] + ;; Append timestamp so we can react to cursor change events + (st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))})) + (reset! state val) + (reset! content-var content))))] + + (mf/use-effect on-mount) + + (mf/use-effect + (mf/deps content) + (fn [] + (reset! state (parse-content content)) + (reset! content-var content))) + + [:foreignObject {:ref ref + :transform (gsh/transform-matrix shape) + :x x :y y + :width (if (#{:auto-width} grow-type) 10000 width) + :height (if (#{:auto-height :auto-width} grow-type) 10000 height)} + [:style "span { line-height: inherit; } + .text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] + [:> rslate/Slate {:editor editor + :value @state + :on-change on-change} + [:> rslate/Editable + {:auto-focus "true" + :spell-check "false" + :on-focus on-focus + :class "rich-text" + :style {:cursor cur/text + :width (:width shape)} + :render-element #(render-element shape %) + :render-leaf render-text + :on-mouse-up on-mouse-up + :on-mouse-down on-mouse-down + :on-blur (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + ;; WARN: monky patch + (obj/set! slate/Transforms "deselect" (constantly nil))) + :placeholder (when (= :fixed grow-type) "Type some text here...")}]]])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index de145248ab..20d384a60e 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -53,7 +53,7 @@ [potok.core :as ptk] [promesa.core :as p] [rumext.alpha :as mf] - [app.main.ui.workspace.shapes.path :refer [path-actions]]) + [app.main.ui.workspace.shapes.path.actions :refer [path-actions]]) (:import goog.events.EventType)) ;; --- Coordinates Widget From 0046b60c93700d4fa97f7336244ecdb761f22de3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 27 Nov 2020 15:14:53 +0100 Subject: [PATCH 095/195] :bug: Fixes problem with flipped texts --- common/app/common/geom/shapes.cljc | 32 +++++---- common/app/common/geom/shapes/transforms.cljc | 7 +- .../src/app/main/ui/workspace/selection.cljs | 71 +++++++++---------- .../app/main/ui/workspace/shapes/text.cljs | 26 +++---- .../main/ui/workspace/shapes/text/editor.cljs | 16 +++-- 5 files changed, 80 insertions(+), 72 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 5109d9d6af..de210cdaa8 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -44,26 +44,29 @@ (move shape (gpt/point dx dy)))) ;; --- Resize (Dimensions) -;; Fixme: Improve using modifiers instead of calculating the selrect/points (defn resize [shape width height] (us/assert map? shape) (us/assert number? width) (us/assert number? height) - (let [selrect (-> (:selrect shape) - (assoc :width width) - (assoc :height height) - (assoc :x2 (+ (-> shape :selrect :x1) width)) - (assoc :y2 (+ (-> shape :selrect :y1) height))) - center (gco/center-selrect selrect) - points (-> selrect gpr/rect->points (gtr/transform-points center (:transform shape)))] + (let [shape-transform (:transform shape (gmt/matrix)) + shape-transform-inv (:transform-inverse shape (gmt/matrix)) + shape-center (gco/center-shape shape) + {sr-width :width sr-height :height} (:selrect shape) + origin (-> (gpt/point (:selrect shape)) + (gtr/transform-point-center shape-center shape-transform)) + + scalev (gpt/divide (gpt/point width height) + (gpt/point sr-width sr-height))] (-> shape - (assoc :width width) - (assoc :height height) - (assoc :selrect selrect) - (assoc :points points)))) + (update :modifiers assoc + :resize-vector scalev + :resize-origin origin + :resize-transform shape-transform + :resize-transform-inverse shape-transform-inv) + (gtr/transform-shape)))) (defn resize-rect [shape attr value] @@ -258,7 +261,10 @@ (defn points->selrect [points] (gpr/points->selrect points)) (defn transform-shape [shape] (gtr/transform-shape shape)) -(defn transform-matrix [shape] (gtr/transform-matrix shape)) +(defn transform-matrix + ([shape] (gtr/transform-matrix shape)) + ([shape options] (gtr/transform-matrix shape options))) + (defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) (defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index deebb59667..b5bc71beea 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -22,12 +22,17 @@ (defn transform-matrix "Returns a transformation matrix without changing the shape properties. The result should be used in a `transform` attribute in svg" - ([{:keys [x y] :as shape}] + ([shape] (transform-matrix shape nil)) + ([{:keys [x y flip-x flip-y] :as shape} {:keys [no-flip]}] (let [shape-center (or (gco/center-shape shape) (gpt/point 0 0))] (-> (gmt/matrix) (gmt/translate shape-center) + (gmt/multiply (:transform shape (gmt/matrix))) + (cond-> + (and (not no-flip) flip-x) (gmt/scale (gpt/point -1 1)) + (and (not no-flip) flip-y) (gmt/scale (gpt/point 1 -1))) (gmt/translate (gpt/negate shape-center)))))) (defn transform-point-center diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 5ea3d5ea73..f14e5d9564 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -65,52 +65,47 @@ :position :top-left :props {:cx x :cy y}} - ;; TOP + {:type :rotation + :position :top-right + :props {:cx (+ x width) :cy y}} + + {:type :resize-point + :position :top-right + :props {:cx (+ x width) :cy y}} + + {:type :rotation + :position :bottom-right + :props {:cx (+ x width) :cy (+ y height)}} + + {:type :resize-point + :position :bottom-right + :props {:cx (+ x width) :cy (+ y height)}} + + {:type :rotation + :position :bottom-left + :props {:cx x :cy (+ y height)}} + + {:type :resize-point + :position :bottom-left + :props {:cx x :cy (+ y height)}} + {:type :resize-side :position :top :props {:x x :y y :length width :angle 0 }} - ;; TOP-RIGHT - {:type :rotation - :position :top-right - :props {:cx (+ x width) :cy y}} - - {:type :resize-point - :position :top-right - :props {:cx (+ x width) :cy y}} - - ;; RIGHT {:type :resize-side :position :right :props {:x (+ x width) :y y :length height :angle 90 }} - ;; BOTTOM-RIGHT - {:type :rotation - :position :bottom-right - :props {:cx (+ x width) :cy (+ y height)}} - - {:type :resize-point - :position :bottom-right - :props {:cx (+ x width) :cy (+ y height)}} - - ;; BOTTOM {:type :resize-side :position :bottom :props {:x (+ x width) :y (+ y height) :length width :angle 180 }} - ;; BOTTOM-LEFT - {:type :rotation - :position :bottom-left - :props {:cx x :cy (+ y height)}} - - {:type :resize-point - :position :bottom-left - :props {:cx x :cy (+ y height)}} - - ;; LEFT {:type :resize-side :position :left - :props {:x x :y (+ y height) :length height :angle 270 }}]) + :props {:x x :y (+ y height) :length height :angle 270 }} + + ]) (mf/defc rotation-handler [{:keys [cx cy transform position rotation zoom on-rotate]}] (let [size (/ rotation-handler-size zoom) @@ -160,11 +155,13 @@ (mf/defc resize-side-handler [{:keys [x y length angle zoom position rotation transform on-resize]}] (let [res-point (if (#{:top :bottom} position) {:y y} - {:x x})] - [:rect {:x (+ x (/ resize-point-rect-size zoom)) + {:x x}) + width length #_(max 0 (- length (/ (* resize-point-rect-size 2) zoom))) + height (/ resize-side-height zoom)] + [:rect {:x x :y (- y (/ resize-side-height 2 zoom)) - :width (max 0 (- length (/ (* resize-point-rect-size 2) zoom))) - :height (/ resize-side-height zoom) + :width width + :height height :transform (gmt/multiply transform (gmt/rotate-matrix angle (gpt/point x y))) :on-mouse-down #(on-resize res-point %) @@ -183,7 +180,7 @@ current-transform (mf/deref refs/current-transform) selrect (:selrect shape) - transform (geom/transform-matrix shape) + transform (geom/transform-matrix shape {:no-flip true}) tr-shape (geom/transform-shape shape)] diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index f6b08211d5..52ddeba2a8 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -10,6 +10,7 @@ (ns app.main.ui.workspace.shapes.text (:require [app.common.geom.shapes :as gsh] + [app.common.math :as mth] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.texts :as dwt] @@ -40,14 +41,11 @@ ;; --- Text Wrapper for workspace -(defn handle-shape-resize [{:keys [name id selrect grow-type overflow-text]} new-width new-height] +(defn handle-shape-resize [{:keys [id selrect grow-type overflow-text]} new-width new-height] (let [{shape-width :width shape-height :height} selrect undo-transaction (get-in @st/state [:workspace-undo :transaction])] (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) - (when (and (> new-width 0) - (> new-height 0) - (or (not= shape-width new-width) - (not= shape-height new-height))) + (when (and (> new-width 0) (> new-height 0)) (cond (and overflow-text (not= :fixed grow-type)) (st/emit! (dwt/update-overflow-text id false)) @@ -58,17 +56,19 @@ (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) (st/emit! (dwt/update-overflow-text id false)) - (= grow-type :auto-width) + (and (or (not= shape-width new-width) + (not= shape-height new-height)) + (= grow-type :auto-width)) (st/emit! (dw/update-dimensions [id] :width new-width) (dw/update-dimensions [id] :height new-height)) - (= grow-type :auto-height) + (and (not= shape-height new-height) (= grow-type :auto-height)) (st/emit! (dw/update-dimensions [id] :height new-height)))) (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))) -(defn resize-observer [shape root query] +(defn resize-observer [{:keys [id selrect grow-type overflow-text] :as shape} root query] (mf/use-effect - (mf/deps shape root query) + (mf/deps id selrect grow-type overflow-text root query) (fn [] (let [on-change (fn [entries] (when (seq entries) @@ -77,7 +77,7 @@ (timers/raf #(let [width (obj/get-in entries [0 "contentRect" "width"]) height (obj/get-in entries [0 "contentRect" "height"])] - (handle-shape-resize shape width height))))) + (handle-shape-resize shape (mth/ceil width) (mth/ceil height)))))) observer (js/ResizeObserver. on-change) node (when root (dom/query root query))] (when node (.observe observer node)) @@ -106,12 +106,9 @@ handle-double-click (use-double-click shape selected?) text-ref (mf/use-ref nil) - text-node (mf/ref-val text-ref) - edit-text-ref (mf/use-ref nil) - edit-text-node (mf/ref-val edit-text-ref)] + text-node (mf/ref-val text-ref)] (resize-observer shape text-node ".paragraph-set") - (resize-observer shape edit-text-node ".paragraph-set") [:> shape-container {:shape shape} [:& text/text-shape {:key "text-shape" @@ -121,7 +118,6 @@ :style {:display (when edition? "none")}}] (when edition? [:& editor/text-shape-edit {:key "editor" - :ref edit-text-ref :shape shape}]) (when-not edition? diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 7aa43d8e6d..c1652bffd2 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -117,8 +117,13 @@ [shape props] (mf/html (let [element (obj/get props "element") - props (obj/merge! props #js {:shape shape})] - (case (obj/get element "type") + type (obj/get element "type") + props (obj/merge! props #js {:shape shape}) + props (cond-> props + (= type "root") (obj/set! "key" "root") + (= type "paragraph-set") (obj/set! "key" "paragraph-set"))] + + (case type "root" [:> editor-root-node props] "paragraph-set" [:> editor-paragraph-set-node props] "paragraph" [:> editor-paragraph-node props] @@ -138,13 +143,12 @@ [props ref] (let [shape (unchecked-get props "shape") node-ref (unchecked-get props "node-ref") - ;; read-only? (or (unchecked-get props "read-only?") false) {:keys [id x y width height content grow-type]} shape zoom (mf/deref refs/selected-zoom) state (mf/use-state #(parse-content content)) editor (mf/use-memo #(dwt/create-editor)) - ;;self-ref (mf/use-ref) + self-ref (mf/use-ref) selecting-ref (mf/use-ref) measure-ref (mf/use-ref) @@ -164,7 +168,7 @@ (let [sidebar (dom/get-element "settings-bar") assets (dom/get-element-by-class "assets-bar") cpicker (dom/get-element-by-class "colorpicker-tooltip") - self (when node-ref (mf/ref-val node-ref)) + self (mf/ref-val self-ref) target (dom/get-target event) selecting? (mf/ref-val selecting-ref)] (when-not (or (and sidebar (.contains sidebar target)) @@ -227,7 +231,7 @@ (reset! state (parse-content content)) (reset! content-var content))) - [:foreignObject {:ref ref + [:foreignObject {:ref self-ref :transform (gsh/transform-matrix shape) :x x :y y :width (if (#{:auto-width} grow-type) 10000 width) From becd0d9cbffdd130e068dba4ceeabaff5853ccfc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 27 Nov 2020 16:08:45 +0100 Subject: [PATCH 096/195] :bug: Add strict spec verify on operations result. --- common/app/common/pages.cljc | 50 ++++++++++++++++++++++++------------ common/app/common/spec.cljc | 15 +++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 8e2c58bb20..971cf92966 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -44,18 +44,33 @@ (s/def ::component-root? boolean?) (s/def ::shape-ref uuid?) -(s/def ::safe-integer - #(and - (integer? %) - (>= % min-safe-int) - (<= % max-safe-int))) +(s/def ::safe-integer ::us/safe-integer) +(s/def ::safe-number ::us/safe-number) -(s/def ::safe-number - #(and - (number? %) - (>= % min-safe-int) - (<= % max-safe-int))) +(s/def :internal.matrix/a ::us/safe-number) +(s/def :internal.matrix/b ::us/safe-number) +(s/def :internal.matrix/c ::us/safe-number) +(s/def :internal.matrix/d ::us/safe-number) +(s/def :internal.matrix/e ::us/safe-number) +(s/def :internal.matrix/f ::us/safe-number) +(s/def ::matrix + (s/and (s/keys :req-un [:internal.matrix/a + :internal.matrix/b + :internal.matrix/c + :internal.matrix/d + :internal.matrix/e + :internal.matrix/f]) + gmt/matrix?)) + + +(s/def :internal.point/x ::us/safe-number) +(s/def :internal.point/y ::us/safe-number) + +(s/def ::point + (s/and (s/keys :req-un [:internal.point/x + :internal.point/y]) + gpt/point?)) ;; GRADIENTS @@ -252,7 +267,6 @@ (s/def :internal.shape/exports (s/coll-of :internal.shape/export :kind vector?)) - (s/def :internal.shape/selrect (s/keys :req-un [:internal.shape/x :internal.shape/y @@ -263,15 +277,15 @@ :internal.shape/width :internal.shape/height])) -(s/def :internal.shape/point - (s/and (s/keys :req-un [:internal.shape/x :internal.shape/y]) gpt/point?)) - (s/def :internal.shape/points - (s/every :internal.shape/point :kind vector?)) + (s/every ::point :kind vector?)) (s/def :internal.shape/shapes (s/every uuid? :kind vector?)) +(s/def :internal.shape/transform ::matrix) +(s/def :internal.shape/transform-inverse ::matrix) + (s/def ::shape-attrs (s/keys :opt-un [:internal.shape/selrect :internal.shape/points @@ -306,6 +320,8 @@ :internal.shape/stroke-width :internal.shape/stroke-alignment :internal.shape/text-align + :internal.shape/transform + :internal.shape/transform-inverse :internal.shape/width :internal.shape/height :internal.shape/interactions @@ -781,7 +797,9 @@ [data {:keys [id page-id component-id operations] :as change}] (let [update-fn (fn [objects] (if-let [obj (get objects id)] - (assoc objects id (reduce process-operation obj operations)) + (let [result (reduce process-operation obj operations)] + (us/verify ::shape result) + (assoc objects id result)) objects))] (if page-id (d/update-in-when data [:pages-index page-id :objects] update-fn) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index 4223c93f37..de52035361 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -121,6 +121,21 @@ (s/def ::point gpt/point?) (s/def ::id ::uuid) +(def max-safe-int 9007199254740991) +(def min-safe-int -9007199254740991) + +(s/def ::safe-integer + #(and + (integer? %) + (>= % min-safe-int) + (<= % max-safe-int))) + +(s/def ::safe-number + #(and + (number? %) + (>= % min-safe-int) + (<= % max-safe-int))) + ;; --- Macros (defn spec-assert From b4341cba18760911f00b4e8e4e618467a83e3a73 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 27 Nov 2020 16:15:44 +0100 Subject: [PATCH 097/195] :fire: Temporary comment undo validation. --- frontend/src/app/main/data/workspace/common.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 69a50ad6a4..eb95f2b9ee 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -66,7 +66,7 @@ commit-local? false} :as opts}] (us/verify ::cp/changes changes) - (us/verify ::cp/changes undo-changes) + ;; (us/verify ::cp/changes undo-changes) (ptk/reify ::commit-changes cljs.core/IDeref (-deref [_] changes) From a976a826a57eb6f00707d79ae6746224635efe3f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 27 Nov 2020 13:20:26 +0100 Subject: [PATCH 098/195] :bug: Fix inconsistences on messages specs. --- frontend/src/app/main/data/media.cljs | 27 +++++++++++++----------- frontend/src/app/main/data/messages.cljs | 4 ++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/data/media.cljs b/frontend/src/app/main/data/media.cljs index bdab5699b4..0f32ada2b8 100644 --- a/frontend/src/app/main/data/media.cljs +++ b/frontend/src/app/main/data/media.cljs @@ -2,25 +2,28 @@ ;; 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) 2016 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.data.media (:require - [cljs.spec.alpha :as s] - [cuerdas.core :as str] - [beicon.core :as rx] - [potok.core :as ptk] - [app.common.spec :as us] [app.common.data :as d] [app.common.media :as cm] - [app.main.data.messages :as dm] - [app.main.store :as st] - [app.main.repo :as rp] - [app.util.i18n :refer [tr]] - [app.util.router :as rt] + [app.common.spec :as us] [app.common.uuid :as uuid] + [app.main.data.messages :as dm] + [app.main.repo :as rp] + [app.main.store :as st] + [app.util.i18n :refer [tr]] + [app.util.router :as r] + [app.util.router :as rt] [app.util.time :as ts] - [app.util.router :as r])) + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [cuerdas.core :as str] + [potok.core :as ptk])) ;; --- Specs diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index a688c756b8..9cce091990 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -28,12 +28,12 @@ (s/def ::status #{:visible :hide}) (s/def ::controls #{:none :close :inline-actions :bottom-actions}) -(s/def ::tag ::us/string) +(s/def ::tag (s/or :str ::us/string :kw ::us/keyword)) (s/def ::label ::us/string) (s/def ::callback fn?) (s/def ::action (s/keys :req-un [::label ::callback])) (s/def ::actions (s/every ::message-action :kind vector?)) -(s/def ::timeout ::us/integer) +(s/def ::timeout (s/nilable ::us/integer)) (s/def ::content ::us/string) (s/def ::message From 420d98c0f9cbd68b62f95b9733e5ba03f4fe2ad3 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 27 Nov 2020 13:29:35 +0100 Subject: [PATCH 099/195] :bug: Fix unauthorized error handling on viewer with token. --- frontend/src/app/main/data/viewer.cljs | 10 ++++++++-- frontend/src/app/main/ui/viewer/header.cljs | 12 +++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index cf06925ecc..5c63e62eab 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -136,12 +136,18 @@ (->> data (filter #(= page-id (:page-id %))) (d/index-by :id) - (assoc state :comment-threads)))] + (assoc state :comment-threads))) + (on-error [err] + (if (= :authorization (:type err)) + (rx/empty) + (rx/throw err)))] + (ptk/reify ::fetch-comment-threads ptk/WatchEvent (watch [_ state stream] (->> (rp/query :comment-threads {:file-id file-id}) - (rx/map #(partial fetched %))))))) + (rx/map #(partial fetched %)) + (rx/catch on-error)))))) (defn refresh-comment-thread [{:keys [id file-id] :as thread}] diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index f0bd849f36..ae063c32ea 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -192,6 +192,16 @@ (mf/use-callback (st/emitf dv/toggle-thumbnails-panel)) + on-goback + (mf/use-callback + (mf/deps project-id file-id page-id anonymous?) + (fn [] + (if anonymous? + (st/emit! (rt/nav :login)) + (st/emit! (rt/nav :workspace + {:project-id project-id + :file-id file-id} + {:page-id page-id}))))) on-edit (mf/use-callback (mf/deps project-id file-id page-id) @@ -220,7 +230,7 @@ [:header.viewer-header [:div.main-icon - [:a {:on-click on-edit} i/logo-icon]] + [:a {:on-click on-goback} i/logo-icon]] [:div.sitemap-zone {:alt (t locale "viewer.header.sitemap") :on-click on-click} From df95bd70100f4f83a9b1a17c985dd61d243fcfac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 30 Nov 2020 13:12:34 +0100 Subject: [PATCH 100/195] :tada: Select all elements tool and shortcut --- frontend/resources/locales.json | 8 ++++++++ frontend/src/app/main/data/workspace.cljs | 3 ++- .../src/app/main/data/workspace/selection.cljs | 17 +++++++++++++++++ frontend/src/app/main/ui/workspace/header.cljs | 7 +++++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 7cdd3bdaa7..333811db23 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -2422,6 +2422,14 @@ "es" : "Ocultar reglas" } }, + "workspace.header.menu.select-all" : { + "translations" : { + "en" : "Select all", + "fr" : "", + "ru" : "", + "es" : "Seleccionar todo" + } + }, "workspace.header.menu.show-assets" : { "used-in" : [ "src/app/main/ui/workspace/header.cljs:210" ], "translations" : { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 3cc6bb702f..ecc17a7158 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1596,6 +1596,7 @@ ;; Selection (def select-shape dws/select-shape) +(def select-all dws/select-all) (def deselect-all dws/deselect-all) (def select-shapes dwc/select-shapes) (def duplicate-selected dws/duplicate-selected) @@ -1630,7 +1631,7 @@ {"ctrl+i" #(st/emit! (toggle-layout-flags :assets)) "ctrl+l" #(st/emit! (toggle-layout-flags :sitemap :layers)) "ctrl+shift+r" #(st/emit! (toggle-layout-flags :rules)) - "ctrl+a" #(st/emit! (toggle-layout-flags :dynamic-alignment)) + "ctrl+a" #(st/emit! (select-all)) "ctrl+p" #(st/emit! (toggle-layout-flags :colorpalette)) "ctrl+'" #(st/emit! (toggle-layout-flags :display-grid)) "ctrl+shift+'" #(st/emit! (toggle-layout-flags :snap-grid)) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 2d33d9e543..d01e9c8b4c 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -118,6 +118,23 @@ objects (dwc/lookup-page-objects state page-id)] (rx/of (dwc/expand-all-parents ids objects)))))) +(defn select-all + [] + (ptk/reify ::select-all + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + is-not-blocked (fn [shape-id] (not (get-in state [:workspace-data + :pages-index page-id + :objects shape-id + :blocked] false)))] + (rx/of (->> (cph/select-toplevel-shapes objects) + (map :id) + (filter is-not-blocked) + (into lks/empty-linked-set) + (select-shapes))))))) + (defn deselect-all "Clear all possible state of drawing, edition or any similar action taken by the user. diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 29cbdf18bb..d79f42ce78 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -208,12 +208,15 @@ (tr "workspace.header.menu.show-assets"))] [:span.shortcut "Ctrl+i"]] + [:li {:on-click #(st/emit! (dw/select-all))} + [:span (tr "workspace.header.menu.select-all")] + [:span.shortcut "Ctrl+a"]] + [:li {:on-click #(st/emit! (dw/toggle-layout-flags :dynamic-alignment))} [:span (if (contains? layout :dynamic-alignment) (tr "workspace.header.menu.disable-dynamic-alignment") - (tr "workspace.header.menu.enable-dynamic-alignment"))] - [:span.shortcut "Ctrl+a"]] + (tr "workspace.header.menu.enable-dynamic-alignment"))]] (if (:is-shared file) [:li {:on-click on-remove-shared} From 6390af082703e3f830be0e3c8e15188a503f2942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 30 Nov 2020 08:55:36 +0100 Subject: [PATCH 101/195] :sparkles: Change tool names and shortcuts --- frontend/resources/locales.json | 18 +++++++++--------- frontend/src/app/main/data/workspace.cljs | 2 +- .../app/main/ui/workspace/left_toolbar.cljs | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 333811db23..90ebd3bf32 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -3635,13 +3635,13 @@ "es" : "Recursos (Ctrl + I)" } }, - "workspace.toolbar.circle" : { + "workspace.toolbar.ellipse" : { "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:69" ], "translations" : { - "en" : "Circle (E)", - "fr" : "Cercle (E)", - "ru" : "Круг (E)", - "es" : "Círculo (E)" + "en" : "Ellipse (E)", + "fr" : "", + "ru" : "", + "es" : "Elipse (E)" } }, "workspace.toolbar.color-palette" : { @@ -3708,10 +3708,10 @@ "workspace.toolbar.rect" : { "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:64" ], "translations" : { - "en" : "Box (B)", - "fr" : "Boîte (B)", - "ru" : "Прямоугольник (B)", - "es" : "Recuadro (B)" + "en" : "Rectangle (R)", + "fr" : "", + "ru" : "", + "es" : "Rectángulo (R)" } }, "workspace.toolbar.text" : { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index ecc17a7158..e66eb73d82 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1651,7 +1651,7 @@ "ctrl+y" #(st/emit! dwc/redo) "ctrl+q" #(st/emit! dwc/reinitialize-undo) "a" #(st/emit! (dwd/select-for-drawing :frame)) - "b" #(st/emit! (dwd/select-for-drawing :rect)) + "r" #(st/emit! (dwd/select-for-drawing :rect)) "e" #(st/emit! (dwd/select-for-drawing :circle)) "t" #(st/emit! dwtxt/start-edit-if-selected (dwd/select-for-drawing :text)) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index 9308a5a1e5..5137d3fdee 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -66,7 +66,7 @@ :on-click (partial select-drawtool :rect)} i/box] [:li.tooltip.tooltip-right - {:alt (t locale "workspace.toolbar.circle") + {:alt (t locale "workspace.toolbar.ellipse") :class (when (= selected-drawtool :circle) "selected") :on-click (partial select-drawtool :circle)} i/circle] From 9445e3abb8c059a5eec91b6c3a197633f5854146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 30 Nov 2020 08:55:36 +0100 Subject: [PATCH 102/195] :sparkles: Restore russian --- frontend/resources/locales.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 90ebd3bf32..0bf7355417 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -3710,7 +3710,7 @@ "translations" : { "en" : "Rectangle (R)", "fr" : "", - "ru" : "", + "ru" : "Прямоугольник (R)", "es" : "Rectángulo (R)" } }, From 357e779013e5d1fd96acb7205efa318593c75f40 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 10:30:01 +0100 Subject: [PATCH 103/195] :lipstick: Cosmetic changes on pages helpers namespace. --- common/app/common/pages_helpers.cljc | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index 8c2f1e5619..b49014ed25 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -262,19 +262,16 @@ "Retrieves a list with the indexes for each element in the layer tree. This will be used for shift+selection." [objects] - (let [rec-index - (fn rec-index [cur-idx id] - (let [object (get objects id) - red-fn - (fn [cur-idx id] - (let [[prev-idx _] (first cur-idx) - prev-idx (or prev-idx 0) - cur-idx (conj cur-idx [(inc prev-idx) id])] - (rec-index cur-idx id)))] - (reduce red-fn cur-idx (reverse (:shapes object)))))] + (letfn [(red-fn [cur-idx id] + (let [[prev-idx _] (first cur-idx) + prev-idx (or prev-idx 0) + cur-idx (conj cur-idx [(inc prev-idx) id])] + (rec-index cur-idx id))) + (rec-index [cur-idx id] + (let [object (get objects id)] + (reduce red-fn cur-idx (reverse (:shapes object)))))] (into {} (rec-index '() uuid/zero)))) - (defn expand-region-selection "Given a selection selects all the shapes between the first and last in an indexed manner (shift selection)" @@ -285,7 +282,7 @@ (map first)) from (apply min filter-indexes) - to (apply max filter-indexes)] + to (apply max filter-indexes)] (->> indexed-shapes (filter (fn [[idx _]] (and (>= idx from) (<= idx to)))) (map second) From 0416ce8da605392fbe4e3c0d0deba6c200f78484 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 10:32:21 +0100 Subject: [PATCH 104/195] :sparkles: Add workaround to broken texts exception. --- frontend/src/app/main/ui/workspace/shapes/text.cljs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 52ddeba2a8..895de130e8 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -41,7 +41,8 @@ ;; --- Text Wrapper for workspace -(defn handle-shape-resize [{:keys [id selrect grow-type overflow-text]} new-width new-height] +(defn handle-shape-resize + [{:keys [id selrect grow-type overflow-text]} new-width new-height] (let [{shape-width :width shape-height :height} selrect undo-transaction (get-in @st/state [:workspace-undo :transaction])] (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) @@ -59,11 +60,14 @@ (and (or (not= shape-width new-width) (not= shape-height new-height)) (= grow-type :auto-width)) - (st/emit! (dw/update-dimensions [id] :width new-width) - (dw/update-dimensions [id] :height new-height)) + (when (and (pos? shape-width) + (pos? shape-height)) + (st/emit! (dw/update-dimensions [id] :width new-width) + (dw/update-dimensions [id] :height new-height))) (and (not= shape-height new-height) (= grow-type :auto-height)) - (st/emit! (dw/update-dimensions [id] :height new-height)))) + (when (pos? shape-height) + (st/emit! (dw/update-dimensions [id] :height new-height))))) (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))) (defn resize-observer [{:keys [id selrect grow-type overflow-text] :as shape} root query] From 39db88c53396ab0a6d3d4105e8163de655df9388 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 10:33:38 +0100 Subject: [PATCH 105/195] :sparkles: Reduce the max and min safe-int values to 1m. --- common/app/common/spec.cljc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index de52035361..c791fc467f 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -121,8 +121,8 @@ (s/def ::point gpt/point?) (s/def ::id ::uuid) -(def max-safe-int 9007199254740991) -(def min-safe-int -9007199254740991) +(def max-safe-int 1000000) +(def min-safe-int -1000000) (s/def ::safe-integer #(and From 4a7b5618ff8c71dbeabda7a1f35846cb44bdf055 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 10:51:44 +0100 Subject: [PATCH 106/195] :bug: Fix unauthorized error on handoff on share-link. --- frontend/src/app/main/data/viewer.cljs | 16 +++++++++++++ frontend/src/app/main/ui.cljs | 7 ++++-- frontend/src/app/main/ui/viewer/header.cljs | 26 ++++++--------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 5c63e62eab..739cc0cefe 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -331,6 +331,22 @@ (when index (rx/of (go-to-frame-by-index index))))))) + +(defn go-to-section + [section] + (ptk/reify ::go-to-section + ptk/WatchEvent + (watch [_ state stream] + (let [route (:route state) + screen (-> route :data :name keyword) + pparams (:path-params route) + qparams (:query-params route)] + (rx/of + (if (= :handoff section) + (rt/nav :handoff pparams qparams) + (rt/nav :viewer pparams (assoc qparams :section section)))))))) + + (defn set-current-frame [frame-id] (ptk/reify ::current-frame ptk/UpdateEvent diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 0783ebca12..8a8ea4b9e2 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -161,10 +161,13 @@ :handoff (let [file-id (get-in route [:path-params :file-id]) page-id (get-in route [:path-params :page-id]) - index (get-in route [:query-params :index])] + index (get-in route [:query-params :index]) + token (get-in route [:query-params :token])] + [:& handoff {:page-id page-id :file-id file-id - :index index}]) + :index index + :token token}]) :render-object (do diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index ae063c32ea..058a8df879 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -213,20 +213,7 @@ (mf/use-callback (mf/deps file-id page-id) (fn [section] - (st/emit! - (case section - :interactions - (rt/nav :viewer - {:file-id file-id :page-id page-id} - {:index index :section "interactions"}) - :comments - (rt/nav :viewer - {:file-id file-id :page-id page-id} - {:index index :section "comments"}) - :handoff - (rt/nav :handoff - {:file-id file-id :page-id page-id} - {:index index})))))] + (st/emit! (dv/go-to-section section))))] [:header.viewer-header [:div.main-icon @@ -249,11 +236,12 @@ :alt "View mode"} i/play] - [:button.mode-zone-button.tooltip.tooltip-bottom - {:on-click #(navigate :comments) - :class (dom/classnames :active (= section :comments)) - :alt "Comments"} - i/chat] + (when-not anonymous? + [:button.mode-zone-button.tooltip.tooltip-bottom + {:on-click #(navigate :comments) + :class (dom/classnames :active (= section :comments)) + :alt "Comments"} + i/chat]) [:button.mode-zone-button.tooltip.tooltip-bottom {:on-click #(navigate :handoff) From 3835e0ea74816e87f03499af1aa34af0ac7620db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 30 Nov 2020 14:29:19 +0100 Subject: [PATCH 107/195] :bug: Select and deselect shapes correctly inside an artboard --- frontend/src/app/main/ui/workspace/effects.cljs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/effects.cljs b/frontend/src/app/main/ui/workspace/effects.cljs index 4cf4346748..ab94350a56 100644 --- a/frontend/src/app/main/ui/workspace/effects.cljs +++ b/frontend/src/app/main/ui/workspace/effects.cljs @@ -60,8 +60,11 @@ nil (= type :frame) - (do (dom/stop-propagation event) + (if selected? + (do + (dom/stop-propagation event) (st/emit! (dw/start-move-selected))) + (st/emit! (dw/deselect-all))) :else (do From 64a53a68c1555a091a1180aa50586b1368749ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 27 Nov 2020 12:10:38 +0100 Subject: [PATCH 108/195] :sparkles: Allow to increment number inputs by 10 --- .../app/main/ui/components/numeric_input.cljs | 48 ++++++++++ frontend/src/app/main/ui/keyboard.cljs | 2 + .../workspace/sidebar/options/frame_grid.cljs | 10 +-- .../workspace/sidebar/options/measures.cljs | 60 ++++++------- .../sidebar/options/rows/color_row.cljs | 16 ++-- .../sidebar/options/rows/input_row.cljs | 14 +-- .../ui/workspace/sidebar/options/shadow.cljs | 88 +++++++++---------- frontend/src/app/util/dom.cljs | 5 ++ 8 files changed, 143 insertions(+), 100 deletions(-) create mode 100644 frontend/src/app/main/ui/components/numeric_input.cljs diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs new file mode 100644 index 0000000000..d2c005729c --- /dev/null +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -0,0 +1,48 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.components.numeric-input + (:require + [rumext.alpha :as mf] + [app.main.ui.keyboard :as kbd] + [app.common.data :as d] + [app.util.dom :as dom] + [app.util.object :as obj])) + +(mf/defc numeric-input + {::mf/wrap-props false + ::mf/forward-ref true} + [props ref] + (let [on-key-down + (mf/use-callback + (fn [event] + (when (and (or (kbd/up-arrow? event) (kbd/down-arrow? event)) + (kbd/shift? event)) + (let [increment (if (kbd/up-arrow? event) 9 -9) ; this is added to the + target (dom/get-target event) ; default 1 or -1 step + min-value (-> (dom/get-attribute target "min") + (d/parse-integer ##-Inf)) + max-value (-> (dom/get-attribute target "max") + (d/parse-integer ##Inf)) + new-value (-> target + (dom/get-value) + (d/parse-integer 0) + (+ increment) + (cljs.core/min max-value) + (cljs.core/max min-value))] + (dom/set-value! target new-value))))) + + props (-> props + (obj/set! "className" "input-text") + (obj/set! "type" "number") + (obj/set! "ref" ref) + (obj/set! "onKeyDown" on-key-down))] + + [:> :input props])) + diff --git a/frontend/src/app/main/ui/keyboard.cljs b/frontend/src/app/main/ui/keyboard.cljs index 9bc6d8499d..ecc03d63bb 100644 --- a/frontend/src/app/main/ui/keyboard.cljs +++ b/frontend/src/app/main/ui/keyboard.cljs @@ -20,3 +20,5 @@ (def esc? (is-keycode? 27)) (def enter? (is-keycode? 13)) (def space? (is-keycode? 32)) +(def up-arrow? (is-keycode? 38)) +(def down-arrow? (is-keycode? 40)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs index d1aba7a4f5..ed4c96295c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs @@ -23,6 +23,7 @@ [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]] + [app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.components.select :refer [select]] [app.main.ui.components.editable-select :refer [editable-select]] [app.main.ui.components.dropdown :refer [dropdown]] @@ -135,11 +136,10 @@ (if (= type :square) [:div.input-element.pixels - [:input.input-text {:type "number" - :min "1" - :no-validate true - :value (:size params) - :on-change (handle-change-event :params :size)}]] + [:> numeric-input {:min "1" + :no-validate true + :value (:size params) + :on-change (handle-change-event :params :size)}]] [:& editable-select {:value (:size params) :type (when (number? (:size params)) "number" ) :class "input-option" diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index 6d67412d8b..4f819819ba 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -20,6 +20,7 @@ [app.common.geom.point :as gpt] [app.main.data.workspace :as udw] [app.main.data.workspace.common :as dwc] + [app.main.ui.components.numeric-input :refer [numeric-input]] [app.common.math :as math] [app.util.i18n :refer [t] :as i18n])) @@ -119,23 +120,20 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.size")] [:div.input-element.width - [:input.input-text {:type "number" - :min "0" - :no-validate true - :placeholder "--" - :on-click select-all - :on-change on-width-change - :value (attr->string :width values)}]] - + [:> numeric-input {:min "0" + :no-validate true + :placeholder "--" + :on-click select-all + :on-change on-width-change + :value (attr->string :width values)}]] [:div.input-element.height - [:input.input-text {:type "number" - :min "0" - :no-validate true - :placeholder "--" - :on-click select-all - :on-change on-height-change - :value (attr->string :height values)}]] + [:> numeric-input {:min "0" + :no-validate true + :placeholder "--" + :on-click select-all + :on-change on-height-change + :value (attr->string :height values)}]] [:div.lock-size {:class (classnames :selected (true? proportion-lock) @@ -150,28 +148,25 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.position")] [:div.input-element.Xaxis - [:input.input-text {:type "number" - :no-validate true - :placeholder "--" - :on-click select-all - :on-change on-pos-x-change - :value (attr->string :x values)}]] + [:> numeric-input {:no-validate true + :placeholder "--" + :on-click select-all + :on-change on-pos-x-change + :value (attr->string :x values)}]] [:div.input-element.Yaxis - [:input.input-text {:type "number" - :no-validate true - :placeholder "--" - :on-click select-all - :on-change on-pos-y-change - :value (attr->string :y values)}]]]) + [:> numeric-input {:no-validate true + :placeholder "--" + :on-click select-all + :on-change on-pos-y-change + :value (attr->string :y values)}]]]) ;; ROTATION (when (options :rotation) [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.rotation")] [:div.input-element.degrees - [:input.input-text - {:type "number" - :no-validate true + [:> numeric-input + {:no-validate true :min "0" :max "359" :placeholder "--" @@ -192,9 +187,8 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.radius")] [:div.input-element.pixels - [:input.input-text - {:type "number" - :placeholder "--" + [:> numeric-input + {:placeholder "--" :on-click select-all :on-change on-radius-change :value (attr->string :rx values)}]] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index 2a6437fb51..45bb7e84dd 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -20,7 +20,8 @@ [app.util.color :as uc] [app.main.refs :as refs] [app.main.data.modal :as modal] - [app.main.ui.components.color-bullet :as cb])) + [app.main.ui.components.color-bullet :as cb] + [app.main.ui.components.numeric-input :refer [numeric-input]])) (defn color-picker-callback [color disable-gradient disable-opacity handle-change-color handle-open handle-close] @@ -158,11 +159,10 @@ (not (:gradient color))) [:div.input-element {:class (classnames :percentail (not= (:opacity color) :multiple))} - [:input.input-text {:type "number" - :value (-> color :opacity opacity->string) - :placeholder (tr "settings.multiple") - :on-click select-all - :on-change handle-opacity-change - :min "0" - :max "100"}]])])])) + [:> numeric-input {:value (-> color :opacity opacity->string) + :placeholder (tr "settings.multiple") + :on-click select-all + :on-change handle-opacity-change + :min "0" + :max "100"}]])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs index 4c79333341..a04be184d2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs @@ -11,6 +11,7 @@ (:require [rumext.alpha :as mf] [app.common.data :as d] + [app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.components.select :refer [select]] [app.main.ui.components.editable-select :refer [editable-select]] [app.util.dom :as dom])) @@ -42,10 +43,9 @@ (or (not min) (>= value min)) (or (not max) (<= value max))) (on-change value))))] - [:input.input-text - {:placeholder placeholder - :type "number" - :on-change handle-change - :value (or value "")}])) - - ]]) + [:> numeric-input {:placeholder placeholder + :min (when min (str min)) + :max (when max (str max)) + :on-change handle-change + :value (or value "")}]))]]) + diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index 54756d4da2..0db47133ae 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -15,6 +15,7 @@ [app.main.data.workspace.common :as dwc] [app.main.store :as st] [app.main.ui.icons :as i] + [app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.util.dom :as dom] @@ -92,23 +93,20 @@ [:div.element-set-actions-button {:on-click #(reset! open-shadow true)} i/actions] - - [:input.input-text {:type "number" - :ref basic-offset-x-ref - :on-change (update-attr index :offset-x valid-number?) - :on-click (select-text basic-offset-x-ref) - :default-value (:offset-x value)}] - [:input.input-text {:type "number" - :ref basic-offset-y-ref - :on-change (update-attr index :offset-y valid-number?) - :on-click (select-text basic-offset-y-ref) - :default-value (:offset-y value)}] - [:input.input-text {:type "number" - :ref basic-blur-ref - :on-click (select-text basic-blur-ref) - :on-change (update-attr index :blur valid-number?) - :min 0 - :default-value (:blur value)}] + + [:> numeric-input {:ref basic-offset-x-ref + :on-change (update-attr index :offset-x valid-number?) + :on-click (select-text basic-offset-x-ref) + :default-value (:offset-x value)}] + [:> numeric-input {:ref basic-offset-y-ref + :on-change (update-attr index :offset-y valid-number?) + :on-click (select-text basic-offset-y-ref) + :default-value (:offset-y value)}] + [:> numeric-input {:ref basic-blur-ref + :on-click (select-text basic-blur-ref) + :on-change (update-attr index :blur valid-number?) + :min 0 + :default-value (:blur value)}] [:div.element-set-actions [:div.element-set-actions-button {:on-click (toggle-visibility index)} @@ -129,46 +127,42 @@ [:div.row-grid-2 [:div.input-element - [:input.input-text {:type "number" - :ref adv-offset-x-ref - :no-validate true - :placeholder "--" - :on-click (select-text adv-offset-x-ref) - :on-change (update-attr index :offset-x valid-number? basic-offset-x-ref) - :default-value (:offset-x value)}] + [:> numeric-input {:ref adv-offset-x-ref + :no-validate true + :placeholder "--" + :on-click (select-text adv-offset-x-ref) + :on-change (update-attr index :offset-x valid-number? basic-offset-x-ref) + :default-value (:offset-x value)}] [:span.after (t locale "workspace.options.shadow-options.offsetx")]] [:div.input-element - [:input.input-text {:type "number" - :ref adv-offset-y-ref - :no-validate true - :placeholder "--" - :on-click (select-text adv-offset-y-ref) - :on-change (update-attr index :offset-y valid-number? basic-offset-y-ref) - :default-value (:offset-y value)}] + [:> numeric-input {:ref adv-offset-y-ref + :no-validate true + :placeholder "--" + :on-click (select-text adv-offset-y-ref) + :on-change (update-attr index :offset-y valid-number? basic-offset-y-ref) + :default-value (:offset-y value)}] [:span.after (t locale "workspace.options.shadow-options.offsety")]]] [:div.row-grid-2 [:div.input-element - [:input.input-text {:type "number" - :ref adv-blur-ref - :no-validate true - :placeholder "--" - :on-click (select-text adv-blur-ref) - :on-change (update-attr index :blur valid-number? basic-blur-ref) - :min 0 - :default-value (:blur value)}] + [:> numeric-input {:ref adv-blur-ref + :no-validate true + :placeholder "--" + :on-click (select-text adv-blur-ref) + :on-change (update-attr index :blur valid-number? basic-blur-ref) + :min 0 + :default-value (:blur value)}] [:span.after (t locale "workspace.options.shadow-options.blur")]] [:div.input-element - [:input.input-text {:type "number" - :ref adv-spread-ref - :no-validate true - :placeholder "--" - :on-click (select-text adv-spread-ref) - :on-change (update-attr index :spread valid-number?) - :min 0 - :default-value (:spread value)}] + [:> numeric-input {:ref adv-spread-ref + :no-validate true + :placeholder "--" + :on-click (select-text adv-spread-ref) + :on-change (update-attr index :spread valid-number?) + :min 0 + :default-value (:spread value)}] [:span.after (t locale "workspace.options.shadow-options.spread")]]] [:div.color-row-wrap diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 11057bc296..81cc977a15 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -75,6 +75,11 @@ [node] (.-value node)) +(defn get-attribute + "Extract the value of one attribute of a dom node." + [node attr-name] + (.getAttribute node attr-name)) + (def get-target-val (comp get-value get-target)) (defn click From 8ae6176242393e313f5fd71dd28e8a3d90a90bae Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 13:12:22 +0100 Subject: [PATCH 109/195] :sparkles: Add better default for messages timeout. --- frontend/src/app/main/data/messages.cljs | 13 +++++++------ frontend/src/app/main/ui/viewer/header.cljs | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index 9cce091990..25aeae409c 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -21,7 +21,8 @@ (declare hide) (declare show) -(def +animation-timeout+ 600) +(def default-animation-timeout 600) +(def default-timeout 2000) (s/def ::type #{:success :error :info :warning}) (s/def ::position #{:fixed :floating :inline}) @@ -73,7 +74,7 @@ (watch [_ state stream] (let [stoper (rx/filter (ptk/type? ::show) stream)] (->> (rx/of #(dissoc % :message)) - (rx/delay +animation-timeout+) + (rx/delay default-animation-timeout) (rx/take-until stoper)))))) (defn hide-tag @@ -87,7 +88,7 @@ (defn error ([content] (error content {})) - ([content {:keys [timeout] :or {timeout 3000}}] + ([content {:keys [timeout] :or {timeout default-timeout}}] (show {:content content :type :error :position :fixed @@ -95,7 +96,7 @@ (defn info ([content] (info content {})) - ([content {:keys [timeout] :or {timeout 3000}}] + ([content {:keys [timeout] :or {timeout default-timeout}}] (show {:content content :type :info :position :fixed @@ -103,7 +104,7 @@ (defn success ([content] (success content {})) - ([content {:keys [timeout] :or {timeout 3000}}] + ([content {:keys [timeout] :or {timeout default-timeout}}] (show {:content content :type :success :position :fixed @@ -111,7 +112,7 @@ (defn warn ([content] (warn content {})) - ([content {:keys [timeout] :or {timeout 3000}}] + ([content {:keys [timeout] :or {timeout default-timeout}}] (show {:content content :type :warning :position :fixed diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 058a8df879..fc1df4b094 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -179,6 +179,7 @@ (let [{:keys [project file page frames]} data fullscreen (mf/use-ctx fs/fullscreen-context) + total (count frames) locale (mf/deref i18n/locale) profile (mf/deref refs/profile) From 3db9907c251364a59b4afb481e63aed3575f6326 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 13:50:05 +0100 Subject: [PATCH 110/195] :sparkles: Prevent leave stream broken on spec failed on commit-changes. --- .../src/app/main/data/workspace/common.cljs | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index eb95f2b9ee..f8bc4d4993 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -67,27 +67,34 @@ :as opts}] (us/verify ::cp/changes changes) ;; (us/verify ::cp/changes undo-changes) - (ptk/reify ::commit-changes - cljs.core/IDeref - (-deref [_] changes) - ptk/UpdateEvent - (update [_ state] - (let [state (update-in state [:workspace-file :data] cp/process-changes changes)] - (cond-> state - commit-local? (update :workspace-data cp/process-changes changes)))) + (let [error (volatile! nil)] + (ptk/reify ::commit-changes + cljs.core/IDeref + (-deref [_] changes) - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state)] - (rx/concat - (when (some :page-id changes) - (rx/of (update-indices page-id))) + ptk/UpdateEvent + (update [_ state] + (try + (let [state (update-in state [:workspace-file :data] cp/process-changes changes)] + (cond-> state + commit-local? (update :workspace-data cp/process-changes changes))) + (catch :default e + (vreset! error e) + state))) - (when (and save-undo? (seq undo-changes)) - (let [entry {:undo-changes undo-changes - :redo-changes changes}] - (rx/of (append-undo entry)))))))))) + ptk/WatchEvent + (watch [_ state stream] + (when-not @error + (let [page-id (:current-page-id state)] + (rx/concat + (when (some :page-id changes) + (rx/of (update-indices page-id))) + + (when (and save-undo? (seq undo-changes)) + (let [entry {:undo-changes undo-changes + :redo-changes changes}] + (rx/of (append-undo entry)))))))))))) (defn generate-operations ([ma mb] (generate-operations ma mb false)) From e73a8a2f7e8ab641d21182d13fd59821149aceac Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 13:50:38 +0100 Subject: [PATCH 111/195] :bug: Make the width and height min value to 1px. --- .../ui/workspace/sidebar/options/frame.cljs | 55 +++++++++---------- .../workspace/sidebar/options/measures.cljs | 6 +- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs index 5adaf5c971..90489cee25 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs @@ -20,6 +20,7 @@ [app.main.data.workspace :as udw] [app.main.ui.icons :as i] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.frame-grid :refer [frame-grid]] @@ -51,7 +52,7 @@ (fn [event attr] (let [value (-> (dom/get-target event) (dom/get-value) - (d/parse-integer 0))] + (d/parse-integer 1))] (st/emit! (udw/update-dimensions [(:id shape)] attr value)))) on-proportion-lock-change @@ -104,43 +105,39 @@ i/lock i/unlock)] [:div.input-element.pixels - [:input.input-text {:type "number" - :min "0" - :on-click select-all - :on-change on-width-change - :value (-> (:width shape) - (math/precision 2) - (d/coalesce-str "0"))}]] + [:> numeric-input {:min "1" + :on-click select-all + :on-change on-width-change + :value (-> (:width shape) + (math/precision 2) + (d/coalesce-str "1"))}]] [:div.input-element.pixels - [:input.input-text {:type "number" - :min "0" - :on-click select-all - :on-change on-height-change - :value (-> (:height shape) - (math/precision 2) - (d/coalesce-str "0"))}]]] + [:> numeric-input {:min "1" + :on-click select-all + :on-change on-height-change + :value (-> (:height shape) + (math/precision 2) + (d/coalesce-str "1"))}]]] ;; POSITION [:div.row-flex [:span.element-set-subtitle (tr "workspace.options.position")] [:div.input-element.pixels - [:input.input-text {:placeholder "x" - :type "number" - :on-click select-all - :on-change on-pos-x-change - :value (-> (:x shape) - (math/precision 2) - (d/coalesce-str "0"))}]] + [:> numeric-input {:placeholder "x" + :on-click select-all + :on-change on-pos-x-change + :value (-> (:x shape) + (math/precision 2) + (d/coalesce-str "0"))}]] [:div.input-element.pixels - [:input.input-text {:placeholder "y" - :type "number" - :on-click select-all - :on-change on-pos-y-change - :value (-> (:y shape) - (math/precision 2) - (d/coalesce-str "0"))}]]]]])) + [:> numeric-input {:placeholder "y" + :on-click select-all + :on-change on-pos-y-change + :value (-> (:y shape) + (math/precision 2) + (d/coalesce-str "0"))}]]]]])) (def +size-presets+ [{:name "APPLE"} diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index 4f819819ba..eabf072939 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -60,7 +60,7 @@ (fn [event attr] (let [value (-> (dom/get-target event) (dom/get-value) - (d/parse-integer 0))] + (d/parse-integer 1))] (st/emit! (udw/update-dimensions ids attr value)))) on-proportion-lock-change @@ -120,7 +120,7 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.size")] [:div.input-element.width - [:> numeric-input {:min "0" + [:> numeric-input {:min "1" :no-validate true :placeholder "--" :on-click select-all @@ -128,7 +128,7 @@ :value (attr->string :width values)}]] [:div.input-element.height - [:> numeric-input {:min "0" + [:> numeric-input {:min "1" :no-validate true :placeholder "--" :on-click select-all From 39fb6111609d074285fb65b98fabdc9c2362951e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 14:43:36 +0100 Subject: [PATCH 112/195] :bug: Fix typografy preloading. --- frontend/src/app/main/fonts.clj | 4 ++-- frontend/src/app/main/ui/shapes/text/styles.cljs | 1 + frontend/src/app/main/ui/workspace/shapes/text/editor.cljs | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/fonts.clj b/frontend/src/app/main/fonts.clj index 4c5d35d94c..2688bc7430 100644 --- a/frontend/src/app/main/fonts.clj +++ b/frontend/src/app/main/fonts.clj @@ -18,10 +18,10 @@ [variant] (cond (= "regular" variant) - {:name "regular" :weight "400" :style "normal"} + {:id "regular" :name "regular" :weight "400" :style "normal"} (= "italic" variant) - {:name "italic" :weight "400" :style "italic"} + {:id "italic" :name "italic" :weight "400" :style "italic"} :else (when-let [[a b c] (re-find #"^(\d+)(.*)$" variant)] diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 1dfaef189a..41e2e29e2d 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -103,6 +103,7 @@ (when (and (string? font-id) (pos? (alength font-id))) + (fonts/ensure-loaded! font-id) (let [font (get fontsdb font-id)] (let [font-family (or (:family font) (obj/get data "fontFamily")) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index c1652bffd2..30277d568a 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -20,7 +20,6 @@ [app.util.object :as obj] [app.main.refs :as refs] [app.main.store :as st] - [app.main.fonts :as fonts] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.texts :as dwt] @@ -143,7 +142,7 @@ [props ref] (let [shape (unchecked-get props "shape") node-ref (unchecked-get props "node-ref") - + {:keys [id x y width height content grow-type]} shape zoom (mf/deref refs/selected-zoom) state (mf/use-state #(parse-content content)) From 6f64053dd57899baa7be9ca21739634b30b59b8f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 15:33:20 +0100 Subject: [PATCH 113/195] :sparkles: Discard wrong queued change if back fails. --- frontend/src/app/main/data/workspace/persistence.cljs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 098464d405..57ee632b11 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -125,9 +125,13 @@ (rx/map #(shapes-changes-persisted file-id %)))))) on-error - (fn [error] - (rx/of (update-persistence-status {:status :error - :reason (:type error)})))] + (fn [{:keys [type status] :as error}] + (if (and (= :server-error type) + (= 502 status)) + (rx/of (update-persistence-status {:status :error :reason type})) + (rx/of update-persistence-queue + (update-persistence-status {:status :error :reason type}))))] + (when (= file-id (:id file)) (->> (rp/mutation :update-file params) From f4124b28d85e9eeaaac7330b59f90dd86db11f2e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 15:57:32 +0100 Subject: [PATCH 114/195] :bug: Fix wrong argument number on recursive delete operation (shapes). --- common/app/common/pages.cljc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 971cf92966..26c6e482af 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -807,7 +807,7 @@ (defmethod process-change :del-obj [data {:keys [page-id component-id id ignore-touched] :as change}] - (letfn [(delete-object [objects] + (letfn [(delete-object [objects id] (if-let [target (get objects id)] (let [parent-id (cph/get-parent id objects) frame-id (:frame-id target) @@ -829,8 +829,8 @@ (as-> $ (reduce delete-object $ (:shapes target))))) objects))] (if page-id - (d/update-in-when data [:pages-index page-id :objects] delete-object) - (d/update-in-when data [:components component-id :objects] delete-object)))) + (d/update-in-when data [:pages-index page-id :objects] delete-object id) + (d/update-in-when data [:components component-id :objects] delete-object id)))) (defn rotation-modifiers [center shape angle] From 9ca683026708e59d6518619c7880470cd610671e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Nov 2020 22:11:51 +0100 Subject: [PATCH 115/195] :sparkles: Add export macro helper for properly reexpor vars. --- common/app/common/data.cljc | 20 +++++++++ common/app/common/geom/shapes.cljc | 39 ++++++++---------- frontend/src/app/main/data/workspace.cljs | 50 +++++++++++------------ 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index be573163bd..b61d02c85e 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,10 +7,13 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) + #?(:cljs + (:require-macros [app.common.data])) (:require [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] + #?(:clj [cljs.analyzer.api :as aapi]) #?(:cljs [cljs.reader :as r] :clj [clojure.edn :as r]) #?(:cljs [cljs.core :as core] @@ -281,3 +284,20 @@ valid and the number otherwise." [v] (if (or (not v) (mth/nan? v)) 0 v)) + +(defmacro export + "A helper macro that allows reexport a var in a current namespace." + [v] + (let [sym (symbol (name v)) + mdata (aapi/resolve &env v) + andsym (symbol "&") + arglists (second (get-in mdata [:meta :arglists]))] + (if (pos? (count arglists)) + `(def + ~(with-meta sym (:meta mdata)) + (fn ~@(for [args arglists] + (if (some #(= andsym %) args) + (let [[sargs dargs] (split-with #(not= andsym %) args)] + `([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs)))) + `([~@args] (~v ~@args)))))) + `(def ~(with-meta sym (:meta mdata)) ~v)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index de210cdaa8..10d7f6bb43 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -9,16 +9,16 @@ (ns app.common.geom.shapes (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] + [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.transforms :as gtr] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.path :as gsp] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.transforms :as gtr] [app.common.math :as mth] - [app.common.data :as d])) + [app.common.spec :as us] + [clojure.spec.alpha :as s])) ;; --- Relative Movement @@ -252,22 +252,17 @@ ;; EXPORTS -(defn center-shape [shape] (gco/center-shape shape)) -(defn center-selrect [selrect] (gco/center-selrect selrect)) -(defn center-rect [rect] (gco/center-rect rect)) - -(defn rect->selrect [rect] (gpr/rect->selrect rect)) -(defn rect->points [rect] (gpr/rect->points rect)) -(defn points->selrect [points] (gpr/points->selrect points)) - -(defn transform-shape [shape] (gtr/transform-shape shape)) -(defn transform-matrix - ([shape] (gtr/transform-matrix shape)) - ([shape options] (gtr/transform-matrix shape options))) - -(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) -(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) +(d/export gco/center-shape) +(d/export gco/center-selrect) +(d/export gco/center-rect) +(d/export gpr/rect->selrect) +(d/export gpr/rect->points) +(d/export gpr/points->selrect) +(d/export gtr/transform-shape) +(d/export gtr/transform-matrix) +(d/export gtr/transform-point-center) +(d/export gtr/transform-rect) ;; PATHS -(defn content->points [content] (gsp/content->points content)) -(defn content->selrect [content] (gsp/content->selrect content)) +(d/export gsp/content->points) +(d/export gsp/content->selrect) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index e66eb73d82..f85f2da3d2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1576,38 +1576,36 @@ ;; Transform -(def start-rotate dwt/start-rotate) -(def start-resize dwt/start-resize) -(def start-move-selected dwt/start-move-selected) -(def move-selected dwt/move-selected) - -(def set-rotation dwt/set-rotation) -(def set-modifiers dwt/set-modifiers) -(def apply-modifiers dwt/apply-modifiers) +(d/export dwt/start-rotate) +(d/export dwt/start-resize) +(d/export dwt/start-move-selected) +(d/export dwt/move-selected) +(d/export dwt/set-rotation) +(d/export dwt/set-modifiers) +(d/export dwt/apply-modifiers) ;; Persistence -(def set-file-shared dwp/set-file-shared) -(def fetch-shared-files dwp/fetch-shared-files) -(def link-file-to-library dwp/link-file-to-library) -(def unlink-file-from-library dwp/unlink-file-from-library) -(def upload-media-objects dwp/upload-media-objects) +(d/export dwp/set-file-shared) +(d/export dwp/fetch-shared-files) +(d/export dwp/link-file-to-library) +(d/export dwp/unlink-file-from-library) +(d/export dwp/upload-media-objects) ;; Selection -(def select-shape dws/select-shape) -(def select-all dws/select-all) -(def deselect-all dws/deselect-all) -(def select-shapes dwc/select-shapes) -(def duplicate-selected dws/duplicate-selected) -(def handle-selection dws/handle-selection) -(def select-inside-group dws/select-inside-group) -(def select-for-drawing dwd/select-for-drawing) -(def clear-edition-mode dwc/clear-edition-mode) -(def add-shape dwc/add-shape) -(def start-edition-mode dwc/start-edition-mode) - -(defn start-path-edit [id] (dwdp/start-path-edit id)) +(d/export dws/select-shape) +(d/export dws/select-all) +(d/export dws/deselect-all) +(d/export dwc/select-shapes) +(d/export dws/duplicate-selected) +(d/export dws/handle-selection) +(d/export dws/select-inside-group) +(d/export dwd/select-for-drawing) +(d/export dwc/clear-edition-mode) +(d/export dwc/add-shape) +(d/export dwc/start-edition-mode) +(d/export dwdp/start-path-edit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts From 45da7df4b40bef0e3f9acade59f56c51598e16d1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Dec 2020 11:33:52 +0100 Subject: [PATCH 116/195] Revert ":sparkles: Add export macro helper for properly reexpor vars." This reverts commit 9ca683026708e59d6518619c7880470cd610671e. --- common/app/common/data.cljc | 20 --------- common/app/common/geom/shapes.cljc | 39 ++++++++++-------- frontend/src/app/main/data/workspace.cljs | 50 ++++++++++++----------- 3 files changed, 48 insertions(+), 61 deletions(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index b61d02c85e..be573163bd 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,13 +7,10 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) - #?(:cljs - (:require-macros [app.common.data])) (:require [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] - #?(:clj [cljs.analyzer.api :as aapi]) #?(:cljs [cljs.reader :as r] :clj [clojure.edn :as r]) #?(:cljs [cljs.core :as core] @@ -284,20 +281,3 @@ valid and the number otherwise." [v] (if (or (not v) (mth/nan? v)) 0 v)) - -(defmacro export - "A helper macro that allows reexport a var in a current namespace." - [v] - (let [sym (symbol (name v)) - mdata (aapi/resolve &env v) - andsym (symbol "&") - arglists (second (get-in mdata [:meta :arglists]))] - (if (pos? (count arglists)) - `(def - ~(with-meta sym (:meta mdata)) - (fn ~@(for [args arglists] - (if (some #(= andsym %) args) - (let [[sargs dargs] (split-with #(not= andsym %) args)] - `([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs)))) - `([~@args] (~v ~@args)))))) - `(def ~(with-meta sym (:meta mdata)) ~v)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 10d7f6bb43..de210cdaa8 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -9,16 +9,16 @@ (ns app.common.geom.shapes (:require - [app.common.data :as d] + [clojure.spec.alpha :as s] + [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.path :as gsp] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.transforms :as gtr] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.path :as gsp] [app.common.math :as mth] - [app.common.spec :as us] - [clojure.spec.alpha :as s])) + [app.common.data :as d])) ;; --- Relative Movement @@ -252,17 +252,22 @@ ;; EXPORTS -(d/export gco/center-shape) -(d/export gco/center-selrect) -(d/export gco/center-rect) -(d/export gpr/rect->selrect) -(d/export gpr/rect->points) -(d/export gpr/points->selrect) -(d/export gtr/transform-shape) -(d/export gtr/transform-matrix) -(d/export gtr/transform-point-center) -(d/export gtr/transform-rect) +(defn center-shape [shape] (gco/center-shape shape)) +(defn center-selrect [selrect] (gco/center-selrect selrect)) +(defn center-rect [rect] (gco/center-rect rect)) + +(defn rect->selrect [rect] (gpr/rect->selrect rect)) +(defn rect->points [rect] (gpr/rect->points rect)) +(defn points->selrect [points] (gpr/points->selrect points)) + +(defn transform-shape [shape] (gtr/transform-shape shape)) +(defn transform-matrix + ([shape] (gtr/transform-matrix shape)) + ([shape options] (gtr/transform-matrix shape options))) + +(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) +(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) ;; PATHS -(d/export gsp/content->points) -(d/export gsp/content->selrect) +(defn content->points [content] (gsp/content->points content)) +(defn content->selrect [content] (gsp/content->selrect content)) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f85f2da3d2..e66eb73d82 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1576,36 +1576,38 @@ ;; Transform -(d/export dwt/start-rotate) -(d/export dwt/start-resize) -(d/export dwt/start-move-selected) -(d/export dwt/move-selected) -(d/export dwt/set-rotation) -(d/export dwt/set-modifiers) -(d/export dwt/apply-modifiers) +(def start-rotate dwt/start-rotate) +(def start-resize dwt/start-resize) +(def start-move-selected dwt/start-move-selected) +(def move-selected dwt/move-selected) + +(def set-rotation dwt/set-rotation) +(def set-modifiers dwt/set-modifiers) +(def apply-modifiers dwt/apply-modifiers) ;; Persistence -(d/export dwp/set-file-shared) -(d/export dwp/fetch-shared-files) -(d/export dwp/link-file-to-library) -(d/export dwp/unlink-file-from-library) -(d/export dwp/upload-media-objects) +(def set-file-shared dwp/set-file-shared) +(def fetch-shared-files dwp/fetch-shared-files) +(def link-file-to-library dwp/link-file-to-library) +(def unlink-file-from-library dwp/unlink-file-from-library) +(def upload-media-objects dwp/upload-media-objects) ;; Selection -(d/export dws/select-shape) -(d/export dws/select-all) -(d/export dws/deselect-all) -(d/export dwc/select-shapes) -(d/export dws/duplicate-selected) -(d/export dws/handle-selection) -(d/export dws/select-inside-group) -(d/export dwd/select-for-drawing) -(d/export dwc/clear-edition-mode) -(d/export dwc/add-shape) -(d/export dwc/start-edition-mode) -(d/export dwdp/start-path-edit) +(def select-shape dws/select-shape) +(def select-all dws/select-all) +(def deselect-all dws/deselect-all) +(def select-shapes dwc/select-shapes) +(def duplicate-selected dws/duplicate-selected) +(def handle-selection dws/handle-selection) +(def select-inside-group dws/select-inside-group) +(def select-for-drawing dwd/select-for-drawing) +(def clear-edition-mode dwc/clear-edition-mode) +(def add-shape dwc/add-shape) +(def start-edition-mode dwc/start-edition-mode) + +(defn start-path-edit [id] (dwdp/start-path-edit id)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts From 497c174d638369170fc767d0675562191f0069f9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Dec 2020 12:30:58 +0100 Subject: [PATCH 117/195] :sparkles: Add export macro helper for properly reexport vars. This reverts commit 45da7df4b40bef0e3f9acade59f56c51598e16d1. Now with JVM/Clojure support. --- backend/deps.edn | 1 + common/app/common/data.cljc | 39 ++++++++++++++++++ common/app/common/geom/shapes.cljc | 39 ++++++++---------- frontend/src/app/main/data/workspace.cljs | 50 +++++++++++------------ 4 files changed, 81 insertions(+), 48 deletions(-) diff --git a/backend/deps.edn b/backend/deps.edn index ce2109b503..8afc04fcd2 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -4,6 +4,7 @@ "jcenter" {:url "https://jcenter.bintray.com/"}} :deps {org.clojure/clojure {:mvn/version "1.10.1"} + org.clojure/clojurescript {:mvn/version "1.10.773"} org.clojure/data.json {:mvn/version "1.0.0"} org.clojure/core.async {:mvn/version "1.3.610"} diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index be573163bd..d56e178647 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,10 +7,13 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) + #?(:cljs + (:require-macros [app.common.data])) (:require [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] + #?(:clj [cljs.analyzer.api :as aapi]) #?(:cljs [cljs.reader :as r] :clj [clojure.edn :as r]) #?(:cljs [cljs.core :as core] @@ -281,3 +284,39 @@ valid and the number otherwise." [v] (if (or (not v) (mth/nan? v)) 0 v)) + + +(defmacro export + "A helper macro that allows reexport a var in a current namespace." + [v] + (if (boolean (:ns &env)) + + ;; Code for ClojureScript + (let [mdata (aapi/resolve &env v) + arglists (second (get-in mdata [:meta :arglists])) + sym (symbol (name v)) + andsym (symbol "&")] + (if (pos? (count arglists)) + `(def + ~(with-meta sym (:meta mdata)) + (fn ~@(for [args arglists] + (if (some #(= andsym %) args) + (let [[sargs dargs] (split-with #(not= andsym %) args)] + `([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs)))) + `([~@args] (~v ~@args)))))) + `(def ~(with-meta sym (:meta mdata)) ~v))) + + ;; Code for Clojure + (let [vr (resolve v) + m (meta vr) + n (:name m) + n (with-meta n + (cond-> {} + (:dynamic m) (assoc :dynamic true) + (:protocol m) (assoc :protocol (:protocol m))))] + `(let [m# (meta ~vr)] + (def ~n (deref ~vr)) + (alter-meta! (var ~n) merge (dissoc m# :name)) + ;; (when (:macro m#) + ;; (.setMacro (var ~n))) + ~vr)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index de210cdaa8..10d7f6bb43 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -9,16 +9,16 @@ (ns app.common.geom.shapes (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] + [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.transforms :as gtr] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.path :as gsp] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.transforms :as gtr] [app.common.math :as mth] - [app.common.data :as d])) + [app.common.spec :as us] + [clojure.spec.alpha :as s])) ;; --- Relative Movement @@ -252,22 +252,17 @@ ;; EXPORTS -(defn center-shape [shape] (gco/center-shape shape)) -(defn center-selrect [selrect] (gco/center-selrect selrect)) -(defn center-rect [rect] (gco/center-rect rect)) - -(defn rect->selrect [rect] (gpr/rect->selrect rect)) -(defn rect->points [rect] (gpr/rect->points rect)) -(defn points->selrect [points] (gpr/points->selrect points)) - -(defn transform-shape [shape] (gtr/transform-shape shape)) -(defn transform-matrix - ([shape] (gtr/transform-matrix shape)) - ([shape options] (gtr/transform-matrix shape options))) - -(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) -(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) +(d/export gco/center-shape) +(d/export gco/center-selrect) +(d/export gco/center-rect) +(d/export gpr/rect->selrect) +(d/export gpr/rect->points) +(d/export gpr/points->selrect) +(d/export gtr/transform-shape) +(d/export gtr/transform-matrix) +(d/export gtr/transform-point-center) +(d/export gtr/transform-rect) ;; PATHS -(defn content->points [content] (gsp/content->points content)) -(defn content->selrect [content] (gsp/content->selrect content)) +(d/export gsp/content->points) +(d/export gsp/content->selrect) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index e66eb73d82..f85f2da3d2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1576,38 +1576,36 @@ ;; Transform -(def start-rotate dwt/start-rotate) -(def start-resize dwt/start-resize) -(def start-move-selected dwt/start-move-selected) -(def move-selected dwt/move-selected) - -(def set-rotation dwt/set-rotation) -(def set-modifiers dwt/set-modifiers) -(def apply-modifiers dwt/apply-modifiers) +(d/export dwt/start-rotate) +(d/export dwt/start-resize) +(d/export dwt/start-move-selected) +(d/export dwt/move-selected) +(d/export dwt/set-rotation) +(d/export dwt/set-modifiers) +(d/export dwt/apply-modifiers) ;; Persistence -(def set-file-shared dwp/set-file-shared) -(def fetch-shared-files dwp/fetch-shared-files) -(def link-file-to-library dwp/link-file-to-library) -(def unlink-file-from-library dwp/unlink-file-from-library) -(def upload-media-objects dwp/upload-media-objects) +(d/export dwp/set-file-shared) +(d/export dwp/fetch-shared-files) +(d/export dwp/link-file-to-library) +(d/export dwp/unlink-file-from-library) +(d/export dwp/upload-media-objects) ;; Selection -(def select-shape dws/select-shape) -(def select-all dws/select-all) -(def deselect-all dws/deselect-all) -(def select-shapes dwc/select-shapes) -(def duplicate-selected dws/duplicate-selected) -(def handle-selection dws/handle-selection) -(def select-inside-group dws/select-inside-group) -(def select-for-drawing dwd/select-for-drawing) -(def clear-edition-mode dwc/clear-edition-mode) -(def add-shape dwc/add-shape) -(def start-edition-mode dwc/start-edition-mode) - -(defn start-path-edit [id] (dwdp/start-path-edit id)) +(d/export dws/select-shape) +(d/export dws/select-all) +(d/export dws/deselect-all) +(d/export dwc/select-shapes) +(d/export dws/duplicate-selected) +(d/export dws/handle-selection) +(d/export dws/select-inside-group) +(d/export dwd/select-for-drawing) +(d/export dwc/clear-edition-mode) +(d/export dwc/add-shape) +(d/export dwc/start-edition-mode) +(d/export dwdp/start-path-edit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts From 7ec30d1f5e155c37dcd6f69770a6c185ae2a21ca Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Dec 2020 13:23:37 +0100 Subject: [PATCH 118/195] :sparkles: Temporary revert previous commit. This reverts commit 497c174d638369170fc767d0675562191f0069f9. --- backend/deps.edn | 1 - common/app/common/data.cljc | 39 ------------------ common/app/common/geom/shapes.cljc | 39 ++++++++++-------- frontend/src/app/main/data/workspace.cljs | 50 ++++++++++++----------- 4 files changed, 48 insertions(+), 81 deletions(-) diff --git a/backend/deps.edn b/backend/deps.edn index 8afc04fcd2..ce2109b503 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -4,7 +4,6 @@ "jcenter" {:url "https://jcenter.bintray.com/"}} :deps {org.clojure/clojure {:mvn/version "1.10.1"} - org.clojure/clojurescript {:mvn/version "1.10.773"} org.clojure/data.json {:mvn/version "1.0.0"} org.clojure/core.async {:mvn/version "1.3.610"} diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index d56e178647..be573163bd 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,13 +7,10 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) - #?(:cljs - (:require-macros [app.common.data])) (:require [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] - #?(:clj [cljs.analyzer.api :as aapi]) #?(:cljs [cljs.reader :as r] :clj [clojure.edn :as r]) #?(:cljs [cljs.core :as core] @@ -284,39 +281,3 @@ valid and the number otherwise." [v] (if (or (not v) (mth/nan? v)) 0 v)) - - -(defmacro export - "A helper macro that allows reexport a var in a current namespace." - [v] - (if (boolean (:ns &env)) - - ;; Code for ClojureScript - (let [mdata (aapi/resolve &env v) - arglists (second (get-in mdata [:meta :arglists])) - sym (symbol (name v)) - andsym (symbol "&")] - (if (pos? (count arglists)) - `(def - ~(with-meta sym (:meta mdata)) - (fn ~@(for [args arglists] - (if (some #(= andsym %) args) - (let [[sargs dargs] (split-with #(not= andsym %) args)] - `([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs)))) - `([~@args] (~v ~@args)))))) - `(def ~(with-meta sym (:meta mdata)) ~v))) - - ;; Code for Clojure - (let [vr (resolve v) - m (meta vr) - n (:name m) - n (with-meta n - (cond-> {} - (:dynamic m) (assoc :dynamic true) - (:protocol m) (assoc :protocol (:protocol m))))] - `(let [m# (meta ~vr)] - (def ~n (deref ~vr)) - (alter-meta! (var ~n) merge (dissoc m# :name)) - ;; (when (:macro m#) - ;; (.setMacro (var ~n))) - ~vr)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 10d7f6bb43..de210cdaa8 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -9,16 +9,16 @@ (ns app.common.geom.shapes (:require - [app.common.data :as d] + [clojure.spec.alpha :as s] + [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.path :as gsp] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.transforms :as gtr] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.path :as gsp] [app.common.math :as mth] - [app.common.spec :as us] - [clojure.spec.alpha :as s])) + [app.common.data :as d])) ;; --- Relative Movement @@ -252,17 +252,22 @@ ;; EXPORTS -(d/export gco/center-shape) -(d/export gco/center-selrect) -(d/export gco/center-rect) -(d/export gpr/rect->selrect) -(d/export gpr/rect->points) -(d/export gpr/points->selrect) -(d/export gtr/transform-shape) -(d/export gtr/transform-matrix) -(d/export gtr/transform-point-center) -(d/export gtr/transform-rect) +(defn center-shape [shape] (gco/center-shape shape)) +(defn center-selrect [selrect] (gco/center-selrect selrect)) +(defn center-rect [rect] (gco/center-rect rect)) + +(defn rect->selrect [rect] (gpr/rect->selrect rect)) +(defn rect->points [rect] (gpr/rect->points rect)) +(defn points->selrect [points] (gpr/points->selrect points)) + +(defn transform-shape [shape] (gtr/transform-shape shape)) +(defn transform-matrix + ([shape] (gtr/transform-matrix shape)) + ([shape options] (gtr/transform-matrix shape options))) + +(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) +(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) ;; PATHS -(d/export gsp/content->points) -(d/export gsp/content->selrect) +(defn content->points [content] (gsp/content->points content)) +(defn content->selrect [content] (gsp/content->selrect content)) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f85f2da3d2..e66eb73d82 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1576,36 +1576,38 @@ ;; Transform -(d/export dwt/start-rotate) -(d/export dwt/start-resize) -(d/export dwt/start-move-selected) -(d/export dwt/move-selected) -(d/export dwt/set-rotation) -(d/export dwt/set-modifiers) -(d/export dwt/apply-modifiers) +(def start-rotate dwt/start-rotate) +(def start-resize dwt/start-resize) +(def start-move-selected dwt/start-move-selected) +(def move-selected dwt/move-selected) + +(def set-rotation dwt/set-rotation) +(def set-modifiers dwt/set-modifiers) +(def apply-modifiers dwt/apply-modifiers) ;; Persistence -(d/export dwp/set-file-shared) -(d/export dwp/fetch-shared-files) -(d/export dwp/link-file-to-library) -(d/export dwp/unlink-file-from-library) -(d/export dwp/upload-media-objects) +(def set-file-shared dwp/set-file-shared) +(def fetch-shared-files dwp/fetch-shared-files) +(def link-file-to-library dwp/link-file-to-library) +(def unlink-file-from-library dwp/unlink-file-from-library) +(def upload-media-objects dwp/upload-media-objects) ;; Selection -(d/export dws/select-shape) -(d/export dws/select-all) -(d/export dws/deselect-all) -(d/export dwc/select-shapes) -(d/export dws/duplicate-selected) -(d/export dws/handle-selection) -(d/export dws/select-inside-group) -(d/export dwd/select-for-drawing) -(d/export dwc/clear-edition-mode) -(d/export dwc/add-shape) -(d/export dwc/start-edition-mode) -(d/export dwdp/start-path-edit) +(def select-shape dws/select-shape) +(def select-all dws/select-all) +(def deselect-all dws/deselect-all) +(def select-shapes dwc/select-shapes) +(def duplicate-selected dws/duplicate-selected) +(def handle-selection dws/handle-selection) +(def select-inside-group dws/select-inside-group) +(def select-for-drawing dwd/select-for-drawing) +(def clear-edition-mode dwc/clear-edition-mode) +(def add-shape dwc/add-shape) +(def start-edition-mode dwc/start-edition-mode) + +(defn start-path-edit [id] (dwdp/start-path-edit id)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts From 9260c59afb5dac12f6b31801ef278fe6649a65f1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Dec 2020 13:53:36 +0100 Subject: [PATCH 119/195] :tada: Add improved export macro. This reverts commit 7ec30d1f5e155c37dcd6f69770a6c185ae2a21ca. --- backend/deps.edn | 1 + common/app/common/data.cljc | 41 +++++++++++++++++++ common/app/common/geom/shapes.cljc | 39 ++++++++---------- frontend/src/app/main/data/workspace.cljs | 50 +++++++++++------------ 4 files changed, 83 insertions(+), 48 deletions(-) diff --git a/backend/deps.edn b/backend/deps.edn index ce2109b503..8afc04fcd2 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -4,6 +4,7 @@ "jcenter" {:url "https://jcenter.bintray.com/"}} :deps {org.clojure/clojure {:mvn/version "1.10.1"} + org.clojure/clojurescript {:mvn/version "1.10.773"} org.clojure/data.json {:mvn/version "1.0.0"} org.clojure/core.async {:mvn/version "1.3.610"} diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index be573163bd..51e1f3a5a7 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -7,10 +7,13 @@ (ns app.common.data "Data manipulation and query helper functions." (:refer-clojure :exclude [concat read-string hash-map]) + #?(:cljs + (:require-macros [app.common.data])) (:require [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] + #?(:clj [cljs.analyzer.api :as aapi]) #?(:cljs [cljs.reader :as r] :clj [clojure.edn :as r]) #?(:cljs [cljs.core :as core] @@ -281,3 +284,41 @@ valid and the number otherwise." [v] (if (or (not v) (mth/nan? v)) 0 v)) + + +(defmacro export + "A helper macro that allows reexport a var in a current namespace." + [v] + (if (boolean (:ns &env)) + + ;; Code for ClojureScript + (let [mdata (aapi/resolve &env v) + arglists (second (get-in mdata [:meta :arglists])) + sym (symbol (name v)) + andsym (symbol "&") + procarg #(if (= % andsym) % (gensym "param"))] + (if (pos? (count arglists)) + `(def + ~(with-meta sym (:meta mdata)) + (fn ~@(for [args arglists] + (let [args (map procarg args)] + (if (some #(= andsym %) args) + (let [[sargs dargs] (split-with #(not= andsym %) args)] + `([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs)))) + `([~@args] (~v ~@args))))))) + `(def ~(with-meta sym (:meta mdata)) ~v))) + + ;; Code for Clojure + (let [vr (resolve v) + m (meta vr) + n (:name m) + n (with-meta n + (cond-> {} + (:dynamic m) (assoc :dynamic true) + (:protocol m) (assoc :protocol (:protocol m))))] + `(let [m# (meta ~vr)] + (def ~n (deref ~vr)) + (alter-meta! (var ~n) merge (dissoc m# :name)) + ;; (when (:macro m#) + ;; (.setMacro (var ~n))) + ~vr)))) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index de210cdaa8..10d7f6bb43 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -9,16 +9,16 @@ (ns app.common.geom.shapes (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] + [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.transforms :as gtr] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.path :as gsp] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.transforms :as gtr] [app.common.math :as mth] - [app.common.data :as d])) + [app.common.spec :as us] + [clojure.spec.alpha :as s])) ;; --- Relative Movement @@ -252,22 +252,17 @@ ;; EXPORTS -(defn center-shape [shape] (gco/center-shape shape)) -(defn center-selrect [selrect] (gco/center-selrect selrect)) -(defn center-rect [rect] (gco/center-rect rect)) - -(defn rect->selrect [rect] (gpr/rect->selrect rect)) -(defn rect->points [rect] (gpr/rect->points rect)) -(defn points->selrect [points] (gpr/points->selrect points)) - -(defn transform-shape [shape] (gtr/transform-shape shape)) -(defn transform-matrix - ([shape] (gtr/transform-matrix shape)) - ([shape options] (gtr/transform-matrix shape options))) - -(defn transform-point-center [point center transform] (gtr/transform-point-center point center transform)) -(defn transform-rect [rect mtx] (gtr/transform-rect rect mtx)) +(d/export gco/center-shape) +(d/export gco/center-selrect) +(d/export gco/center-rect) +(d/export gpr/rect->selrect) +(d/export gpr/rect->points) +(d/export gpr/points->selrect) +(d/export gtr/transform-shape) +(d/export gtr/transform-matrix) +(d/export gtr/transform-point-center) +(d/export gtr/transform-rect) ;; PATHS -(defn content->points [content] (gsp/content->points content)) -(defn content->selrect [content] (gsp/content->selrect content)) +(d/export gsp/content->points) +(d/export gsp/content->selrect) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index e66eb73d82..f85f2da3d2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1576,38 +1576,36 @@ ;; Transform -(def start-rotate dwt/start-rotate) -(def start-resize dwt/start-resize) -(def start-move-selected dwt/start-move-selected) -(def move-selected dwt/move-selected) - -(def set-rotation dwt/set-rotation) -(def set-modifiers dwt/set-modifiers) -(def apply-modifiers dwt/apply-modifiers) +(d/export dwt/start-rotate) +(d/export dwt/start-resize) +(d/export dwt/start-move-selected) +(d/export dwt/move-selected) +(d/export dwt/set-rotation) +(d/export dwt/set-modifiers) +(d/export dwt/apply-modifiers) ;; Persistence -(def set-file-shared dwp/set-file-shared) -(def fetch-shared-files dwp/fetch-shared-files) -(def link-file-to-library dwp/link-file-to-library) -(def unlink-file-from-library dwp/unlink-file-from-library) -(def upload-media-objects dwp/upload-media-objects) +(d/export dwp/set-file-shared) +(d/export dwp/fetch-shared-files) +(d/export dwp/link-file-to-library) +(d/export dwp/unlink-file-from-library) +(d/export dwp/upload-media-objects) ;; Selection -(def select-shape dws/select-shape) -(def select-all dws/select-all) -(def deselect-all dws/deselect-all) -(def select-shapes dwc/select-shapes) -(def duplicate-selected dws/duplicate-selected) -(def handle-selection dws/handle-selection) -(def select-inside-group dws/select-inside-group) -(def select-for-drawing dwd/select-for-drawing) -(def clear-edition-mode dwc/clear-edition-mode) -(def add-shape dwc/add-shape) -(def start-edition-mode dwc/start-edition-mode) - -(defn start-path-edit [id] (dwdp/start-path-edit id)) +(d/export dws/select-shape) +(d/export dws/select-all) +(d/export dws/deselect-all) +(d/export dwc/select-shapes) +(d/export dws/duplicate-selected) +(d/export dws/handle-selection) +(d/export dws/select-inside-group) +(d/export dwd/select-for-drawing) +(d/export dwc/clear-edition-mode) +(d/export dwc/add-shape) +(d/export dwc/start-edition-mode) +(d/export dwdp/start-path-edit) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts From 001f90a54009cfa5ec5e6ad823baacf879136342 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 30 Nov 2020 17:59:39 +0100 Subject: [PATCH 120/195] :bug: Safari compatibility fixes --- frontend/resources/styles/common/base.scss | 5 ++ .../main/partials/debug-icons-preview.scss | 1 - frontend/src/app/config.cljs | 44 +++++++++++++++- frontend/src/app/main/data/workspace.cljs | 52 +++++++++++-------- frontend/src/app/main/ui/cursors.clj | 10 ++-- frontend/src/app/main/ui/shapes/text.cljs | 16 +++--- .../src/app/main/ui/shapes/text/styles.cljs | 22 ++++---- .../src/app/main/ui/workspace/selection.cljs | 7 +-- .../app/main/ui/workspace/shapes/text.cljs | 12 +++-- .../main/ui/workspace/shapes/text/editor.cljs | 51 +++++++++++------- .../src/app/main/ui/workspace/viewport.cljs | 16 +++--- frontend/src/app/util/dom.cljs | 3 ++ 12 files changed, 164 insertions(+), 75 deletions(-) diff --git a/frontend/resources/styles/common/base.scss b/frontend/resources/styles/common/base.scss index a9fcacdee2..ddd6237923 100644 --- a/frontend/resources/styles/common/base.scss +++ b/frontend/resources/styles/common/base.scss @@ -224,3 +224,8 @@ input[type=number]::-webkit-inner-spin-button, input[type=number] { -moz-appearance: textfield; } + +[contenteditable] { + -webkit-user-select: text; + user-select: text; +} diff --git a/frontend/resources/styles/main/partials/debug-icons-preview.scss b/frontend/resources/styles/main/partials/debug-icons-preview.scss index 5e56fc0a4e..7a4940eec1 100644 --- a/frontend/resources/styles/main/partials/debug-icons-preview.scss +++ b/frontend/resources/styles/main/partials/debug-icons-preview.scss @@ -1,5 +1,4 @@ .debug-preview { - max-height: 100vh; display: flex; flex-direction: column; overflow: scroll; diff --git a/frontend/src/app/config.cljs b/frontend/src/app/config.cljs index 6281a10f5b..bff44964cb 100644 --- a/frontend/src/app/config.cljs +++ b/frontend/src/app/config.cljs @@ -9,9 +9,41 @@ (ns app.config (:require + [clojure.spec.alpha :as s] + [app.common.spec :as us] [app.util.object :as obj] + [app.util.dom :as dom] [cuerdas.core :as str])) +(s/def ::platform #{:windows :linux :macos :other}) +(s/def ::browser #{:chrome :mozilla :safari :edge :other}) + +(defn parse-browser + [] + (let [user-agent (-> (dom/get-user-agent) str/lower) + check-chrome? (fn [] (str/includes? user-agent "chrom")) + check-firefox? (fn [] (str/includes? user-agent "firefox")) + check-edge? (fn [] (str/includes? user-agent "edg")) + check-safari? (fn [] (str/includes? user-agent "safari"))] + (cond + (check-edge?) :edge + (check-chrome?) :chrome + (check-firefox?) :firefox + (check-safari?) :safari + :else :other))) + +(defn parse-platform + [] + (let [user-agent (-> (dom/get-user-agent) str/lower) + check-windows? (fn [] (str/includes? user-agent "windows")) + check-linux? (fn [] (str/includes? user-agent "linux")) + check-macos? (fn [] (str/includes? user-agent "mac os"))] + (cond + (check-windows?) :windows + (check-linux?) :linux + (check-macos?) :macos + :else :other))) + (this-as global (def default-language "en") (def demo-warning (obj/get global "appDemoWarning" false)) @@ -22,7 +54,17 @@ (def public-uri (or (obj/get global "appPublicURI") (.-origin ^js js/location))) (def media-uri (str public-uri "/media")) - (def default-theme "default")) + (def default-theme "default") + (def browser (parse-browser)) + (def platform (parse-platform))) + +(defn ^boolean check-browser? [candidate] + (us/verify ::browser candidate) + (= candidate browser)) + +(defn ^boolean check-platform? [candidate] + (us/verify ::platform candidate) + (= candidate platform)) (defn resolve-media-path [path] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f85f2da3d2..bd4251ffe7 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1625,45 +1625,53 @@ (deselect-all true)) (rx/empty)))))) +(defn c-mod + "Adds the control/command modifier to a shortcuts depending on the + operating system for the user" + [shortcut] + (if (cfg/check-platform? :macos) + (str "command+" shortcut) + (str "ctrl+" shortcut))) + (def shortcuts - {"ctrl+i" #(st/emit! (toggle-layout-flags :assets)) - "ctrl+l" #(st/emit! (toggle-layout-flags :sitemap :layers)) - "ctrl+shift+r" #(st/emit! (toggle-layout-flags :rules)) - "ctrl+a" #(st/emit! (select-all)) - "ctrl+p" #(st/emit! (toggle-layout-flags :colorpalette)) - "ctrl+'" #(st/emit! (toggle-layout-flags :display-grid)) - "ctrl+shift+'" #(st/emit! (toggle-layout-flags :snap-grid)) + {(c-mod "i") #(st/emit! (toggle-layout-flags :assets)) + (c-mod "l") #(st/emit! (toggle-layout-flags :sitemap :layers)) + (c-mod "shift+r") #(st/emit! (toggle-layout-flags :rules)) + (c-mod "a") #(st/emit! (select-all)) + (c-mod "p") #(st/emit! (toggle-layout-flags :colorpalette)) + (c-mod "'") #(st/emit! (toggle-layout-flags :display-grid)) + (c-mod "shift+'") #(st/emit! (toggle-layout-flags :snap-grid)) "+" #(st/emit! (increase-zoom nil)) "-" #(st/emit! (decrease-zoom nil)) - "ctrl+g" #(st/emit! group-selected) + (c-mod "g") #(st/emit! group-selected) "shift+g" #(st/emit! ungroup-selected) - "ctrl+m" #(st/emit! mask-group) + (c-mod "m") #(st/emit! mask-group) "shift+m" #(st/emit! unmask-group) - "ctrl+k" #(st/emit! dwl/add-component) + (c-mod "k") #(st/emit! dwl/add-component) "shift+0" #(st/emit! reset-zoom) "shift+1" #(st/emit! zoom-to-fit-all) "shift+2" #(st/emit! zoom-to-selected-shape) - "ctrl+d" #(st/emit! duplicate-selected) - "ctrl+z" #(st/emit! dwc/undo) - "ctrl+shift+z" #(st/emit! dwc/redo) - "ctrl+y" #(st/emit! dwc/redo) - "ctrl+q" #(st/emit! dwc/reinitialize-undo) + (c-mod "d") #(st/emit! duplicate-selected) + (c-mod "z") #(st/emit! dwc/undo) + (c-mod "shift+z") #(st/emit! dwc/redo) + (c-mod "y") #(st/emit! dwc/redo) + (c-mod "q") #(st/emit! dwc/reinitialize-undo) "a" #(st/emit! (dwd/select-for-drawing :frame)) "r" #(st/emit! (dwd/select-for-drawing :rect)) "e" #(st/emit! (dwd/select-for-drawing :circle)) "t" #(st/emit! dwtxt/start-edit-if-selected (dwd/select-for-drawing :text)) "p" #(st/emit! (dwd/select-for-drawing :path)) - "ctrl+c" #(st/emit! copy-selected) - "ctrl+v" #(st/emit! paste) - "ctrl+x" #(st/emit! copy-selected delete-selected) + (c-mod "c") #(st/emit! copy-selected) + (c-mod "v") #(st/emit! paste) + (c-mod "x") #(st/emit! copy-selected delete-selected) "escape" #(st/emit! (esc-pressed)) "del" #(st/emit! delete-selected) "backspace" #(st/emit! delete-selected) - "ctrl+up" #(st/emit! (vertical-order-selected :up)) - "ctrl+down" #(st/emit! (vertical-order-selected :down)) - "ctrl+shift+up" #(st/emit! (vertical-order-selected :top)) - "ctrl+shift+down" #(st/emit! (vertical-order-selected :bottom)) + (c-mod "up") #(st/emit! (vertical-order-selected :up)) + (c-mod "down") #(st/emit! (vertical-order-selected :down)) + (c-mod "shift+up") #(st/emit! (vertical-order-selected :top)) + (c-mod "shift+down") #(st/emit! (vertical-order-selected :bottom)) "shift+up" #(st/emit! (dwt/move-selected :up true)) "shift+down" #(st/emit! (dwt/move-selected :down true)) "shift+right" #(st/emit! (dwt/move-selected :right true)) diff --git a/frontend/src/app/main/ui/cursors.clj b/frontend/src/app/main/ui/cursors.clj index e816aed0f4..5360356e22 100644 --- a/frontend/src/app/main/ui/cursors.clj +++ b/frontend/src/app/main/ui/cursors.clj @@ -55,10 +55,14 @@ (defn encode-svg-cursor [id rotation x y height] (let [svg-path (str cursor-folder "/" (name id) ".svg") - data (-> svg-path io/resource slurp parse-svg uri/percent-encode) - transform (if rotation (str " transform='rotate(" rotation ")'") "")] + data (-> svg-path io/resource slurp parse-svg) + data (uri/percent-encode data) + + data (if rotation + (str/fmt "%3Cg transform='rotate(%s 8,8)'%3E%s%3C/g%3E" rotation data) + data)] (str "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' " - "height='" height "px' " transform "%3E" data "%3C/svg%3E\") " x " " y ", auto"))) + "height='" height "px' %3E" data "%3C/svg%3E\") " x " " y ", auto"))) (defmacro cursor-ref "Creates a static cursor given its name, rotation and x/y hotspot" diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 2d36fe781c..266dc66015 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -26,7 +26,7 @@ [{:keys [node index shape] :as props}] (let [embed-resources? (mf/use-ctx muc/embed-ctx) {:keys [type text children]} node - + props #js {:shape shape} render-node (fn [index node] (mf/element text-node {:index index @@ -35,29 +35,31 @@ :shape shape}))] (if (string? text) - (let [style (sts/generate-text-styles (clj->js node))] - [:span.text-node {:style style} (if (= text "") "\u00A0" text)]) + (let [style (sts/generate-text-styles (clj->js node) props)] + [:span {:style style + :className (when (:fill-color-gradient node) "gradient")} + (if (= text "") "\u00A0" text)]) (let [children (map-indexed render-node children)] (case type "root" - (let [style (sts/generate-root-styles (clj->js node) #js {:shape shape})] + (let [style (sts/generate-root-styles (clj->js node) props)] [:div.root.rich-text {:key index :style style :xmlns "http://www.w3.org/1999/xhtml"} [:* - [:style ".text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] + [:style ".gradient { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] (when embed-resources? [ste/embed-fontfaces-style {:node node}])] children]) "paragraph-set" - (let [style (sts/generate-paragraph-set-styles (clj->js node))] + (let [style (sts/generate-paragraph-set-styles (clj->js node) props)] [:div.paragraph-set {:key index :style style} children]) "paragraph" - (let [style (sts/generate-paragraph-styles (clj->js node))] + (let [style (sts/generate-paragraph-styles (clj->js node) props)] [:p.paragraph {:key index :style style} children]) nil))))) diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 41e2e29e2d..02926dc781 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -35,27 +35,29 @@ (= talign "justify") (obj/set! "justifyContent" "stretch")))) (defn generate-paragraph-set-styles - [data] + [data props] ;; The position absolute is used so the paragraph is "outside" ;; the normal layout and can grow outside its parent ;; We use this element to measure the size of the text - (let [base #js {:display "inline-block" - :position "absolute"}] + (let [base #js {:display "inline-block"}] base)) (defn generate-paragraph-styles - [data] - (let [base #js {:fontSize "14px" + [data props] + (let [shape (obj/get props "shape") + grow-type (:grow-type shape) + base #js {:fontSize "14px" :margin "inherit" :lineHeight "1.2"} lh (obj/get data "line-height") ta (obj/get data "text-align")] (cond-> base ta (obj/set! "textAlign" ta) - lh (obj/set! "lineHeight" lh)))) + lh (obj/set! "lineHeight" lh) + (= grow-type :auto-width) (obj/set! "whiteSpace" "pre")))) (defn generate-text-styles - [data] + [data props] (let [letter-spacing (obj/get data "letter-spacing") text-decoration (obj/get data "text-decoration") text-transform (obj/get data "text-transform") @@ -82,7 +84,7 @@ fill-color-ref-file (obj/get data "fill-color-ref-file") [r g b a] (uc/hex->rgba fill-color fill-opacity) - background (if fill-color-gradient + text-color (if fill-color-gradient (uc/gradient->css (js->clj fill-color-gradient)) (str/format "rgba(%s, %s, %s, %s)" r g b a)) @@ -91,7 +93,8 @@ base #js {:textDecoration text-decoration :textTransform text-transform :lineHeight (or line-height "inherit") - "--text-color" background}] + :color text-color + "--text-color" text-color}] (when (and (string? letter-spacing) (pos? (alength letter-spacing))) @@ -117,4 +120,5 @@ (obj/set! base "fontStyle" font-style) (obj/set! base "fontWeight" font-weight)))) + base)) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index f14e5d9564..4d53b68027 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -156,10 +156,11 @@ (let [res-point (if (#{:top :bottom} position) {:y y} {:x x}) - width length #_(max 0 (- length (/ (* resize-point-rect-size 2) zoom))) + target-length (max 0 (- length (/ (* resize-point-rect-size 2) zoom))) + width (if (< target-length 6) length target-length) height (/ resize-side-height zoom)] - [:rect {:x x - :y (- y (/ resize-side-height 2 zoom)) + [:rect {:x (+ x (/ (- length width) 2)) + :y (- y (/ height 2)) :width width :height height :transform (gmt/multiply transform diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 895de130e8..ea30d02821 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -115,11 +115,13 @@ (resize-observer shape text-node ".paragraph-set") [:> shape-container {:shape shape} - [:& text/text-shape {:key "text-shape" - :ref text-ref - :shape shape - :selected? selected? - :style {:display (when edition? "none")}}] + ;; We keep hidden the shape when we're editing so it keeps track of the size + ;; and updates the selrect acordingly + [:g.text-shape {:opacity (when edition? 0)} + [:& text/text-shape {:key "text-shape" + :ref text-ref + :shape shape + :selected? selected?}]] (when edition? [:& editor/text-shape-edit {:key "editor" :shape shape}]) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 30277d568a..0e55d242c3 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -82,7 +82,7 @@ data (obj/get props "element") type (obj/get data "type") shape (obj/get props "shape") - style (sts/generate-paragraph-set-styles data) + style (sts/generate-paragraph-set-styles data props) attrs (-> (obj/get props "attributes") (obj/set! "style" style) (obj/set! "className" type))] @@ -95,7 +95,7 @@ childs (obj/get props "children") data (obj/get props "element") type (obj/get data "type") - style (sts/generate-paragraph-styles data) + style (sts/generate-paragraph-styles data props) attrs (-> (obj/get props "attributes") (obj/set! "style" style) (obj/set! "className" type))] @@ -106,10 +106,14 @@ [props] (let [childs (obj/get props "children") data (obj/get props "leaf") - style (sts/generate-text-styles data) + type (obj/get data "type") + style (sts/generate-text-styles data props) attrs (-> (obj/get props "attributes") - (obj/set! "style" style) - (obj/set! "className" "text-node"))] + (obj/set! "style" style)) + gradient (obj/get data "fill-color-gradient" nil)] + (if gradient + (obj/set! attrs "className" (str type " gradient")) + (obj/set! attrs "className" type)) [:> :span attrs childs])) (defn- render-element @@ -135,7 +139,7 @@ ;; --- Text Shape Edit -(mf/defc text-shape-edit +(mf/defc text-shape-edit-html {::mf/wrap [mf/memo] ::mf/wrap-props false ::mf/forward-ref true} @@ -161,9 +165,6 @@ on-click-outside (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - (let [sidebar (dom/get-element "settings-bar") assets (dom/get-element-by-class "assets-bar") cpicker (dom/get-element-by-class "colorpicker-tooltip") @@ -174,9 +175,13 @@ (and assets (.contains assets target)) (and self (.contains self target)) (and cpicker (.contains cpicker target))) - (if selecting? - (mf/set-ref-val! selecting-ref false) - (on-close))))) + (do + (dom/prevent-default event) + (dom/stop-propagation event) + + (if selecting? + (mf/set-ref-val! selecting-ref false) + (on-close)))))) on-mouse-down (fn [event] @@ -230,13 +235,9 @@ (reset! state (parse-content content)) (reset! content-var content))) - [:foreignObject {:ref self-ref - :transform (gsh/transform-matrix shape) - :x x :y y - :width (if (#{:auto-width} grow-type) 10000 width) - :height (if (#{:auto-height :auto-width} grow-type) 10000 height)} + [:div.text-editor {:ref self-ref} [:style "span { line-height: inherit; } - .text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] + .gradient { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"] [:> rslate/Slate {:editor editor :value @state :on-change on-change} @@ -257,3 +258,17 @@ ;; WARN: monky patch (obj/set! slate/Transforms "deselect" (constantly nil))) :placeholder (when (= :fixed grow-type) "Type some text here...")}]]])) + +(mf/defc text-shape-edit + {::mf/wrap [mf/memo] + ::mf/wrap-props false + ::mf/forward-ref true} + [props ref] + (let [shape (unchecked-get props "shape") + {:keys [x y width height grow-type]} shape] + [:foreignObject {:transform (gsh/transform-matrix shape) + :x x :y y + :width (if (#{:auto-width} grow-type) 10000 width) + :height (if (#{:auto-height :auto-width} grow-type) 10000 height)} + + [:& text-shape-edit-html {:shape shape}]])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 20d384a60e..adbb0b0534 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -116,8 +116,7 @@ (st/emit! dw/start-pan) (rx/subscribe stream (fn [delta] - (let [vbox (.. ^js node -viewBox -baseVal) - zoom (gpt/point @refs/selected-zoom) + (let [zoom (gpt/point @refs/selected-zoom) delta (gpt/divide delta zoom)] (st/emit! (dw/update-viewport-position {:x #(- % (:x delta)) @@ -352,10 +351,15 @@ on-mouse-move (fn [event] (let [event (.getBrowserEvent ^js event) - pt (dom/get-client-position ^js event) - pt (translate-point-to-viewport pt) - delta (gpt/point (.-movementX ^js event) - (.-movementY ^js event))] + raw-pt (dom/get-client-position ^js event) + pt (translate-point-to-viewport raw-pt) + + ;; We calculate the delta because Safari's MouseEvent.movementX/Y drop + ;; events + delta (if @last-position + (gpt/subtract raw-pt @last-position) + (gpt/point 0 0))] + (reset! last-position raw-pt) (st/emit! (ms/->PointerEvent :delta delta (kbd/ctrl? event) (kbd/shift? event) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 81cc977a15..2095bae52b 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -245,3 +245,6 @@ (defn ^boolean class? [node class-name] (let [class-list (.-classList ^js node)] (.contains ^js class-list class-name))) + +(defn get-user-agent [] + (.-userAgent js/navigator)) From b180d9e878ef4380c3f5005bd4694773190efaef Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 1 Dec 2020 14:58:19 +0100 Subject: [PATCH 121/195] :bug: Fixed persistent outline after editing --- frontend/src/app/main/data/workspace/common.cljs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index f8bc4d4993..7b42338ff5 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -511,7 +511,10 @@ (ptk/reify ::clear-edition-mode ptk/UpdateEvent (update [_ state] - (update state :workspace-local dissoc :edition)))) + (let [id (get-in state [:workspace-local :edition])] + (-> state + (update-in [:workspace-local :hover] disj id) + (update :workspace-local dissoc :edition)))))) (defn add-shape From f37a85fd82fab6d8c768e22b4ac8fddb3c3f240b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 1 Dec 2020 17:27:19 +0100 Subject: [PATCH 122/195] :sparkles: Fixes tests and linter for commons --- backend/tests/app/tests/helpers.clj | 9 +- backend/tests/app/tests/test_emails.clj | 6 +- .../tests/app/tests/test_services_media.clj | 12 +-- .../tests/app/tests/test_services_profile.clj | 2 +- .../tests/app/tests/test_services_viewer.clj | 7 +- common/app/common/data.cljc | 7 +- common/app/common/exceptions.cljc | 2 +- common/app/common/geom/matrix.cljc | 11 ++- common/app/common/geom/point.cljc | 3 +- common/app/common/geom/proportions.cljc | 12 +-- common/app/common/geom/shapes.cljc | 18 ++-- common/app/common/geom/shapes/common.cljc | 6 +- common/app/common/geom/shapes/path.cljc | 5 +- common/app/common/geom/shapes/rect.cljc | 7 +- common/app/common/geom/shapes/transforms.cljc | 84 +++++++++---------- common/app/common/pages.cljc | 73 ++++++++-------- common/app/common/pages_helpers.cljc | 13 ++- common/app/common/pages_migrations.cljc | 12 ++- common/app/common/spec.cljc | 3 - docs/06-Testing-Guide.md | 39 +++++++++ .../main/data/workspace/drawing/curve.cljs | 17 +++- .../src/app/main/ui/workspace/drawarea.cljs | 6 +- .../src/app/main/ui/workspace/viewport.cljs | 1 + 23 files changed, 187 insertions(+), 168 deletions(-) create mode 100644 docs/06-Testing-Guide.md diff --git a/backend/tests/app/tests/helpers.clj b/backend/tests/app/tests/helpers.clj index c99294344f..2ae597a029 100644 --- a/backend/tests/app/tests/helpers.clj +++ b/backend/tests/app/tests/helpers.clj @@ -36,9 +36,9 @@ [] (doto (PGSimpleDataSource.) (.setServerName "postgres") - (.setDatabaseName "uxbox_test") - (.setUser "uxbox") - (.setPassword "uxbox"))) + (.setDatabaseName "penpot_test") + (.setUser "penpot") + (.setPassword "penpot"))) (defn state-init [next] @@ -91,7 +91,8 @@ (let [params {:id (mk-uuid "profile" i) :fullname (str "Profile " i) :email (str "profile" i ".test@nodomain.com") - :password "123123"}] + :password "123123" + :demo? true}] (->> (#'profile/create-profile conn params) (#'profile/create-profile-relations conn)))) diff --git a/backend/tests/app/tests/test_emails.clj b/backend/tests/app/tests/test_emails.clj index a4c318f412..c06315deb3 100644 --- a/backend/tests/app/tests/test_emails.clj +++ b/backend/tests/app/tests/test_emails.clj @@ -23,10 +23,10 @@ (let [result (emails/render emails/register {:to "example@app.io" :name "foo"})] (t/is (map? result)) (t/is (contains? result :subject)) - (t/is (contains? result :content)) + (t/is (contains? result :body)) (t/is (contains? result :to)) - (t/is (contains? result :reply-to)) - (t/is (vector? (:content result))))) + #_(t/is (contains? result :reply-to)) + (t/is (vector? (:body result))))) ;; (t/deftest email-sending-and-sendmail-job ;; (let [res @(emails/send! emails/register {:to "example@app.io" :name "foo"})] diff --git a/backend/tests/app/tests/test_services_media.clj b/backend/tests/app/tests/test_services_media.clj index 2680b6379c..8b56c48e21 100644 --- a/backend/tests/app/tests/test_services_media.clj +++ b/backend/tests/app/tests/test_services_media.clj @@ -78,13 +78,13 @@ (t/is (string? (get-in out [:result :path]))) (t/is (string? (get-in out [:result :thumb-path]))))) - (t/testing "list media objects by file" + #_(t/testing "list media objects by file" (let [data {::sq/type :media-objects :profile-id (:id prof) :file-id (:id file) :is-local true} out (th/try-on! (sq/handle data))] - ;; (th/print-result! out) + (th/print-result! out) ;; Result is ordered by creation date descendent (t/is (= object-id-2 (get-in out [:result 0 :id]))) @@ -96,7 +96,7 @@ (t/is (string? (get-in out [:result 0 :path]))) (t/is (string? (get-in out [:result 0 :thumb-path]))))) - (t/testing "single media object" + #_(t/testing "single media object" (let [data {::sq/type :media-object :profile-id (:id prof) :id object-id-2} @@ -111,7 +111,7 @@ (t/is (string? (get-in out [:result :path]))))) - (t/testing "delete media objects" + #_(t/testing "delete media objects" (let [data {::sm/type :delete-media-object :profile-id (:id prof) :id object-id-1} @@ -121,7 +121,7 @@ (t/is (nil? (:error out))) (t/is (nil? (:result out))))) - (t/testing "query media object after delete" + #_(t/testing "query media object after delete" (let [data {::sq/type :media-object :profile-id (:id prof) :id object-id-1} @@ -136,7 +136,7 @@ (t/is (th/ex-info? error)) (t/is (th/ex-of-type? error :not-found))))) - (t/testing "query media objects after delete" + #_(t/testing "query media objects after delete" (let [data {::sq/type :media-objects :profile-id (:id prof) :file-id (:id file) diff --git a/backend/tests/app/tests/test_services_profile.clj b/backend/tests/app/tests/test_services_profile.clj index 6bae6de63b..57e309b679 100644 --- a/backend/tests/app/tests/test_services_profile.clj +++ b/backend/tests/app/tests/test_services_profile.clj @@ -40,7 +40,7 @@ (let [error (ex-cause (:error out))] (t/is (th/ex-info? error)) (t/is (th/ex-of-type? error :validation)) - (t/is (th/ex-of-code? error :app.services.mutations.profile/wrong-credentials))))) + (t/is (th/ex-of-code? error :wrong-credentials))))) (t/testing "success" (let [event {::sm/type :login diff --git a/backend/tests/app/tests/test_services_viewer.clj b/backend/tests/app/tests/test_services_viewer.clj index c3b16938f4..c4544475ed 100644 --- a/backend/tests/app/tests/test_services_viewer.clj +++ b/backend/tests/app/tests/test_services_viewer.clj @@ -78,12 +78,13 @@ (let [error (ex-cause (:error out)) error-data (ex-data error)] (t/is (th/ex-info? error)) - (t/is (= (:type error-data) :not-found))))) + (t/is (= (:type error-data) :validation)) + (t/is (= (:code error-data) :not-authorized))))) (t/testing "authenticated with token & profile" (let [data {::sq/type :viewer-bundle :profile-id (:id prof2) - :share-token @token + :token @token :file-id (:id file) :page-id (get-in file [:data :pages 0])} out (th/try-on! (sq/handle data))] @@ -97,7 +98,7 @@ (t/testing "authenticated with token" (let [data {::sq/type :viewer-bundle - :share-token @token + :token @token :file-id (:id file) :page-id (get-in file [:data :pages 0])} out (th/try-on! (sq/handle data))] diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index 51e1f3a5a7..5cde2320a2 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -10,7 +10,6 @@ #?(:cljs (:require-macros [app.common.data])) (:require - [clojure.set :as set] [linked.set :as lks] [app.common.math :as mth] #?(:clj [cljs.analyzer.api :as aapi]) @@ -40,7 +39,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn dissoc-in - [m [k & ks :as keys]] + [m [k & ks]] (if ks (if-let [nextmap (get m k)] (let [newmap (dissoc-in nextmap ks)] @@ -224,7 +223,7 @@ #?(:cljs (js/parseInt v 10) :clj (try (Integer/parseInt v) - (catch Throwable e + (catch Throwable _ nil)))) (defn- impl-parse-double @@ -232,7 +231,7 @@ #?(:cljs (js/parseFloat v) :clj (try (Double/parseDouble v) - (catch Throwable e + (catch Throwable _ nil)))) (defn parse-integer diff --git a/common/app/common/exceptions.cljc b/common/app/common/exceptions.cljc index 2abd014260..8f74d09225 100644 --- a/common/app/common/exceptions.cljc +++ b/common/app/common/exceptions.cljc @@ -22,7 +22,7 @@ ::cause])) (defn error - [& {:keys [type code message hint cause] :as params}] + [& {:keys [message hint cause] :as params}] (s/assert ::error-params params) (let [message (or message hint "") payload (dissoc params :cause)] diff --git a/common/app/common/geom/matrix.cljc b/common/app/common/geom/matrix.cljc index 185197f168..737acc78c3 100644 --- a/common/app/common/geom/matrix.cljc +++ b/common/app/common/geom/matrix.cljc @@ -9,7 +9,6 @@ (ns app.common.geom.matrix (:require - [cuerdas.core :as str] [app.common.math :as mth] [app.common.geom.point :as gpt])) @@ -21,8 +20,8 @@ (str "matrix(" a "," b "," c "," d "," e "," f ")"))) (defn multiply - ([{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f :as m1} - {m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f :as m2}] + ([{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f} + {m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f}] (Matrix. (+ (* m1a m2a) (* m1c m2b)) (+ (* m1b m2a) (* m1d m2b)) @@ -34,8 +33,8 @@ (reduce multiply (multiply m1 m2) others))) (defn substract - [{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f :as m1} - {m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f :as m2}] + [{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f} + {m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f}] (Matrix. (- m1a m2a) (- m1b m2b) (- m1c m2c) (- m1d m2d) (- m1e m2e) (- m1f m2f))) @@ -88,7 +87,7 @@ (defn skew-matrix ([angle-x angle-y point] (multiply (translate-matrix point) - (skew-matrix angle-y angle-y) + (skew-matrix angle-x angle-y) (translate-matrix (gpt/negate point)))) ([angle-x angle-y] (let [m1 (mth/tan (mth/radians angle-x)) diff --git a/common/app/common/geom/point.cljc b/common/app/common/geom/point.cljc index ef0139f211..7fd2fe621e 100644 --- a/common/app/common/geom/point.cljc +++ b/common/app/common/geom/point.cljc @@ -12,7 +12,6 @@ (:require #?(:cljs [cljs.core :as c] :clj [clojure.core :as c]) - [cuerdas.core :as str] [app.common.math :as mth])) ;; --- Point Impl @@ -196,7 +195,7 @@ (defn transform "Transform a point applying a matrix transfomation." - [{:keys [x y] :as p} {:keys [a b c d e f] :as m}] + [{:keys [x y] :as p} {:keys [a b c d e f]}] (assert (point? p)) (Point. (+ (* x a) (* y c) e) (+ (* x b) (* y d) f))) diff --git a/common/app/common/geom/proportions.cljc b/common/app/common/geom/proportions.cljc index e70a9b3b5f..8fe1bf7635 100644 --- a/common/app/common/geom/proportions.cljc +++ b/common/app/common/geom/proportions.cljc @@ -7,17 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.common.geom.proportions - (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.geom.shapes.common :as gco] - [app.common.geom.shapes.transforms :as gtr] - [app.common.geom.shapes.rect :as gpr] - [app.common.math :as mth] - [app.common.data :as d])) +(ns app.common.geom.proportions) ;; --- Proportions diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 10d7f6bb43..4f633ed60f 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -16,9 +16,7 @@ [app.common.geom.shapes.path :as gsp] [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.transforms :as gtr] - [app.common.math :as mth] - [app.common.spec :as us] - [clojure.spec.alpha :as s])) + [app.common.spec :as us])) ;; --- Relative Movement @@ -104,7 +102,7 @@ :selrect selrect))) (defn- setup-image - [{:keys [metadata] :as shape} {:keys [x y width height] :as props}] + [{:keys [metadata] :as shape} props] (-> (setup-rect shape props) (assoc :proportion (/ (:width metadata) @@ -131,11 +129,11 @@ (gpr/join-selrects))) (defn translate-to-frame - [shape {:keys [x y] :as frame}] + [shape {:keys [x y]}] (move shape (gpt/point (- x) (- y)))) (defn translate-from-frame - [shape {:keys [x y] :as frame}] + [shape {:keys [x y]}] (move shape (gpt/point x y))) ;; --- Helpers @@ -205,10 +203,8 @@ (fn [x1 y1 x2 y2] {:x1 x1 :y1 y1 :x2 x2 :y2 y2 :x x1 :y y1 :width (- x2 x1) :height (- y2 y1) :type :rect}) - {frame-x1 :x1 frame-x2 :x2 frame-y1 :y1 frame-y2 :y2 - frame-width :width frame-height :height} bounds - {sr-x1 :x1 sr-x2 :x2 sr-y1 :y1 sr-y2 :y2 - sr-width :width sr-height :height} selrect] + {frame-x1 :x1 frame-x2 :x2 frame-y1 :y1 frame-y2 :y2} bounds + {sr-x1 :x1 sr-x2 :x2 sr-y1 :y1 sr-y2 :y2} selrect] {:left (make-selrect frame-x1 sr-y1 sr-x1 sr-y2) :top (make-selrect sr-x1 frame-y1 sr-x2 sr-y1) :right (make-selrect sr-x2 sr-y1 frame-x2 sr-y2) @@ -243,7 +239,7 @@ (and (>= s1c2 s2c1) (<= s1c2 s2c2))))) -(defn setup-selrect [{:keys [x y width height] :as shape}] +(defn setup-selrect [shape] (let [selrect (gpr/rect->selrect shape) points (gpr/rect->points shape)] (-> shape diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index 75ea7df5a3..49abc5943d 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -9,12 +9,8 @@ (ns app.common.geom.shapes.common (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] - [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.math :as mth] - [app.common.data :as d])) + [app.common.math :as mth])) (defn center-rect [{:keys [x y width height]}] diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index d62b8df08d..e2fa26bc81 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -9,9 +9,6 @@ (ns app.common.geom.shapes.path (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] - [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.rect :as gpr] [app.common.math :as mth] @@ -136,7 +133,7 @@ py (:y tr-point)))) transform-params - (fn [{:keys [x y c1x c1y c2x c2y] :as params}] + (fn [{:keys [x c1x c2x] :as params}] (cond-> params (not (nil? x)) (set-tr :x :y) (not (nil? c1x)) (set-tr :c1x :c1y) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index 330a54a8b4..b748492da6 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -9,13 +9,8 @@ (ns app.common.geom.shapes.rect (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] - [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes.common :as gco] - [app.common.math :as mth] - [app.common.data :as d])) + [app.common.geom.shapes.common :as gco])) (defn rect->points [{:keys [x y width height]}] [(gpt/point x y) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index b5bc71beea..6248131a72 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -9,21 +9,18 @@ (ns app.common.geom.shapes.transforms (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.path :as gpa] [app.common.geom.shapes.rect :as gpr] - [app.common.math :as mth] - [app.common.data :as d])) + [app.common.math :as mth])) (defn transform-matrix "Returns a transformation matrix without changing the shape properties. The result should be used in a `transform` attribute in svg" ([shape] (transform-matrix shape nil)) - ([{:keys [x y flip-x flip-y] :as shape} {:keys [no-flip]}] + ([{:keys [flip-x flip-y] :as shape} {:keys [no-flip]}] (let [shape-center (or (gco/center-shape shape) (gpt/point 0 0))] (-> (gmt/matrix) @@ -59,7 +56,7 @@ (defn transform-rect "Transform a rectangles and changes its attributes" - [{:keys [x y width height] :as rect} matrix] + [rect matrix] (let [points (-> (gpr/rect->points rect) (transform-points matrix))] @@ -74,54 +71,51 @@ :else scale)) (defn modifiers->transform - ([center modifiers] - (modifiers->transform (gmt/matrix) center modifiers)) + [center modifiers] + (let [ds-modifier (:displacement modifiers (gmt/matrix)) + {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) - ([current-transform center modifiers] - (let [ds-modifier (:displacement modifiers (gmt/matrix)) - {res-x :x res-y :y} (:resize-vector modifiers (gpt/point 1 1)) + ;; Normalize x/y vector coordinates because scale by 0 is infinite + res-x (normalize-scale res-x) + res-y (normalize-scale res-y) + resize (gpt/point res-x res-y) - ;; Normalize x/y vector coordinates because scale by 0 is infinite - res-x (normalize-scale res-x) - res-y (normalize-scale res-y) - resize (gpt/point res-x res-y) + origin (:resize-origin modifiers (gpt/point 0 0)) - origin (:resize-origin modifiers (gpt/point 0 0)) + resize-transform (:resize-transform modifiers (gmt/matrix)) + resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) + rt-modif (or (:rotation modifiers) 0) - resize-transform (:resize-transform modifiers (gmt/matrix)) - resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) - rt-modif (or (:rotation modifiers) 0) + center (gpt/transform center ds-modifier) - center (gpt/transform center ds-modifier) + transform (-> (gmt/matrix) - transform (-> (gmt/matrix) + ;; Applies the current resize transformation + (gmt/translate origin) + (gmt/multiply resize-transform) + (gmt/scale resize) + (gmt/multiply resize-transform-inverse) + (gmt/translate (gpt/negate origin)) - ;; Applies the current resize transformation - (gmt/translate origin) - (gmt/multiply resize-transform) - (gmt/scale resize) - (gmt/multiply resize-transform-inverse) - (gmt/translate (gpt/negate origin)) + ;; Applies the stacked transformations + (gmt/translate center) + (gmt/multiply (gmt/rotate-matrix rt-modif)) + (gmt/translate (gpt/negate center)) - ;; Applies the stacked transformations - (gmt/translate center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - (gmt/translate (gpt/negate center)) - - ;; Displacement - (gmt/multiply ds-modifier))] - transform))) + ;; Displacement + (gmt/multiply ds-modifier))] + transform)) (defn- calculate-skew-angle "Calculates the skew angle of the paralelogram given by the points" - [[p1 p2 p3 p4]] + [[p1 _ p3 p4]] (let [v1 (gpt/to-vec p3 p4) v2 (gpt/to-vec p4 p1)] (- 90 (gpt/angle-with-other v1 v2)))) (defn- calculate-height "Calculates the height of a paralelogram given by the points" - [[p1 p2 p3 p4]] + [[p1 _ p3 p4]] (let [v1 (gpt/to-vec p3 p4) v2 (gpt/to-vec p4 p1) angle (gpt/angle-with-other v1 v2)] @@ -146,7 +140,7 @@ (* rot-sign rot-angle))) (defn- calculate-dimensions - [[p1 p2 p3 p4]] + [[p1 p2 p3 _]] (let [width (gpt/distance p1 p2) height (gpt/distance p2 p3)] {:width width :height height})) @@ -199,13 +193,16 @@ (let [content (gpa/transform-content (:content shape) transform) selrect (gpa/content->selrect content) points (gpr/rect->points selrect) - rotation (mod (+ (:rotation shape 0) - (or (get-in shape [:modifiers :rotation]) 0)) - 360)] + ;;rotation (mod (+ (:rotation shape 0) + ;; (or (get-in shape [:modifiers :rotation]) 0)) + ;; 360) + ] (assoc shape :content content :points points - :selrect selrect))) + :selrect selrect + ;;:rotation rotation + ))) (defn apply-transform-rect "Given a new set of points transformed, set up the rectangle so it keeps @@ -217,7 +214,6 @@ ;; Reverse the current transformation stack to get the base rectangle tr-inverse (:transform-inverse shape (gmt/matrix)) - modifiers (:modifiers shape) points-temp (transform-points points center tr-inverse) points-temp-dim (calculate-dimensions points-temp) @@ -260,7 +256,7 @@ (defn transform-shape [shape] (let [center (gco/center-shape shape)] (if (and (:modifiers shape) center) - (let [transform (modifiers->transform (:transform shape (gmt/matrix)) center (:modifiers shape))] + (let [transform (modifiers->transform center (:modifiers shape))] (-> shape (set-flip (:modifiers shape)) (apply-transform transform) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 26c6e482af..8d89806984 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -734,7 +734,7 @@ ;; --- Changes Processing Impl -(defmulti process-change (fn [data change] (:type change))) +(defmulti process-change (fn [_ change] (:type change))) (defmulti process-operation (fn [_ op] (:type op))) (defn process-changes @@ -756,45 +756,45 @@ (defmethod process-change :add-obj [data {:keys [id obj page-id component-id frame-id parent-id - index ignore-touched] :as change}] + index ignore-touched]}] (letfn [(update-fn [data] (let [parent-id (or parent-id frame-id) - objects (:objects data)] - (let [obj (assoc obj - :frame-id frame-id - :parent-id parent-id - :id id)] - (if (and (contains? objects parent-id) - (contains? objects frame-id)) - (-> data - (update :objects assoc id obj) - (update-in [:objects parent-id :shapes] - (fn [shapes] - (let [shapes (or shapes [])] - (cond - (some #{id} shapes) - shapes + objects (:objects data) + obj (assoc obj + :frame-id frame-id + :parent-id parent-id + :id id)] + (if (and (contains? objects parent-id) + (contains? objects frame-id)) + (-> data + (update :objects assoc id obj) + (update-in [:objects parent-id :shapes] + (fn [shapes] + (let [shapes (or shapes [])] + (cond + (some #{id} shapes) + shapes - (nil? index) - (if (= :frame (:type obj)) - (d/concat [id] shapes) - (conj shapes id)) + (nil? index) + (if (= :frame (:type obj)) + (d/concat [id] shapes) + (conj shapes id)) - :else - (cph/insert-at-index shapes index [id]))))) + :else + (cph/insert-at-index shapes index [id]))))) - (cond-> (and (:shape-ref (get-in data [:objects parent-id])) - (not= parent-id frame-id) - (not ignore-touched)) - (update-in [:objects parent-id :touched] - cph/set-touched-group :shapes-group))) - data))))] + (cond-> (and (:shape-ref (get-in data [:objects parent-id])) + (not= parent-id frame-id) + (not ignore-touched)) + (update-in [:objects parent-id :touched] + cph/set-touched-group :shapes-group))) + data)))] (if page-id (d/update-in-when data [:pages-index page-id] update-fn) (d/update-in-when data [:components component-id] update-fn)))) (defmethod process-change :mod-obj - [data {:keys [id page-id component-id operations] :as change}] + [data {:keys [id page-id component-id operations]}] (let [update-fn (fn [objects] (if-let [obj (get objects id)] (let [result (reduce process-operation obj operations)] @@ -806,7 +806,7 @@ (d/update-in-when data [:components component-id :objects] update-fn)))) (defmethod process-change :del-obj - [data {:keys [page-id component-id id ignore-touched] :as change}] + [data {:keys [page-id component-id id ignore-touched]}] (letfn [(delete-object [objects id] (if-let [target (get objects id)] (let [parent-id (cph/get-parent id objects) @@ -880,7 +880,7 @@ (d/update-in-when data [:components component-id :objects] reg-objects)))) (defmethod process-change :mov-objects - [data {:keys [parent-id shapes index page-id component-id ignore-touched] :as change}] + [data {:keys [parent-id shapes index page-id component-id ignore-touched]}] (letfn [(is-valid-move? [objects shape-id] (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] (and (not (invalid-targets parent-id)) @@ -961,7 +961,6 @@ (keys objects)) cpindex (persistent! cpindex) - parent (get-in data [:objects parent-id]) parent (get objects parent-id) frame (if (= :frame (:type parent)) parent @@ -993,9 +992,9 @@ (update :pages-index assoc id page))) (map? page) - (->> data - (update :pages conj (:id page) - (update :pages-index assoc (:id page) page))) + (-> data + (update :pages conj (:id page)) + (update :pages-index assoc (:id page) page)) :else (ex/raise :type :conflict @@ -1121,7 +1120,7 @@ (assoc shape :touched touched)))) (defmethod process-operation :default - [shape op] + [_ op] (ex/raise :type :not-implemented :code :operation-not-implemented :context {:type (:type op)})) diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index b49014ed25..2fb13a2e27 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -38,8 +38,7 @@ (if (:component-id shape) shape (if-let [parent-id (:parent-id shape)] - (get-root-shape (get objects (:parent-id shape)) - objects) + (get-root-shape (get objects parent-id) objects) nil))) (defn make-container @@ -118,7 +117,7 @@ (defn get-parents [shape-id objects] - (let [{:keys [parent-id] :as obj} (get objects shape-id)] + (let [{:keys [parent-id]} (get objects shape-id)] (when parent-id (lazy-seq (cons parent-id (get-parents parent-id objects)))))) @@ -252,10 +251,10 @@ (clone-object child new-id objects update-new-object update-original-object)] (recur - (next child-ids) - (d/concat new-direct-children [new-child]) - (d/concat new-children new-child-objects) - (d/concat updated-children updated-child-objects)))))))) + (next child-ids) + (d/concat new-direct-children [new-child]) + (d/concat new-children new-child-objects) + (d/concat updated-children updated-child-objects)))))))) (defn indexed-shapes diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index 257d135b52..d9af48c7cd 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -3,9 +3,7 @@ [app.common.pages :as cp] [app.common.geom.shapes :as gsh] [app.common.geom.shapes.path :as gsp] - [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] - [app.common.spec :as us] [app.common.uuid :as uuid] [app.common.data :as d])) @@ -21,7 +19,7 @@ data (range (:version data 0) cp/file-version)))) - ([data from-version to-version] + ([data _ to-version] (-> data (assoc :version to-version) (migrate)))) @@ -38,14 +36,14 @@ ;; Ensure that all :shape attributes on shapes are vectors. (defmethod migrate 2 [data] - (letfn [(update-object [id object] + (letfn [(update-object [_ object] (d/update-when object :shapes (fn [shapes] (if (seq? shapes) (into [] shapes) shapes)))) - (update-page [id page] + (update-page [_ page] (update page :objects #(d/mapm update-object %)))] (update data :pages-index #(d/mapm update-page %)))) @@ -82,7 +80,7 @@ (empty? (:points shape)) (assoc :points (gsh/rect->points (:selrect shape)))))) - (update-object [id object] + (update-object [_ object] (cond-> object (= :curve (:type object)) (assoc :type :path) @@ -105,7 +103,7 @@ )) - (update-page [id page] + (update-page [_ page] (update page :objects #(d/mapm update-object %)))] (update data :pages-index #(d/mapm update-page %)))) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index c791fc467f..1292e1bf96 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -15,9 +15,6 @@ #?(:clj [clojure.spec.alpha :as s] :cljs [cljs.spec.alpha :as s]) - #?(:clj [clojure.spec.test.alpha :as stest] - :cljs [cljs.spec.test.alpha :as stest]) - [expound.alpha :as expound] [app.common.uuid :as uuid] [app.common.exceptions :as ex] diff --git a/docs/06-Testing-Guide.md b/docs/06-Testing-Guide.md new file mode 100644 index 0000000000..66390b4091 --- /dev/null +++ b/docs/06-Testing-Guide.md @@ -0,0 +1,39 @@ +# Testing guide # + +## Backend / Common + +You can run the tests directly with: + +```bash +~/penpot/backend$ clojure -M:dev:tests +``` + +Alternatively, you can run them from a REPL. First starting a REPL. + +```bash +~/penpot/backend$ scripts/repl +``` + +And then: + +```bash +user=> (run-tests) +user=> (run-tests 'namespace) +user=> (run-tests 'namespace/test) +``` + +## Frontend + +Frontend tests have to be compiled first, and then run with node. + +```bash +npx shadow-cljs compile tests && node target/tests.js +``` + +## Linter + +We can execute the linter for the whole codebase with the following command + +```bash +npx clj-kondo --lint common:backend/src:frontend/src +``` diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index e06e7240d4..6edb5390d4 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -27,7 +27,22 @@ (assoc-in state [:workspace-drawing :object :initialized?] true)) (defn insert-point-segment [state point] - (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) + + (let [segments (-> state + (get-in [:workspace-drawing :object :segments]) + (or []) + (conj point)) + content (gsp/segments->content segments) + selrect (gsh/content->selrect content) + points (gsh/rect->points selrect)] + (-> state + (update-in [:workspace-drawing :object] assoc + :segments segments + :content content + :selrect selrect + :points points)))) + + (defn curve-to-path [{:keys [segments] :as shape}] (let [content (gsp/segments->content segments) diff --git a/frontend/src/app/main/ui/workspace/drawarea.cljs b/frontend/src/app/main/ui/workspace/drawarea.cljs index c89a4e691d..3c365dea03 100644 --- a/frontend/src/app/main/ui/workspace/drawarea.cljs +++ b/frontend/src/app/main/ui/workspace/drawarea.cljs @@ -12,6 +12,7 @@ [app.main.data.workspace.drawing :as dd] [app.main.store :as st] [app.main.ui.workspace.shapes :as shapes] + [app.main.ui.shapes.path :refer [path-shape]] [app.main.ui.workspace.shapes.path.editor :refer [path-editor]] [app.common.geom.shapes :as gsh] [app.common.data :as d] @@ -22,13 +23,14 @@ (declare path-draw-area) (mf/defc draw-area - [{:keys [shape zoom] :as props}] + [{:keys [shape zoom tool] :as props}] [:g.draw-area [:& shapes/shape-wrapper {:shape shape}] - (case (:type shape) + (case tool :path [:& path-editor {:shape shape :zoom zoom}] + :curve [:& path-shape {:shape shape :zoom zoom}] #_:default [:& generic-draw-area {:shape shape :zoom zoom}])]) (mf/defc generic-draw-area diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index adbb0b0534..a6886f9144 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -592,6 +592,7 @@ (when drawing-obj [:& draw-area {:shape drawing-obj :zoom zoom + :tool drawing-tool :modifiers (:modifiers local)}]) (when (contains? layout :display-grid) From 7f1a436f30b32f789d183cd34ce658572c1bc806 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 09:39:39 +0100 Subject: [PATCH 123/195] :recycle: Refactor docker devenv and image building. --- .gitignore | 2 +- docker/devenv/Dockerfile | 32 ++-- docker/devenv/docker-compose.yaml | 3 +- docker/devenv/files/bashrc | 7 +- docker/devenv/files/entrypoint.sh | 8 +- docker/devenv/files/init.sh | 9 +- docker/devenv/files/start-tmux.sh | 7 + docker/images/Dockerfile.backend | 21 +++ .../Dockerfile.exporter} | 2 +- .../Dockerfile.frontend} | 0 docker/images/docker-compose.yaml | 68 ++++++++ .../files/exporter-entrypoint.sh | 0 .../files/nginx-entrypoint.sh | 0 docker/{testenv => images}/files/nginx.conf | 10 +- docker/testenv/Dockerfile-backend | 5 - docker/testenv/docker-compose.yaml | 112 ------------ manage.sh | 165 ++++++++++++------ 17 files changed, 234 insertions(+), 217 deletions(-) create mode 100644 docker/images/Dockerfile.backend rename docker/{testenv/Dockerfile-exporter => images/Dockerfile.exporter} (98%) rename docker/{testenv/Dockerfile-nginx => images/Dockerfile.frontend} (100%) create mode 100644 docker/images/docker-compose.yaml rename docker/{testenv => images}/files/exporter-entrypoint.sh (100%) rename docker/{testenv => images}/files/nginx-entrypoint.sh (100%) rename docker/{testenv => images}/files/nginx.conf (89%) delete mode 100644 docker/testenv/Dockerfile-backend delete mode 100644 docker/testenv/docker-compose.yaml diff --git a/.gitignore b/.gitignore index 0e01a66857..59b74d6ec9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ node_modules /frontend/resources/public/* /exporter/target /exporter/.shadow-cljs -/docker/testenv/bundle +/docker/images/bundle /bundle* /media /deploy diff --git a/docker/devenv/Dockerfile b/docker/devenv/Dockerfile index 75e04f06f9..69cb617a87 100644 --- a/docker/devenv/Dockerfile +++ b/docker/devenv/Dockerfile @@ -2,10 +2,9 @@ FROM debian:buster LABEL maintainer="Andrey Antukh " ARG DEBIAN_FRONTEND=noninteractive -ARG EXTERNAL_UID=1000 -ENV NODE_VERSION=v14.15.0 \ - CLOJURE_VERSION=1.10.1.727 \ +ENV NODE_VERSION=v14.15.1 \ + CLOJURE_VERSION=1.10.1.739 \ LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 @@ -31,7 +30,7 @@ RUN set -ex; \ rm -rf /var/lib/apt/lists/*; RUN set -ex; \ - useradd -m -g users -s /bin/bash -u $EXTERNAL_UID penpot; \ + useradd -m -g users -s /bin/bash penpot; \ passwd penpot -d; \ echo "penpot ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers @@ -120,19 +119,20 @@ COPY files/phantomjs-mock /usr/bin/phantomjs COPY files/bashrc /root/.bashrc COPY files/vimrc /root/.vimrc COPY files/tmux.conf /root/.tmux.conf -COPY files/start-tmux.sh /home/start-tmux.sh -COPY files/entrypoint.sh /home/entrypoint.sh -COPY files/init.sh /home/init.sh -USER penpot -WORKDIR /home/penpot +WORKDIR /home RUN set -ex; \ - git clone https://github.com/creationix/nvm.git .nvm; \ - bash -c "source .nvm/nvm.sh && nvm install $NODE_VERSION"; \ - bash -c "source .nvm/nvm.sh && nvm alias default $NODE_VERSION"; \ - bash -c "source .nvm/nvm.sh && nvm use default"; \ - bash -c "source .nvm/nvm.sh && npm install -g yarn"; + mkdir -p /tmp/node; \ + cd /tmp/node; \ + export PATH="$PATH:/usr/local/nodejs/bin"; \ + wget https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.xz; \ + tar xvf node-$NODE_VERSION-linux-x64.tar.xz; \ + mv /tmp/node/node-$NODE_VERSION-linux-x64 /usr/local/nodejs; \ + chown -R root /usr/local/nodejs; \ + /usr/local/nodejs/bin/npm install -g yarn; \ + /usr/local/nodejs/bin/yarn global add clj-kondo; \ + rm -rf /tmp/node; EXPOSE 3447 EXPOSE 3448 @@ -140,5 +140,9 @@ EXPOSE 3449 EXPOSE 6060 EXPOSE 9090 +COPY files/start-tmux.sh /home/start-tmux.sh +COPY files/entrypoint.sh /home/entrypoint.sh +COPY files/init.sh /home/init.sh + ENTRYPOINT ["/home/entrypoint.sh"] CMD ["/home/init.sh"] diff --git a/docker/devenv/docker-compose.yaml b/docker/devenv/docker-compose.yaml index 21978864fe..286f2e1034 100644 --- a/docker/devenv/docker-compose.yaml +++ b/docker/devenv/docker-compose.yaml @@ -14,7 +14,7 @@ volumes: services: main: privileged: true - image: "penpot-devenv" + image: "penpotapp/devenv:latest" build: context: "." container_name: "penpot-devenv-main" @@ -42,6 +42,7 @@ services: - APP_DATABASE_USERNAME=penpot - APP_DATABASE_PASSWORD=penpot - APP_REDIS_URI=redis://redis/0 + - EXTERNAL_UID=${CURRENT_USER_ID} postgres: image: postgres:13 diff --git a/docker/devenv/files/bashrc b/docker/devenv/files/bashrc index 246700b756..526ef9db59 100644 --- a/docker/devenv/files/bashrc +++ b/docker/devenv/files/bashrc @@ -1,12 +1,7 @@ -export PATH=$HOME/.local/bin:$PATH +export PATH=$HOME/.local/bin:/usr/local/nodejs/bin:$PATH alias l='ls --color -GFlh' alias rm='rm -r' alias ls='ls --color -F' alias lsd='ls -d *(/)' alias lsf='ls -h *(.)' - -export LEIN_FAST_TRAMPOLINE=y - -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm diff --git a/docker/devenv/files/entrypoint.sh b/docker/devenv/files/entrypoint.sh index 87f47077f4..9754942190 100755 --- a/docker/devenv/files/entrypoint.sh +++ b/docker/devenv/files/entrypoint.sh @@ -1,12 +1,6 @@ #!/usr/bin/env bash set -e - -sudo cp /root/.bashrc /home/penpot/.bashrc -sudo cp /root/.vimrc /home/penpot/.vimrc -sudo cp /root/.tmux.conf /home/penpot/.tmux.conf - -source /home/penpot/.bashrc -sudo chown penpot:users /home/penpot +usermod -u ${EXTERNAL_UID:-1000} penpot exec "$@" diff --git a/docker/devenv/files/init.sh b/docker/devenv/files/init.sh index 0a5a754fb8..2f809ebbb9 100755 --- a/docker/devenv/files/init.sh +++ b/docker/devenv/files/init.sh @@ -1,10 +1,5 @@ #!/usr/bin/env bash -set -e; -source ~/.bashrc - -echo "[init.sh] Start nginx." -sudo nginx - -echo "[init.sh] Ready!" +set -e +nginx tail -f /dev/null diff --git a/docker/devenv/files/start-tmux.sh b/docker/devenv/files/start-tmux.sh index e658069656..1c0202a664 100755 --- a/docker/devenv/files/start-tmux.sh +++ b/docker/devenv/files/start-tmux.sh @@ -1,5 +1,12 @@ #!/usr/bin/env bash +sudo cp /root/.bashrc /home/penpot/.bashrc +sudo cp /root/.vimrc /home/penpot/.vimrc +sudo cp /root/.tmux.conf /home/penpot/.tmux.conf + +source /home/penpot/.bashrc +sudo chown penpot:users /home/penpot + cd ~; set -e; diff --git a/docker/images/Dockerfile.backend b/docker/images/Dockerfile.backend new file mode 100644 index 0000000000..b528e497a2 --- /dev/null +++ b/docker/images/Dockerfile.backend @@ -0,0 +1,21 @@ +FROM debian:buster-slim +LABEL maintainer="Andrey Antukh " + +ENV LANG='en_US.UTF-8' LC_ALL='en_US.UTF-8' + +RUN set -ex; \ + apt-get -qq update; \ + apt-get -qqy --no-install-recommends install wget locales ca-certificates imagemagick webp gnupg2; \ + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \ + locale-gen; \ + mkdir -p /usr/share/man/man1; \ + mkdir -p /usr/share/man/man7; \ + wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -; \ + echo "deb https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/ buster main" >> /etc/apt/sources.list.d/adoptopenjdk.list; \ + apt-get -qq update; \ + apt-get -qqy install adoptopenjdk-15-hotspot; \ + rm -rf /var/lib/apt/lists/*; + +ADD ./bundle/backend/ /opt/bundle/ +WORKDIR /opt/bundle +CMD ["/bin/bash", "run.sh"] diff --git a/docker/testenv/Dockerfile-exporter b/docker/images/Dockerfile.exporter similarity index 98% rename from docker/testenv/Dockerfile-exporter rename to docker/images/Dockerfile.exporter index eaeee4a9fe..2697d1155c 100644 --- a/docker/testenv/Dockerfile-exporter +++ b/docker/images/Dockerfile.exporter @@ -5,7 +5,7 @@ ARG DEBIAN_FRONTEND=noninteractive ENV LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 \ - NODE_VERSION=v12.18.4 + NODE_VERSION=v14.15.1 RUN set -ex; \ mkdir -p /etc/resolvconf/resolv.conf.d; \ diff --git a/docker/testenv/Dockerfile-nginx b/docker/images/Dockerfile.frontend similarity index 100% rename from docker/testenv/Dockerfile-nginx rename to docker/images/Dockerfile.frontend diff --git a/docker/images/docker-compose.yaml b/docker/images/docker-compose.yaml new file mode 100644 index 0000000000..689b13f092 --- /dev/null +++ b/docker/images/docker-compose.yaml @@ -0,0 +1,68 @@ +--- +version: "3" + +networks: + default: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.177.99.0/24 + +volumes: + postgres_data: + user_data: + backend_data: + +services: + penpot-frontend: + image: "penpotapp/frontend:develop" + ports: + - 8080:80 + + volumes: + - backend_data:/opt/data + + depends_on: + - penpot-backend + - penpot-exporter + + penpot-backend: + image: "penpotapp/backend:develop" + volumes: + - backend_data:/opt/data + + depends_on: + - penpot-postgres + - penpot-redis + + environment: + - APP_DATABASE_URI=postgresql://penpot-postgres/penpot + - APP_DATABASE_USERNAME=penpot + - APP_DATABASE_PASSWORD=penpot + - APP_SMTP_ENABLED=false + - APP_REDIS_URI=redis://penpot-redis/0 + - APP_MEDIA_DIRECTORY=/opt/data/media + + penpot-exporter: + image: "penpotapp/exporter:develop" + environment: + - APP_PUBLIC_URI=http://penpot-frontend + + penpot-postgres: + image: "postgres:13" + restart: always + stop_signal: SIGINT + + environment: + - POSTGRES_INITDB_ARGS=--data-checksums + - POSTGRES_DB=penpot + - POSTGRES_USER=penpot + - POSTGRES_PASSWORD=penpot + + volumes: + - postgres_data:/var/lib/postgresql/data + + penpot-redis: + image: redis:6 + restart: always diff --git a/docker/testenv/files/exporter-entrypoint.sh b/docker/images/files/exporter-entrypoint.sh similarity index 100% rename from docker/testenv/files/exporter-entrypoint.sh rename to docker/images/files/exporter-entrypoint.sh diff --git a/docker/testenv/files/nginx-entrypoint.sh b/docker/images/files/nginx-entrypoint.sh similarity index 100% rename from docker/testenv/files/nginx-entrypoint.sh rename to docker/images/files/nginx-entrypoint.sh diff --git a/docker/testenv/files/nginx.conf b/docker/images/files/nginx.conf similarity index 89% rename from docker/testenv/files/nginx.conf rename to docker/images/files/nginx.conf index af58933d4e..c8ceca0f10 100644 --- a/docker/testenv/files/nginx.conf +++ b/docker/images/files/nginx.conf @@ -26,9 +26,9 @@ http { access_log /dev/stdout; gzip on; - gzip_vary on; gzip_proxied any; + gzip_static on; gzip_comp_level 4; gzip_buffers 16 8k; gzip_http_version 1.1; @@ -70,21 +70,21 @@ http { } location /api { - proxy_pass http://172.177.99.3:6060/api; + proxy_pass http://penpot-backend:6060/api; } location /export { - proxy_pass http://172.177.99.4:6061; + proxy_pass http://penpot-exporter:6061; } location /ws/notifications { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; - proxy_pass http://172.177.99.3:6060/ws/notifications; + proxy_pass http://penpot-backend:6060/ws/notifications; } location /media { - alias /mount/backend/media; + alias /opt/data/media; } } } diff --git a/docker/testenv/Dockerfile-backend b/docker/testenv/Dockerfile-backend deleted file mode 100644 index 03906855e0..0000000000 --- a/docker/testenv/Dockerfile-backend +++ /dev/null @@ -1,5 +0,0 @@ -FROM adoptopenjdk/openjdk15:debianslim-jre -LABEL maintainer="Andrey Antukh " -ADD ./bundle/backend/ /opt/bundle/ -WORKDIR /opt/bundle -CMD ["/bin/bash", "run.sh"] diff --git a/docker/testenv/docker-compose.yaml b/docker/testenv/docker-compose.yaml deleted file mode 100644 index e266d7d2ad..0000000000 --- a/docker/testenv/docker-compose.yaml +++ /dev/null @@ -1,112 +0,0 @@ ---- -version: "3" - -networks: - default: - driver: bridge - ipam: - driver: default - config: - - subnet: 172.177.99.0/24 - -volumes: - postgres_data: - user_data: - backend_data: - -services: - nginx: - image: "uxbox-testenv-nginx" - build: - context: "." - dockerfile: "Dockerfile-nginx" - - ports: - - 8080:80 - - networks: - default: - ipv4_address: 172.177.99.2 - - backend: - image: "uxbox-testenv-backend" - build: - context: "." - dockerfile: "Dockerfile-backend" - - volumes: - - backend_data:/opt/data - - depends_on: - - postgres - - smtp - - redis - - environment: - - APP_DATABASE_URI=postgresql://postgres/uxbox - - APP_DATABASE_USERNAME=uxbox - - APP_DATABASE_PASSWORD=uxbox - - APP_SENDMAIL_BACKEND=smtp - - APP_SMTP_HOST=smtp - - APP_SMTP_PORT=25 - - APP_MEDIA_DIRECTORY=/opt/data/media - - networks: - default: - ipv4_address: 172.177.99.3 - - - exporter: - image: "uxbox-testenv-exporter" - build: - context: "." - dockerfile: "Dockerfile-exporter" - - environment: - - APP_PUBLIC_URI=http://nginx - - depends_on: - - backend - - nginx - - networks: - default: - ipv4_address: 172.177.99.4 - - smtp: - image: mwader/postfix-relay:latest - restart: always - environment: - - POSTFIX_myhostname=smtp.testing.uxbox.io - - OPENDKIM_DOMAINS=smtp.testing.uxbox.io - - networks: - default: - ipv4_address: 172.177.99.5 - - postgres: - image: "postgres:12" - restart: always - stop_signal: SIGINT - - environment: - - POSTGRES_INITDB_ARGS=--data-checksums - - POSTGRES_DB=uxbox - - POSTGRES_USER=uxbox - - POSTGRES_PASSWORD=uxbox - - volumes: - - postgres_data:/var/lib/postgresql/data - - networks: - default: - ipv4_address: 172.177.99.6 - - redis: - image: redis:6 - restart: always - - networks: - default: - ipv4_address: 172.177.99.7 - diff --git a/manage.sh b/manage.sh index 6f29902b75..870a1f39b3 100755 --- a/manage.sh +++ b/manage.sh @@ -1,58 +1,76 @@ #!/usr/bin/env bash set -e -REV=`git log -n 1 --pretty=format:%h -- docker/` -DEVENV_IMGNAME="penpot-devenv" +export ORGANIZATION="penpotapp"; +export DEVENV_IMGNAME="$ORGANIZATION/devenv"; +export DEVENV_PNAME="penpotdev"; + +export CURRENT_USER_ID=$(id -u); +export CURRENT_GIT_TAG=$(git describe --tags); +export CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD); function build-devenv { - echo "Building development image $DEVENV_IMGNAME:latest with UID $EXTERNAL_UID..." - local EXTERNAL_UID=${1:-$(id -u)} - docker-compose -p penpotdev -f docker/devenv/docker-compose.yaml build \ - --force-rm --build-arg EXTERNAL_UID=$EXTERNAL_UID + echo "Building development image $DEVENV_IMGNAME:latest..." + + pushd docker/devenv; + docker build -t $DEVENV_IMGNAME:latest . + popd; } -function build-devenv-if-not-exists { +function publish-devenv { + docker push $DEVENV_IMGNAME:latest +} + +function pull-devenv { + set -ex + docker pull $DEVENV_IMGNAME:latest +} + +function pull-devenv-if-not-exists { if [[ ! $(docker images $DEVENV_IMGNAME:latest -q) ]]; then - build-devenv $@ + pull-devenv $@ fi } function start-devenv { - build-devenv-if-not-exists $@; - docker-compose -p penpotdev -f docker/devenv/docker-compose.yaml up -d; + pull-devenv-if-not-exists $@; + docker-compose -p $DEVENV_PNAME -f docker/devenv/docker-compose.yaml up -d; } function stop-devenv { - docker-compose -p penpotdev -f docker/devenv/docker-compose.yaml stop -t 2; + docker-compose -p $DEVENV_PNAME -f docker/devenv/docker-compose.yaml stop -t 2; } function drop-devenv { - docker-compose -p penpotdev -f docker/devenv/docker-compose.yaml down -t 2 -v; + docker-compose -p $DEVENV_PNAME -f docker/devenv/docker-compose.yaml down -t 2 -v; echo "Clean old development image $DEVENV_IMGNAME..." docker images $DEVENV_IMGNAME -q | awk '{print $3}' | xargs --no-run-if-empty docker rmi } +function log-devenv { + docker-compose -p $DEVENV_PNAME -f docker/devenv/docker-compose.yaml logs -f --tail=50 +} + function run-devenv { if [[ ! $(docker ps -f "name=penpot-devenv-main" -q) ]]; then start-devenv fi - docker exec -ti penpot-devenv-main /home/start-tmux.sh + docker exec -ti penpot-devenv-main sudo -EH -u penpot /home/start-tmux.sh } function build { - build-devenv-if-not-exists; - local IMAGE=$DEVENV_IMGNAME:latest; - - docker volume create penpotdev_user_data; + pull-devenv-if-not-exists; + docker volume create $DEVENV_PNAME_user_data; echo "Running development image $IMAGE to build frontend." docker run -t --rm \ - --mount source=penpotdev_user_data,type=volume,target=/home/penpot/ \ + --mount source=$DEVENV_PNAME_user_data,type=volume,target=/home/penpot/ \ --mount source=`pwd`,type=bind,target=/home/penpot/penpot \ + -e EXTERNAL_UID=$CURRENT_USER_ID \ -w /home/penpot/penpot/$1 \ - $IMAGE ./scripts/build.sh + $DEVENV_IMGNAME:latest sudo -u penpot ./scripts/build.sh } function build-frontend { @@ -68,7 +86,6 @@ function build-backend { } function build-bundle { - build "frontend"; build "exporter"; build "backend"; @@ -79,70 +96,103 @@ function build-bundle { mv ./backend/target/dist ./bundle/backend mv ./exporter/target ./bundle/exporter - NAME="penpot-$(date '+%Y.%m.%d-%H%M')" + local name="penpot-$CURRENT_GIT_TAG"; + + echo $CURRENT_GIT_TAG > ./bundle/frontend/version.txt + echo $CURRENT_GIT_TAG > ./bundle/backend/main/version.txt + echo $CURRENT_GIT_TAG > ./bundle/exporter/version.txt + echo $CURRENT_GIT_TAG > ./bundle/version.txt pushd bundle/ - tar -cvf ../$NAME.tar *; + tar -cvf ../$name.tar *; popd - xz -vez4f -T4 $NAME.tar + xz -vez1f -T4 $name.tar + + echo "##############################################################"; + echo "# Generated $name.tar.xz"; + echo "##############################################################"; } -function log-devenv { - docker-compose -p penpotdev -f docker/devenv/docker-compose.yaml logs -f --tail=50 +function build-image { + set -ex; + + local image=$1; + + pushd ./docker/images; + local docker_image="$ORGANIZATION/$image"; + docker build -t $docker_image:$CURRENT_GIT_TAG -f Dockerfile.$image .; + popd; } -function build-testenv { - local BUNDLE_FILE=$1; - local BUNDLE_FILE_PATH=`readlink -f $BUNDLE_FILE`; +function build-images { + local bundle_file="penpot-$CURRENT_GIT_TAG.tar.xz"; - echo "Building testenv with bundle: $BUNDLE_FILE_PATH." - - if [ ! -f $BUNDLE_FILE ]; then - echo "File $BUNDLE_FILE does not exists." + if [ ! -f $bundle_file ]; then + echo "File '$bundle_file' does not exists."; + exit 1; fi - rm -rf ./docker/testenv/bundle; - mkdir -p ./docker/testenv/bundle; + rm -rf ./docker/images/bundle; + mkdir -p ./docker/images/bundle; - pushd ./docker/testenv/bundle; - tar xvf $BUNDLE_FILE_PATH; + local bundle_file_path=`readlink -f $bundle_file`; + echo "Building docker image from: $bundle_file_path."; + + pushd ./docker/images/bundle; + tar xvf $bundle_file_path; popd - pushd ./docker/testenv; - docker-compose -p penpot-testenv -f ./docker-compose.yaml build - popd + build-image "backend"; + build-image "frontend"; + build-image "exporter"; } -function start-testenv { - pushd ./docker/testenv; - docker-compose -p penpot-testenv -f ./docker-compose.yaml up - popd +function publish-snapshot { + set -x + docker tag $ORGANIZATION/frontend:$CURRENT_GIT_TAG $ORGANIZATION/frontend:$CURRENT_GIT_BRANCH + docker tag $ORGANIZATION/backend:$CURRENT_GIT_TAG $ORGANIZATION/backend:$CURRENT_GIT_BRANCH + docker tag $ORGANIZATION/exporter:$CURRENT_GIT_TAG $ORGANIZATION/exporter:$CURRENT_GIT_BRANCH + + docker push $ORGANIZATION/frontend:$CURRENT_GIT_BRANCH; + docker push $ORGANIZATION/backend:$CURRENT_GIT_BRANCH; + docker push $ORGANIZATION/exporter:$CURRENT_GIT_BRANCH; } function usage { - echo "PENPOT build & release manager v$REV" + echo "PENPOT build & release manager" echo "USAGE: $0 OPTION" echo "Options:" # echo "- clean Stop and clean up docker containers" # echo "" - echo "- build-devenv Build docker development oriented image; (can specify external user id in parameter)" + echo "- pull-devenv Pulls docker development oriented image" + echo "- build-devenv Build docker development oriented image" echo "- start-devenv Start the development oriented docker-compose service." echo "- stop-devenv Stops the development oriented docker-compose service." echo "- drop-devenv Remove the development oriented docker-compose containers, volumes and clean images." echo "- run-devenv Attaches to the running devenv container and starts development environment" echo " based on tmux (frontend at localhost:3449, backend at localhost:6060)." echo "" - echo "- run-all-tests Execute unit tests for both backend and frontend." - echo "- run-frontend-tests Execute unit tests for frontend only." - echo "- run-backend-tests Execute unit tests for backend only." + # echo "- run-all-tests Execute unit tests for both backend and frontend." + # echo "- run-frontend-tests Execute unit tests for frontend only." + # echo "- run-backend-tests Execute unit tests for backend only." } case $1 in ## devenv related commands + pull-devenv) + pull-devenv ${@:2}; + ;; + build-devenv) build-devenv ${@:2} ;; + + + publish-devenv) + publish-devenv ${@:2} + ;; + start-devenv) start-devenv ${@:2} ;; @@ -159,16 +209,6 @@ case $1 in log-devenv ${@:2} ;; - - # Test Env - start-testenv) - start-testenv - ;; - - build-testenv) - build-testenv ${@:2} - ;; - ## testin related commands # run-all-tests) @@ -198,6 +238,15 @@ case $1 in build-bundle ;; + # Docker Image Tasks + build-images) + build-images; + ;; + + publish-snapshot) + publish-snapshot ${@:2} + ;; + *) usage ;; From 8bc37416a07af4f37c710c12d17957111e4c28b1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 09:58:50 +0100 Subject: [PATCH 124/195] :tada: Add initial clj-kondo config. --- .clj-kondo/config.edn | 11 +++++++++++ .gitignore | 1 + 2 files changed, 12 insertions(+) create mode 100644 .clj-kondo/config.edn diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn new file mode 100644 index 0000000000..6e490a822f --- /dev/null +++ b/.clj-kondo/config.edn @@ -0,0 +1,11 @@ +{:lint-as {potok.core/reify clojure.core/reify + promesa.core/let clojure.core/let + app.db/with-atomic clojure.core/with-open} + :linters + {:unused-binding + {:exclude-destructured-as true} + :unresolved-symbol + {:exclude ['(app.services.mutations/defmutation) + '(app.services.queries/defquery) + ]}}} + diff --git a/.gitignore b/.gitignore index 59b74d6ec9..b78c9815b6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ node_modules /exporter/target /exporter/.shadow-cljs /docker/images/bundle +/.clj-kondo/.cache /bundle* /media /deploy From 1fb5ffb59b351c370390db4990bb90eff2deb4ce Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 2 Dec 2020 12:49:49 +0100 Subject: [PATCH 125/195] :sparkles: Improved tests for geom transforms --- backend/tests/app/tests/test_common_geom.clj | 94 +++++++++ .../app/tests/test_common_geom_shapes.clj | 179 ++++++++++++++++++ common/app/common/geom/shapes/path.cljc | 4 +- common/app/common/geom/shapes/rect.cljc | 4 + frontend/tests/app/test_util_geom.cljs | 83 -------- 5 files changed, 279 insertions(+), 85 deletions(-) create mode 100644 backend/tests/app/tests/test_common_geom.clj create mode 100644 backend/tests/app/tests/test_common_geom_shapes.clj delete mode 100644 frontend/tests/app/test_util_geom.cljs diff --git a/backend/tests/app/tests/test_common_geom.clj b/backend/tests/app/tests/test_common_geom.clj new file mode 100644 index 0000000000..a333c32757 --- /dev/null +++ b/backend/tests/app/tests/test_common_geom.clj @@ -0,0 +1,94 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.tests.test_common_geom + (:require + [clojure.test :as t] + [app.common.geom.point :as gpt] + [app.common.geom.matrix :as gmt])) + +(t/deftest point-constructors-test + (t/testing "Create point with both coordinates" + (let [p (gpt/point 1 2)] + (t/is (= (:x p) 1)) + (t/is (= (:y p) 2)))) + + (t/testing "Create point with single coordinate" + (let [p (gpt/point 1)] + (t/is (= (:x p) 1)) + (t/is (= (:y p) 1)))) + + (t/testing "Create empty point" + (let [p (gpt/point)] + (t/is (= (:x p) 0)) + (t/is (= (:y p) 0))))) + +(t/deftest point-add-test + (t/testing "Adds two points together" + (let [p1 (gpt/point 1 1) + p2 (gpt/point 2 2) + p3 (gpt/add p1 p2)] + (t/is (= (:x p3) 3)) + (t/is (= (:y p3) 3))))) + +(t/deftest point-subtract-test + (t/testing "Point substraction" + (let [p1 (gpt/point 3 3) + p2 (gpt/point 2 2) + p3 (gpt/subtract p1 p2)] + (t/is (= (:x p3) 1)) + (t/is (= (:y p3) 1))))) + +(t/deftest point-distance-test + (let [p1 (gpt/point 0 0) + p2 (gpt/point 10 0) + d (gpt/distance p1 p2)] + (t/is (number? d)) + (t/is (= d 10.0)))) + +(t/deftest point-length-test + (let [p1 (gpt/point 10 0) + ln (gpt/length p1)] + (t/is (number? ln)) + (t/is (= ln 10.0)))) + +(t/deftest point-angle-test + (t/testing "Get angle a 90 degree angle" + (let [p1 (gpt/point 0 10) + angle (gpt/angle p1)] + (t/is (number? angle)) + (t/is (= angle 90.0)))) + + (t/testing "Get 45 degree angle" + (let [p1 (gpt/point 0 10) + p2 (gpt/point 10 10) + angle (gpt/angle-with-other p1 p2)] + (t/is (number? angle)) + (t/is (= angle 45.0))))) + +(t/deftest matrix-constructors-test + (let [m (gmt/matrix)] + (t/is (= (str m) "matrix(1,0,0,1,0,0)"))) + (let [m (gmt/matrix 1 1 1 2 2 2)] + (t/is (= (str m) "matrix(1,1,1,2,2,2)")))) + +(t/deftest matrix-translate-test + (let [m (-> (gmt/matrix) + (gmt/translate (gpt/point 2 10)))] + (t/is (= (str m) "matrix(1,0,0,1,2,10)")))) + +(t/deftest matrix-scale-test + (let [m (-> (gmt/matrix) + (gmt/scale (gpt/point 2)))] + (t/is (= (str m) "matrix(2,0,0,2,0,0)")))) + +(t/deftest matrix-rotate-test + (let [m (-> (gmt/matrix) + (gmt/rotate 10))] + (t/is (= (str m) "matrix(0.984807753012208,0.17364817766693033,-0.17364817766693033,0.984807753012208,0,0)")))) diff --git a/backend/tests/app/tests/test_common_geom_shapes.clj b/backend/tests/app/tests/test_common_geom_shapes.clj new file mode 100644 index 0000000000..96fb1e6698 --- /dev/null +++ b/backend/tests/app/tests/test_common_geom_shapes.clj @@ -0,0 +1,179 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.tests.test-common-geom-shapes + (:require + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.common.pages :refer [make-minimal-shape]] + [clojure.test :as t])) + +(def default-path [{:command :move-to :params {:x 0 :y 0}} + {:command :line-to :params {:x 20 :y 20}} + {:command :line-to :params {:x 30 :y 30}} + {:command :curve-to :params {:x 40 :y 40 :c1x 35 :c1y 35 :c2x 45 :c2y 45}} + {:command :close-path}]) + +(defn add-path-data [shape] + (let [content (:content shape default-path) + selrect (gsh/content->selrect content) + points (gsh/rect->points selrect)] + (assoc shape + :content content + :selrect selrect + :points points))) + +(defn add-rect-data [shape] + (let [selrect (gsh/rect->selrect shape) + points (gsh/rect->points selrect)] + (assoc shape + :selrect selrect + :points points))) + +(defn create-test-shape + ([type] (create-test-shape type {})) + ([type params] + (-> (make-minimal-shape type) + (merge params) + (cond-> + (= type :path) (add-path-data) + (not= type :path) (add-rect-data))))) + + +(t/deftest transform-shape-tests + (t/testing "Shape without modifiers should stay the same" + (t/are [type] + (let [shape-before (create-test-shape type) + shape-after (gsh/transform-shape shape-before)] + (= shape-before shape-after)) + + :rect :path)) + + + (t/testing "Transform shape with translation modifiers" + (t/are [type] + (let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}] + (let [shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/is (not= shape-before shape-after)) + + (t/is (== (get-in shape-before [:selrect :x]) + (- 10 (get-in shape-after [:selrect :x])))) + + (t/is (== (get-in shape-before [:selrect :y]) + (+ 10 (get-in shape-after [:selrect :y])))) + + (t/is (== (get-in shape-before [:selrect :width]) + (get-in shape-after [:selrect :width]))) + + (t/is (== (get-in shape-before [:selrect :height]) + (get-in shape-after [:selrect :height]))))) + + :rect :path)) + + (t/testing "Transform with empty translation" + (t/are [type] + (let [modifiers {:displacement (gmt/matrix)} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/are [prop] + (t/is (== (get-in shape-before [:selrect prop]) + (get-in shape-after [:selrect prop]))) + :x :y :width :height :x1 :y1 :x2 :y2)) + :rect :path)) + + (t/testing "Transform shape with resize modifiers" + (t/are [type] + (let [modifiers {:resize-origin (gpt/point 0 0) + :resize-vector (gpt/point 2 2) + :resize-transform (gmt/matrix)} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/is (not= shape-before shape-after)) + + (t/is (== (get-in shape-before [:selrect :x]) + (get-in shape-after [:selrect :x]))) + + (t/is (== (get-in shape-before [:selrect :y]) + (get-in shape-after [:selrect :y]))) + + (t/is (== (* 2 (get-in shape-before [:selrect :width])) + (get-in shape-after [:selrect :width]))) + + (t/is (== (* 2 (get-in shape-before [:selrect :height])) + (get-in shape-after [:selrect :height])))) + :rect :path)) + + (t/testing "Transform with empty resize" + (t/are [type] + (let [modifiers {:resize-origin (gpt/point 0 0) + :resize-vector (gpt/point 1 1) + :resize-transform (gmt/matrix)} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/are [prop] + (t/is (== (get-in shape-before [:selrect prop]) + (get-in shape-after [:selrect prop]))) + :x :y :width :height :x1 :y1 :x2 :y2)) + :rect :path)) + + (t/testing "Transform with resize=0" + (t/are [type] + (let [modifiers {:resize-origin (gpt/point 0 0) + :resize-vector (gpt/point 0 0) + :resize-transform (gmt/matrix)} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/is (> (get-in shape-before [:selrect :width]) + (get-in shape-after [:selrect :width]))) + (t/is (> (get-in shape-after [:selrect :width]) 0)) + + (t/is (> (get-in shape-before [:selrect :height]) + (get-in shape-after [:selrect :height]))) + (t/is (> (get-in shape-after [:selrect :height]) 0))) + :rect :path)) + + (t/testing "Transform shape with rotation modifiers" + (t/are [type] + (let [modifiers {:rotation 30} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/is (not= shape-before shape-after)) + + (t/is (not (== (get-in shape-before [:selrect :x]) + (get-in shape-after [:selrect :x])))) + + (t/is (not (== (get-in shape-before [:selrect :y]) + (get-in shape-after [:selrect :y]))))) + :rect :path)) + + (t/testing "Transform shape with rotation = 0 should leave equal selrect" + (t/are [type] + (let [modifiers {:rotation 0} + shape-before (create-test-shape type {:modifiers modifiers}) + shape-after (gsh/transform-shape shape-before)] + (t/are [prop] + (t/is (== (get-in shape-before [:selrect prop]) + (get-in shape-after [:selrect prop]))) + :x :y :width :height :x1 :y1 :x2 :y2)) + :rect :path)) + + (t/testing "Transform shape with invalid selrect fails gracefuly" + (t/are [type selrect] + (let [modifiers {:displacement (gmt/matrix)} + shape-before (-> (create-test-shape type {:modifiers modifiers}) + (assoc :selrect selrect)) + shape-after (gsh/transform-shape shape-before)] + (= (:selrect shape-before) (:selrect shape-after))) + + :rect {:x 0 :y 0 :width ##Inf :height ##Inf} + :path {:x 0 :y 0 :width ##Inf :height ##Inf} + :rect nil + :path nil))) diff --git a/common/app/common/geom/shapes/path.cljc b/common/app/common/geom/shapes/path.cljc index e2fa26bc81..08378b2209 100644 --- a/common/app/common/geom/shapes/path.cljc +++ b/common/app/common/geom/shapes/path.cljc @@ -102,7 +102,6 @@ (let [calc-extremities (fn [command prev] (case (:command command) - :close-path [] :move-to [(command->point command)] ;; If it's a line we add the beginning point and endpoint @@ -116,7 +115,8 @@ (curve-extremities (command->point prev) (command->point command) (command->point command :c1) - (command->point command :c2))))) + (command->point command :c2))) + [])) extremities (mapcat calc-extremities content diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index b748492da6..c788bb3630 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -13,6 +13,10 @@ [app.common.geom.shapes.common :as gco])) (defn rect->points [{:keys [x y width height]}] + (assert (number? x)) + (assert (number? y)) + (assert (and (number? width) (> width 0))) + (assert (and (number? height) (> height 0))) [(gpt/point x y) (gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height)) diff --git a/frontend/tests/app/test_util_geom.cljs b/frontend/tests/app/test_util_geom.cljs deleted file mode 100644 index 3fdf0dc5e4..0000000000 --- a/frontend/tests/app/test_util_geom.cljs +++ /dev/null @@ -1,83 +0,0 @@ -(ns app.test-util-geom - (:require [cljs.test :as t :include-macros true] - [cljs.pprint :refer [pprint]] - [app.common.geom.point :as gpt] - [app.common.geom.matrix :as gmt])) - -(t/deftest point-constructors-test - (let [p (gpt/point 1 2)] - (t/is (= (:x p) 1)) - (t/is (= (:y p) 2))) - - (let [p (gpt/point 1)] - (t/is (= (:x p) 1)) - (t/is (= (:y p) 1))) - - (let [p (gpt/point)] - (t/is (= (:x p) 0)) - (t/is (= (:y p) 0)))) - -;; (t/deftest point-rotate-test -;; (let [p1 (gpt/point 10 0) -;; p2 (gpt/rotate p1 90)] -;; (t/is (= (:x p2) 0)) -;; (t/is (= (:y p2) 10)))) - -(t/deftest point-add-test - (let [p1 (gpt/point 1 1) - p2 (gpt/point 2 2) - p3 (gpt/add p1 p2)] - (t/is (= (:x p3) 3)) - (t/is (= (:y p3) 3)))) - -(t/deftest point-subtract-test - (let [p1 (gpt/point 3 3) - p2 (gpt/point 2 2) - p3 (gpt/subtract p1 p2)] - (t/is (= (:x p3) 1)) - (t/is (= (:y p3) 1)))) - -(t/deftest point-distance-test - (let [p1 (gpt/point 0 0) - p2 (gpt/point 10 0) - d (gpt/distance p1 p2)] - (t/is (number? d)) - (t/is (= d 10)))) - -(t/deftest point-length-test - (let [p1 (gpt/point 10 0) - ln (gpt/length p1)] - (t/is (number? ln)) - (t/is (= ln 10)))) - -(t/deftest point-angle-test - (let [p1 (gpt/point 0 10) - angle (gpt/angle p1)] - (t/is (number? angle)) - (t/is (= angle 90))) - (let [p1 (gpt/point 0 10) - p2 (gpt/point 10 10) - angle (gpt/angle-with-other p1 p2)] - (t/is (number? angle)) - (t/is (= angle 45)))) - -(t/deftest matrix-constructors-test - (let [m (gmt/matrix)] - (t/is (= (str m) "matrix(1,0,0,1,0,0)"))) - (let [m (gmt/matrix 1 1 1 2 2 2)] - (t/is (= (str m) "matrix(1,1,1,2,2,2)")))) - -(t/deftest matrix-translate-test - (let [m (-> (gmt/matrix) - (gmt/translate (gpt/point 2 10)))] - (t/is (= (str m) "matrix(1,0,0,1,2,10)")))) - -(t/deftest matrix-scale-test - (let [m (-> (gmt/matrix) - (gmt/scale (gpt/point 2)))] - (t/is (= (str m) "matrix(2,0,0,2,0,0)")))) - -(t/deftest matrix-rotate-test - (let [m (-> (gmt/matrix) - (gmt/rotate 10))] - (t/is (= (str m) "matrix(0.984807753012208,0.17364817766693033,-0.17364817766693033,0.984807753012208,0,0)")))) From deb39c22914ca76b2d814bfe2469882542a9e8d0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 11:00:08 +0100 Subject: [PATCH 126/195] :sparkles: Add updated clj-kondo to devenv. --- docker/devenv/Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docker/devenv/Dockerfile b/docker/devenv/Dockerfile index 69cb617a87..211f97f7f2 100644 --- a/docker/devenv/Dockerfile +++ b/docker/devenv/Dockerfile @@ -24,6 +24,7 @@ RUN set -ex; \ bash \ git \ rlwrap \ + unzip \ ; \ echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \ locale-gen; \ @@ -131,9 +132,15 @@ RUN set -ex; \ mv /tmp/node/node-$NODE_VERSION-linux-x64 /usr/local/nodejs; \ chown -R root /usr/local/nodejs; \ /usr/local/nodejs/bin/npm install -g yarn; \ - /usr/local/nodejs/bin/yarn global add clj-kondo; \ rm -rf /tmp/node; +RUN set -ex; \ + cd /tmp; \ + wget https://github.com/borkdude/clj-kondo/releases/download/v2020.11.07/clj-kondo-2020.11.07-linux-amd64.zip; \ + unzip clj-kondo-2020.11.07-linux-amd64.zip; \ + mv clj-kondo /usr/local/bin/; \ + rm clj-kondo-2020.11.07-linux-amd64.zip; + EXPOSE 3447 EXPOSE 3448 EXPOSE 3449 From 74077a0ead61111b5d399b9481b724e025e65850 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 11:18:49 +0100 Subject: [PATCH 127/195] :sparkles: Improve clj-kondo configuration. --- .clj-kondo/config.edn | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 6e490a822f..bd1a5d82c4 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -2,10 +2,20 @@ promesa.core/let clojure.core/let app.db/with-atomic clojure.core/with-open} :linters - {:unused-binding - {:exclude-destructured-as true} + {:unsorted-required-namespaces + {:level :warning} + + :single-key-in + {:level :warning} + + :unused-binding + {:exclude-destructured-as true + :exclude-destructured-keys-in-fn-args false + } + :unresolved-symbol {:exclude ['(app.services.mutations/defmutation) '(app.services.queries/defquery) + '(mount.core/defstate) ]}}} From ce3c055819da53bf03de8f22a36bac7cf67198db Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 11:19:27 +0100 Subject: [PATCH 128/195] :sparkles: Fix linter issues on backend util namespace directory. --- backend/src/app/util/async.clj | 5 ++--- backend/src/app/util/data.clj | 2 +- backend/src/app/util/dispatcher.clj | 11 ++++------- backend/src/app/util/emails.clj | 21 +++++++++------------ backend/src/app/util/http.clj | 10 ++++++---- backend/src/app/util/migrations.clj | 9 ++++++--- backend/src/app/util/redis.clj | 14 ++++++++------ backend/src/app/util/sql.clj | 2 +- backend/src/app/util/storage.clj | 13 +++++-------- backend/src/app/util/svg.clj | 22 ++++++++++++---------- backend/src/app/util/template.clj | 13 ++++++------- backend/src/app/util/time.clj | 6 +++--- backend/src/app/util/transit.clj | 10 ++++------ backend/src/app/worker.clj | 20 ++++++++------------ 14 files changed, 75 insertions(+), 83 deletions(-) diff --git a/backend/src/app/util/async.clj b/backend/src/app/util/async.clj index f455f03ca1..afb221b596 100644 --- a/backend/src/app/util/async.clj +++ b/backend/src/app/util/async.clj @@ -6,9 +6,8 @@ (ns app.util.async (:require - [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] - [clojure.core.async :as a]) + [clojure.core.async :as a] + [clojure.spec.alpha :as s]) (:import java.util.concurrent.Executor)) diff --git a/backend/src/app/util/data.clj b/backend/src/app/util/data.clj index d5e12cd8b5..32bd107ee1 100644 --- a/backend/src/app/util/data.clj +++ b/backend/src/app/util/data.clj @@ -12,7 +12,7 @@ ;; TODO: move to app.common.helpers (defn dissoc-in - [m [k & ks :as keys]] + [m [k & ks]] (if ks (if-let [nextmap (get m k)] (let [newmap (dissoc-in nextmap ks)] diff --git a/backend/src/app/util/dispatcher.clj b/backend/src/app/util/dispatcher.clj index 8aad12455a..e86ae408c5 100644 --- a/backend/src/app/util/dispatcher.clj +++ b/backend/src/app/util/dispatcher.clj @@ -8,14 +8,11 @@ "A generic service dispatcher implementation." (:refer-clojure :exclude [defmethod]) (:require - [clojure.spec.alpha :as s] - [expound.alpha :as expound] - [app.common.exceptions :as ex]) + [app.common.exceptions :as ex] + [clojure.spec.alpha :as s]) (:import - clojure.lang.IDeref - clojure.lang.MapEntry - java.util.Map - java.util.HashMap)) + java.util.HashMap + java.util.Map)) (definterface IDispatcher (^void add [key f])) diff --git a/backend/src/app/util/emails.clj b/backend/src/app/util/emails.clj index 2558c52077..f1371f5941 100644 --- a/backend/src/app/util/emails.clj +++ b/backend/src/app/util/emails.clj @@ -5,27 +5,25 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2019-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.emails (:require + [app.common.exceptions :as ex] + [app.common.spec :as us] + [app.util.template :as tmpl] [clojure.java.io :as io] [clojure.spec.alpha :as s] - [cuerdas.core :as str] - [app.common.spec :as us] - [app.common.exceptions :as ex] - [app.util.template :as tmpl]) + [cuerdas.core :as str]) (:import java.util.Properties - javax.mail.Message - javax.mail.Transport javax.mail.Message$RecipientType - javax.mail.PasswordAuthentication javax.mail.Session + javax.mail.Transport javax.mail.internet.InternetAddress - javax.mail.internet.MimeMultipart javax.mail.internet.MimeBodyPart - javax.mail.internet.MimeMessage)) + javax.mail.internet.MimeMessage + javax.mail.internet.MimeMultipart)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Email Building @@ -205,8 +203,7 @@ (defn- build-email-template [id context] - (let [lang (:lang context :en) - subj (render-email-template-part :subj id context) + (let [subj (render-email-template-part :subj id context) text (render-email-template-part :txt id context) html (render-email-template-part :html id context)] (when (or (not subj) diff --git a/backend/src/app/util/http.clj b/backend/src/app/util/http.clj index e2f46493b2..fa8d5be28e 100644 --- a/backend/src/app/util/http.clj +++ b/backend/src/app/util/http.clj @@ -2,14 +2,16 @@ ;; 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) 2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.http "Http client abstraction layer." (:require - [promesa.core :as p] - [promesa.exec :as px] - [java-http-clj.core :as http])) + [java-http-clj.core :as http] + [promesa.exec :as px])) (def default-client (delay (http/build-client {:executor @px/default-executor}))) diff --git a/backend/src/app/util/migrations.clj b/backend/src/app/util/migrations.clj index 479ffb7a2d..9829082bc5 100644 --- a/backend/src/app/util/migrations.clj +++ b/backend/src/app/util/migrations.clj @@ -2,13 +2,16 @@ ;; 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) 2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.migrations (:require - [clojure.tools.logging :as log] [clojure.java.io :as io] [clojure.spec.alpha :as s] + [clojure.tools.logging :as log] [cuerdas.core :as str] [next.jdbc :as jdbc])) @@ -45,7 +48,7 @@ ((:fn migration) pool)))) (defn- impl-migrate - [conn migrations {:keys [fake] :or {fake false}}] + [conn migrations _opts] (s/assert ::migrations migrations) (let [mname (:name migrations) steps (:steps migrations)] diff --git a/backend/src/app/util/redis.clj b/backend/src/app/util/redis.clj index 1c69911326..0be8b5b465 100644 --- a/backend/src/app/util/redis.clj +++ b/backend/src/app/util/redis.clj @@ -2,14 +2,17 @@ ;; 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) 2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.redis "Asynchronous posgresql client." (:refer-clojure :exclude [run!]) (:require - [promesa.core :as p] - [clojure.core.async :as a]) + [clojure.core.async :as a] + [promesa.core :as p]) (:import io.lettuce.core.RedisClient io.lettuce.core.RedisURI @@ -18,7 +21,6 @@ io.lettuce.core.api.StatefulRedisConnection io.lettuce.core.pubsub.RedisPubSubListener io.lettuce.core.pubsub.StatefulRedisPubSubConnection - io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands io.lettuce.core.pubsub.api.sync.RedisPubSubCommands )) @@ -87,7 +89,7 @@ output)) (defn subscribe - [{:keys [uri] :as client} {:keys [topic topics xform]}] + [{:keys [uri] :as client} {:keys [topics xform]}] (let [topics (if (vector? topics) (into-array String (map str topics)) (into-array String [(str topics)]))] @@ -100,7 +102,7 @@ true false)) -(defmulti impl-run (fn [conn cmd parmas] cmd)) +(defmulti impl-run (fn [_ cmd _] cmd)) (defn run! [conn cmd params] diff --git a/backend/src/app/util/sql.clj b/backend/src/app/util/sql.clj index f61e2963d9..61274db155 100644 --- a/backend/src/app/util/sql.clj +++ b/backend/src/app/util/sql.clj @@ -164,7 +164,7 @@ (defn- process-param-tokens [sql] (let [cnt (java.util.concurrent.atomic.AtomicInteger. 1)] - (str/replace sql #"\?" (fn [& args] + (str/replace sql #"\?" (fn [& _args] (str "$" (.getAndIncrement cnt)))))) (def ^:private select-formatters diff --git a/backend/src/app/util/storage.clj b/backend/src/app/util/storage.clj index b4329df3ca..e9b28d062d 100644 --- a/backend/src/app/util/storage.clj +++ b/backend/src/app/util/storage.clj @@ -5,7 +5,7 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.storage "A local filesystem storage implementation." @@ -16,17 +16,14 @@ [clojure.java.io :as io] [clojure.spec.alpha :as s] [cuerdas.core :as str] - [datoteka.core :as fs] - [datoteka.proto :as fp]) + [datoteka.core :as fs]) (:import java.io.ByteArrayInputStream java.io.InputStream java.io.OutputStream java.net.URI - java.nio.file.Files java.nio.file.NoSuchFileException - java.nio.file.Path - java.security.MessageDigest)) + java.nio.file.Path)) (defn uri [v] @@ -54,7 +51,7 @@ (defn- transform-path [storage ^Path path] (if-let [xf (::xf storage)] - ((xf (fn [a b] b)) nil path) + ((xf (fn [_ b] b)) nil path) path)) (defn blob @@ -89,7 +86,7 @@ (normalize-path (::base-path storage)) (fs/delete)) true - (catch java.nio.file.NoSuchFileException e + (catch NoSuchFileException _e false))) (defn clear! diff --git a/backend/src/app/util/svg.clj b/backend/src/app/util/svg.clj index bb37d83b83..04d404a813 100644 --- a/backend/src/app/util/svg.clj +++ b/backend/src/app/util/svg.clj @@ -2,21 +2,23 @@ ;; 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) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.svg "Icons SVG parsing helpers." (:require - [clojure.spec.alpha :as s] - [cuerdas.core :as str] + [app.common.exceptions :as ex] [app.common.spec :as us] - [app.common.exceptions :as ex]) + [clojure.spec.alpha :as s] + [cuerdas.core :as str]) (:import org.jsoup.Jsoup org.jsoup.nodes.Attribute org.jsoup.nodes.Element - org.jsoup.nodes.Document - java.io.InputStream)) + org.jsoup.nodes.Document)) (s/def ::content string?) (s/def ::width ::us/number) @@ -65,19 +67,19 @@ content (.html element) attrs (parse-attrs element)] (assoc attrs :content content)) - (catch java.lang.IllegalArgumentException e + (catch java.lang.IllegalArgumentException _e (ex/raise :type :validation :code ::invalid-input :message "Input does not seems to be a valid svg.")) - (catch java.lang.NullPointerException e + (catch java.lang.NullPointerException _e (ex/raise :type :validation :code ::invalid-input :message "Input does not seems to be a valid svg.")) - (catch org.jsoup.UncheckedIOException e + (catch org.jsoup.UncheckedIOException _e (ex/raise :type :validation :code ::invalid-input :message "Input does not seems to be a valid svg.")) - (catch Exception e + (catch Exception _e (ex/raise :type :internal :code ::unexpected)))) diff --git a/backend/src/app/util/template.clj b/backend/src/app/util/template.clj index 0148c98945..f2dc3facd8 100644 --- a/backend/src/app/util/template.clj +++ b/backend/src/app/util/template.clj @@ -2,18 +2,17 @@ ;; 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) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.template "A lightweight abstraction over mustache.java template engine. The documentation can be found: http://mustache.github.io/mustache.5.html" (:require - [clojure.tools.logging :as log] - [clojure.walk :as walk] - [clojure.java.io :as io] - [cuerdas.core :as str] - [selmer.parser :as sp] - [app.common.exceptions :as ex])) + [app.common.exceptions :as ex] + [selmer.parser :as sp])) ;; (sp/cache-off!) diff --git a/backend/src/app/util/time.clj b/backend/src/app/util/time.clj index c855afd247..e8d62d8778 100644 --- a/backend/src/app/util/time.clj +++ b/backend/src/app/util/time.clj @@ -5,12 +5,12 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2016-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.util.time (:require - [clojure.spec.alpha :as s] [app.common.exceptions :as ex] + [clojure.spec.alpha :as s] [cognitect.transit :as t]) (:import java.time.Instant @@ -106,7 +106,7 @@ (string? v) (try (parse-duration v) - (catch java.time.format.DateTimeParseException e + (catch java.time.format.DateTimeParseException _e ::s/invalid)) :else diff --git a/backend/src/app/util/transit.clj b/backend/src/app/util/transit.clj index e188e9b041..59630313df 100644 --- a/backend/src/app/util/transit.clj +++ b/backend/src/app/util/transit.clj @@ -9,13 +9,11 @@ (ns app.util.transit (:require - [cognitect.transit :as t] - [clojure.java.io :as io] - [linked.core :as lk] - [app.util.time :as dt] - [app.util.data :as data] + [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.matrix :as gmt]) + [app.util.time :as dt] + [cognitect.transit :as t] + [linked.core :as lk]) (:import linked.set.LinkedSet java.io.ByteArrayInputStream diff --git a/backend/src/app/worker.clj b/backend/src/app/worker.clj index 4c0084f10f..b3bd38016a 100644 --- a/backend/src/app/worker.clj +++ b/backend/src/app/worker.clj @@ -15,12 +15,11 @@ [app.db :as db] [app.tasks.delete-object] [app.tasks.delete-profile] - [app.tasks.remove-media] [app.tasks.maintenance] + [app.tasks.remove-media] [app.tasks.sendmail] [app.tasks.trim-file] [app.util.async :as aa] - [app.util.blob :as blob] [app.util.time :as dt] [clojure.core.async :as a] [clojure.spec.alpha :as s] @@ -31,10 +30,7 @@ org.eclipse.jetty.util.thread.QueuedThreadPool java.util.concurrent.ExecutorService java.util.concurrent.Executors - java.util.concurrent.Executor - java.time.Duration - java.time.Instant - java.util.Date)) + java.time.Instant)) (declare start-scheduler-worker!) (declare start-worker!) @@ -149,7 +145,7 @@ nil)))) (defn- run-task - [{:keys [tasks conn]} item] + [{:keys [tasks]} item] (try (log/debugf "Started task '%s/%s/%s'." (:name item) (:id item) (:retry-num item)) (handle-task tasks item) @@ -187,7 +183,7 @@ for update skip locked") (defn- event-loop-fn* - [{:keys [tasks executor batch-size] :as opts}] + [{:keys [executor batch-size] :as opts}] (db/with-atomic [conn db/pool] (let [queue (:queue opts "default") items (->> (db/exec! conn [sql:select-next-tasks queue batch-size]) @@ -222,7 +218,7 @@ :opt-un [::poll-interval])) (defn start-worker! - [{:keys [poll-interval executor] + [{:keys [poll-interval] :or {poll-interval 5000} :as opts}] (us/assert ::start-worker-params opts) @@ -290,7 +286,7 @@ do update set cron_expr=?") (defn- synchronize-schedule-item - [conn {:keys [id cron] :as item}] + [conn {:keys [id cron]}] (let [cron (str cron)] (log/debugf "Initialize scheduled task '%s' (cron: '%s')." id cron) (db/exec-one! conn [sql:upsert-scheduled-task id cron cron]))) @@ -311,7 +307,7 @@ (.printStackTrace ^Throwable error (java.io.PrintWriter. *out*)))) (defn- execute-scheduled-task - [{:keys [scheduler executor] :as opts} {:keys [id cron] :as task}] + [{:keys [executor] :as opts} {:keys [id] :as task}] (letfn [(run-task [conn] (try (when (db/exec-one! conn [sql:lock-scheduled-task id]) @@ -384,7 +380,7 @@ (defn thread-pool ([] (thread-pool {})) - ([{:keys [min-threads max-threads idle-timeout name] + ([{:keys [min-threads max-threads name] :or {min-threads 0 max-threads 128 idle-timeout 60000}}] (let [executor (QueuedThreadPool. max-threads min-threads)] (.setName executor (or name "default-tp")) From 6881e3d7958b9337d8279c40014ee4c9f788ac79 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 11:24:51 +0100 Subject: [PATCH 129/195] :sparkles: Fix linter issues on backend tasks ns directory. --- backend/src/app/tasks/delete_object.clj | 10 ++++------ backend/src/app/tasks/delete_profile.clj | 11 ++--------- backend/src/app/tasks/maintenance.clj | 2 -- backend/src/app/tasks/remove_media.clj | 2 +- backend/src/app/tasks/sendmail.clj | 8 +++----- backend/src/app/tasks/trim_file.clj | 11 ++++------- 6 files changed, 14 insertions(+), 30 deletions(-) diff --git a/backend/src/app/tasks/delete_object.clj b/backend/src/app/tasks/delete_object.clj index 7bc9874a09..d50b4e1549 100644 --- a/backend/src/app/tasks/delete_object.clj +++ b/backend/src/app/tasks/delete_object.clj @@ -10,13 +10,11 @@ (ns app.tasks.delete-object "Generic task for permanent deletion of objects." (:require - [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] - [app.common.exceptions :as ex] [app.common.spec :as us] [app.db :as db] [app.metrics :as mtx] - [app.util.storage :as ust])) + [clojure.spec.alpha :as s] + [clojure.tools.logging :as log])) (s/def ::type keyword?) (s/def ::id ::us/uuid) @@ -24,10 +22,10 @@ (s/def ::props (s/keys :req-un [::id ::type])) -(defmulti handle-deletion (fn [conn props] (:type props))) +(defmulti handle-deletion (fn [_ props] (:type props))) (defmethod handle-deletion :default - [conn {:keys [type id] :as props}] + [_conn {:keys [type]}] (log/warn "no handler found for" type)) (defn handler diff --git a/backend/src/app/tasks/delete_profile.clj b/backend/src/app/tasks/delete_profile.clj index a9304fb506..c1fe70728d 100644 --- a/backend/src/app/tasks/delete_profile.clj +++ b/backend/src/app/tasks/delete_profile.clj @@ -10,13 +10,11 @@ (ns app.tasks.delete-profile "Task for permanent deletion of profiles." (:require - [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] - [app.common.exceptions :as ex] [app.common.spec :as us] [app.db :as db] [app.metrics :as mtx] - [app.util.storage :as ust])) + [clojure.spec.alpha :as s] + [clojure.tools.logging :as log])) (declare delete-profile-data) (declare delete-teams) @@ -51,11 +49,6 @@ (delete-files conn profile-id) (delete-profile conn profile-id)) -(def ^:private sql:select-profile - "select id, is_demo, deleted_at - from profile - where id=? for update") - (def ^:private sql:remove-owned-teams "with teams as ( select distinct diff --git a/backend/src/app/tasks/maintenance.clj b/backend/src/app/tasks/maintenance.clj index be344a5e9a..786bdd6a66 100644 --- a/backend/src/app/tasks/maintenance.clj +++ b/backend/src/app/tasks/maintenance.clj @@ -10,8 +10,6 @@ (ns app.tasks.maintenance (:require [app.common.spec :as us] - [app.common.exceptions :as ex] - [app.config :as cfg] [app.db :as db] [app.metrics :as mtx] [app.util.time :as dt] diff --git a/backend/src/app/tasks/remove_media.clj b/backend/src/app/tasks/remove_media.clj index e4020e081b..a517aadd2b 100644 --- a/backend/src/app/tasks/remove_media.clj +++ b/backend/src/app/tasks/remove_media.clj @@ -73,7 +73,7 @@ returning *") (defn trim-media-storage - [{:keys [props] :as task}] + [_task] (letfn [(decode-row [{:keys [data] :as row}] (cond-> row (db/pgobject? data) (assoc :data (db/decode-pgobject data)))) diff --git a/backend/src/app/tasks/sendmail.clj b/backend/src/app/tasks/sendmail.clj index 54706b487e..c078f2c1e1 100644 --- a/backend/src/app/tasks/sendmail.clj +++ b/backend/src/app/tasks/sendmail.clj @@ -9,12 +9,10 @@ (ns app.tasks.sendmail (:require - [clojure.tools.logging :as log] - [app.common.data :as d] - [app.common.exceptions :as ex] - [app.util.emails :as emails] [app.config :as cfg] - [app.metrics :as mtx])) + [app.metrics :as mtx] + [app.util.emails :as emails] + [clojure.tools.logging :as log])) (defn- send-console! [config email] diff --git a/backend/src/app/tasks/trim_file.clj b/backend/src/app/tasks/trim_file.clj index 80608726ad..e135953a49 100644 --- a/backend/src/app/tasks/trim_file.clj +++ b/backend/src/app/tasks/trim_file.clj @@ -9,15 +9,12 @@ (ns app.tasks.trim-file (:require - [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] - [app.common.exceptions :as ex] - [app.common.spec :as us] [app.config :as cfg] [app.db :as db] [app.tasks :as tasks] [app.util.blob :as blob] - [app.util.time :as dt])) + [app.util.time :as dt] + [clojure.tools.logging :as log])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Task: Trim File @@ -27,7 +24,7 @@ ;; associated with file but not used by any page. (defn decode-row - [{:keys [data metadata changes] :as row}] + [{:keys [data] :as row}] (cond-> row (bytes? data) (assoc :data (blob/decode data)))) @@ -90,7 +87,7 @@ nil))) (defn handler - [{:keys [props] :as task}] + [_task] (log/debug "Running 'trim-file' task.") (loop [] (let [files (retrieve-candidates db/pool)] From 44a21de7830e48968a4cee9bfbef9729014d1370 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 12:36:08 +0100 Subject: [PATCH 130/195] :sparkles: Fix all linter issues on backend code. --- .clj-kondo/config.edn | 8 ++++ backend/src/app/cli/fixtures.clj | 9 ++--- backend/src/app/cli/media_loader.clj | 30 +++++++------- backend/src/app/config.clj | 8 ++-- backend/src/app/db.clj | 8 ++-- backend/src/app/emails.clj | 9 ++--- backend/src/app/http.clj | 10 ++--- backend/src/app/http/auth.clj | 16 ++++---- backend/src/app/http/auth/gitlab.clj | 6 +-- backend/src/app/http/auth/google.clj | 8 ++-- backend/src/app/http/auth/ldap.clj | 29 +++++++++----- backend/src/app/http/debug.clj | 24 ------------ backend/src/app/http/errors.clj | 19 ++++----- backend/src/app/http/handlers.clj | 3 -- backend/src/app/http/middleware.clj | 17 ++++---- backend/src/app/http/ws.clj | 12 +++--- backend/src/app/main.clj | 4 +- backend/src/app/media.clj | 12 +++--- backend/src/app/media_storage.clj | 13 ++++--- backend/src/app/metrics.clj | 5 +-- backend/src/app/migrations.clj | 5 +-- backend/src/app/redis.clj | 12 +++--- backend/src/app/services/middleware.clj | 10 ++--- .../src/app/services/mutations/comments.clj | 30 +++++++------- backend/src/app/services/mutations/demo.clj | 9 ++--- backend/src/app/services/mutations/files.clj | 17 ++++---- backend/src/app/services/mutations/media.clj | 11 ++---- .../src/app/services/mutations/profile.clj | 16 +++----- .../src/app/services/mutations/projects.clj | 19 ++++----- backend/src/app/services/mutations/teams.clj | 6 +-- .../app/services/mutations/verify_token.clj | 39 +++++++------------ backend/src/app/services/mutations/viewer.clj | 3 -- backend/src/app/services/notifications.clj | 27 ++++++------- backend/src/app/services/queries/comments.clj | 11 +----- backend/src/app/services/queries/files.clj | 10 ++--- backend/src/app/services/queries/projects.clj | 6 +-- .../src/app/services/queries/recent_files.clj | 10 ++--- backend/src/app/services/queries/teams.clj | 6 +-- backend/src/app/services/tokens.clj | 5 --- backend/src/app/srepl/main.clj | 1 + backend/src/app/srepl/server.clj | 14 +++++-- backend/src/app/tasks.clj | 1 - backend/src/app/worker.clj | 5 +-- 43 files changed, 219 insertions(+), 304 deletions(-) delete mode 100644 backend/src/app/http/debug.clj diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index bd1a5d82c4..5201014d55 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -1,10 +1,17 @@ {:lint-as {potok.core/reify clojure.core/reify promesa.core/let clojure.core/let app.db/with-atomic clojure.core/with-open} + :output + {:exclude-files ["data_readers.clj"]} + :linters {:unsorted-required-namespaces {:level :warning} + :unresolved-namespace + {:level :warning + :exclude [data_readers]} + :single-key-in {:level :warning} @@ -16,6 +23,7 @@ :unresolved-symbol {:exclude ['(app.services.mutations/defmutation) '(app.services.queries/defquery) + '(app.util.dispatcher/defservice) '(mount.core/defstate) ]}}} diff --git a/backend/src/app/cli/fixtures.clj b/backend/src/app/cli/fixtures.clj index 5e5c9f07fd..9c1997581a 100644 --- a/backend/src/app/cli/fixtures.clj +++ b/backend/src/app/cli/fixtures.clj @@ -10,17 +10,16 @@ (ns app.cli.fixtures "A initial fixtures." (:require - [clojure.tools.logging :as log] - [mount.core :as mount] - [buddy.hashers :as hashers] - [app.common.data :as d] [app.common.pages :as cp] [app.common.uuid :as uuid] [app.config :as cfg] [app.db :as db] [app.migrations] [app.services.mutations.profile :as profile] - [app.util.blob :as blob])) + [app.util.blob :as blob] + [buddy.hashers :as hashers] + [clojure.tools.logging :as log] + [mount.core :as mount])) (defn- mk-uuid [prefix & args] diff --git a/backend/src/app/cli/media_loader.clj b/backend/src/app/cli/media_loader.clj index e038f4eb44..946fd88801 100644 --- a/backend/src/app/cli/media_loader.clj +++ b/backend/src/app/cli/media_loader.clj @@ -5,27 +5,27 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2016-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.cli.media-loader "Media libraries importer (command line helper)." - (:require - [clojure.tools.logging :as log] - [clojure.spec.alpha :as s] - [clojure.java.io :as io] - [mount.core :as mount] - [datoteka.core :as fs] - [app.config] + #_(:require [app.common.spec :as us] - [app.db :as db] - [app.media] - [app.media-storage] - [app.migrations] [app.common.uuid :as uuid] - [app.services.mutations.projects :as projects] + [app.config] + [app.db :as db] + [app.media-storage] + [app.media] + [app.migrations] [app.services.mutations.files :as files] - [app.services.mutations.media :as media]) - (:import + [app.services.mutations.media :as media] + [app.services.mutations.projects :as projects] + [clojure.java.io :as io] + [clojure.spec.alpha :as s] + [clojure.tools.logging :as log] + [datoteka.core :as fs] + [mount.core :as mount]) + #_(:import java.io.PushbackReader)) ;; --- Constants & Helpers diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index 9a6802d067..a590eb5516 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -10,14 +10,12 @@ (ns app.config "A configuration management." (:require + [app.common.spec :as us] + [app.util.time :as dt] [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] [cuerdas.core :as str] [environ.core :refer [env]] - [mount.core :refer [defstate]] - [app.common.exceptions :as ex] - [app.common.spec :as us] - [app.util.time :as dt])) + [mount.core :refer [defstate]])) (def defaults {:http-server-port 6060 diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj index 74b41e858e..a40318a990 100644 --- a/backend/src/app/db.clj +++ b/backend/src/app/db.clj @@ -13,19 +13,15 @@ [app.common.geom.point :as gpt] [app.config :as cfg] [app.metrics :as mtx] - [app.util.data :as data] [app.util.time :as dt] [app.util.transit :as t] [clojure.data.json :as json] [clojure.spec.alpha :as s] [clojure.string :as str] - [clojure.tools.logging :as log] - [lambdaisland.uri :refer [uri]] [mount.core :as mount :refer [defstate]] [next.jdbc :as jdbc] [next.jdbc.date-time :as jdbc-dt] [next.jdbc.optional :as jdbc-opt] - [next.jdbc.result-set :as jdbc-rs] [next.jdbc.sql :as jdbc-sql] [next.jdbc.sql.builder :as jdbc-bld]) (:import @@ -34,8 +30,8 @@ com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory java.sql.Connection java.sql.Savepoint - org.postgresql.jdbc.PgArray org.postgresql.geometric.PGpoint + org.postgresql.jdbc.PgArray org.postgresql.util.PGInterval org.postgresql.util.PGobject)) @@ -83,6 +79,8 @@ (jdbc-dt/read-as-instant) (HikariDataSource. dsc))) +(declare pool) + (defstate pool :start (create-pool cfg/config) :stop (.close pool)) diff --git a/backend/src/app/emails.clj b/backend/src/app/emails.clj index 5d471add07..d6408b8e4d 100644 --- a/backend/src/app/emails.clj +++ b/backend/src/app/emails.clj @@ -10,14 +10,11 @@ (ns app.emails "Main api for send emails." (:require - [clojure.spec.alpha :as s] - [promesa.core :as p] - [app.config :as cfg] - [app.common.exceptions :as ex] [app.common.spec :as us] - [app.db :as db] + [app.config :as cfg] [app.tasks :as tasks] - [app.util.emails :as emails])) + [app.util.emails :as emails] + [clojure.spec.alpha :as s])) ;; --- Defaults diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index eed57f9050..c263304bc6 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -9,23 +9,21 @@ (ns app.http (:require - [clojure.tools.logging :as log] - [mount.core :as mount :refer [defstate]] - [reitit.ring :as rring] - [ring.adapter.jetty9 :as jetty] [app.config :as cfg] [app.http.auth :as auth] [app.http.auth.gitlab :as gitlab] [app.http.auth.google :as google] [app.http.auth.ldap :as ldap] - [app.http.debug :as debug] [app.http.errors :as errors] [app.http.handlers :as handlers] [app.http.middleware :as middleware] [app.http.session :as session] [app.http.ws :as ws] [app.metrics :as mtx] - [app.services.notifications :as usn])) + [clojure.tools.logging :as log] + [mount.core :as mount :refer [defstate]] + [reitit.ring :as rring] + [ring.adapter.jetty9 :as jetty])) (defn- create-router [] diff --git a/backend/src/app/http/auth.clj b/backend/src/app/http/auth.clj index a4113ef84b..cf7f8ce737 100644 --- a/backend/src/app/http/auth.clj +++ b/backend/src/app/http/auth.clj @@ -9,20 +9,18 @@ (ns app.http.auth (:require - [app.common.exceptions :as ex] - [app.common.uuid :as uuid] [app.http.session :as session] [app.services.mutations :as sm])) (defn login-handler [req] - (let [data (:body-params req) - uagent (get-in req [:headers "user-agent"])] - (let [profile (sm/handle (assoc data ::sm/type :login)) - id (session/create (:id profile) uagent)] - {:status 200 - :cookies (session/cookies id) - :body profile}))) + (let [data (:body-params req) + uagent (get-in req [:headers "user-agent"]) + profile (sm/handle (assoc data ::sm/type :login)) + id (session/create (:id profile) uagent)] + {:status 200 + :cookies (session/cookies id) + :body profile})) (defn logout-handler [req] diff --git a/backend/src/app/http/auth/gitlab.clj b/backend/src/app/http/auth/gitlab.clj index dade853091..fd3ebcc3e0 100644 --- a/backend/src/app/http/auth/gitlab.clj +++ b/backend/src/app/http/auth/gitlab.clj @@ -11,7 +11,6 @@ (:require [app.common.exceptions :as ex] [app.config :as cfg] - [app.db :as db] [app.http.session :as session] [app.services.mutations :as sm] [app.services.tokens :as tokens] @@ -21,7 +20,6 @@ [clojure.tools.logging :as log] [lambdaisland.uri :as uri])) - (def default-base-gitlab-uri "https://gitlab.com") (def scope "read_user") @@ -100,7 +98,7 @@ nil)))) (defn auth - [req] + [_req] (let [token (tokens/generate {:iss :gitlab-oauth :exp (dt/in-future "15m")}) @@ -119,7 +117,7 @@ (defn callback [req] (let [token (get-in req [:params :state]) - tdata (tokens/verify token {:iss :gitlab-oauth}) + _ (tokens/verify token {:iss :gitlab-oauth}) info (some-> (get-in req [:params :code]) (get-access-token) (get-user-info))] diff --git a/backend/src/app/http/auth/google.clj b/backend/src/app/http/auth/google.clj index 97b24a1b9f..33fba31791 100644 --- a/backend/src/app/http/auth/google.clj +++ b/backend/src/app/http/auth/google.clj @@ -11,7 +11,6 @@ (:require [app.common.exceptions :as ex] [app.config :as cfg] - [app.db :as db] [app.http.session :as session] [app.services.mutations :as sm] [app.services.tokens :as tokens] @@ -84,9 +83,8 @@ nil)))) (defn auth - [req] - (let [token (tokens/generate {:iss :google-oauth - :exp (dt/in-future "15m")}) + [_req] + (let [token (tokens/generate {:iss :google-oauth :exp (dt/in-future "15m")}) params {:scope scope :access_type "offline" :include_granted_scopes true @@ -104,7 +102,7 @@ (defn callback [req] (let [token (get-in req [:params :state]) - tdata (tokens/verify token {:iss :google-oauth}) + _ (tokens/verify token {:iss :google-oauth}) info (some-> (get-in req [:params :code]) (get-access-token) (get-user-info))] diff --git a/backend/src/app/http/auth/ldap.clj b/backend/src/app/http/auth/ldap.clj index 1018eb44f5..1dc61b0d4b 100644 --- a/backend/src/app/http/auth/ldap.clj +++ b/backend/src/app/http/auth/ldap.clj @@ -1,18 +1,29 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + (ns app.http.auth.ldap (:require - [clj-ldap.client :as client] - [clojure.set :as set] - [mount.core :refer [defstate]] - [app.common.exceptions :as ex] - [app.config :as cfg] - [app.services.mutations :as sm] - [app.http.session :as session] - [clojure.tools.logging :as log])) - + [app.common.exceptions :as ex] + [app.config :as cfg] + [app.http.session :as session] + [app.services.mutations :as sm] + [clj-ldap.client :as client] + [clojure.set :as set] + [clojure.string] + [clojure.tools.logging :as log] + [mount.core :refer [defstate]])) (defn replace-several [s & {:as replacements}] (reduce-kv clojure.string/replace s replacements)) +(declare *ldap-pool) + (defstate *ldap-pool :start (delay (try diff --git a/backend/src/app/http/debug.clj b/backend/src/app/http/debug.clj deleted file mode 100644 index e0df75670f..0000000000 --- a/backend/src/app/http/debug.clj +++ /dev/null @@ -1,24 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) 2019 Andrey Antukh - -(ns app.http.debug - "Debug related handlers." - (:require - [clojure.tools.logging :as log] - [promesa.core :as p] - [app.http.errors :as errors] - [app.http.session :as session] - [app.common.uuid :as uuid])) - -(defn emails-list - [req] - {:status 200 - :body "Hello world\n"}) - -(defn email - [req] - {:status 200 - :body "Hello world\n"}) diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index d723b28c6b..36754f8c8b 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -2,23 +2,24 @@ ;; 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) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL (ns app.http.errors "A errors handling for the http server." (:require [clojure.tools.logging :as log] - [cuerdas.core :as str] - [app.metrics :as mtx] - [io.aviso.exception :as e])) + [cuerdas.core :as str])) (defmulti handle-exception - (fn [err & rest] + (fn [err & _rest] (:type (ex-data err)))) (defmethod handle-exception :authorization - [err req] + [err _] {:status 403 :body (ex-data err)}) @@ -38,13 +39,13 @@ :body response}))) (defmethod handle-exception :ratelimit - [err req] + [_ _] {:status 429 :headers {"retry-after" 1000} :body ""}) (defmethod handle-exception :not-found - [err req] + [err _] (let [response (ex-data err)] {:status 404 :body response})) @@ -54,7 +55,7 @@ (handle-exception (.getCause ^Throwable err) req)) (defmethod handle-exception :parse - [err req] + [err _] {:status 400 :body {:type :parse :message (ex-message err)}}) diff --git a/backend/src/app/http/handlers.clj b/backend/src/app/http/handlers.clj index f859b7a362..3d38551756 100644 --- a/backend/src/app/http/handlers.clj +++ b/backend/src/app/http/handlers.clj @@ -9,9 +9,6 @@ (ns app.http.handlers (:require - [app.common.exceptions :as ex] - [app.emails :as emails] - [app.http.session :as session] [app.services.init] [app.services.mutations :as sm] [app.services.queries :as sq])) diff --git a/backend/src/app/http/middleware.clj b/backend/src/app/http/middleware.clj index ab02d96758..e2fafae1ae 100644 --- a/backend/src/app/http/middleware.clj +++ b/backend/src/app/http/middleware.clj @@ -5,20 +5,19 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2019-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.http.middleware (:require - [clojure.tools.logging :as log] + [app.common.exceptions :as ex] + [app.config :as cfg] + [app.metrics :as mtx] + [app.util.transit :as t] [ring.middleware.cookies :refer [wrap-cookies]] [ring.middleware.keyword-params :refer [wrap-keyword-params]] [ring.middleware.multipart-params :refer [wrap-multipart-params]] [ring.middleware.params :refer [wrap-params]] - [ring.middleware.resource :refer [wrap-resource]] - [app.metrics :as mtx] - [app.common.exceptions :as ex] - [app.config :as cfg] - [app.util.transit :as t])) + [ring.middleware.resource :refer [wrap-resource]])) (defn- wrap-parse-request-body [handler] @@ -126,13 +125,13 @@ (def development-cors {:name ::development-cors - :compile (fn [& args] + :compile (fn [& _args] (when *assert* wrap-development-cors))}) (def development-resources {:name ::development-resources - :compile (fn [& args] + :compile (fn [& _args] (when *assert* #(wrap-resource % "public")))}) diff --git a/backend/src/app/http/ws.clj b/backend/src/app/http/ws.clj index c470776943..0f54a0d23e 100644 --- a/backend/src/app/http/ws.clj +++ b/backend/src/app/http/ws.clj @@ -10,16 +10,14 @@ (ns app.http.ws "Web Socket handlers" (:require - [clojure.spec.alpha :as s] - [clojure.tools.logging :as log] - [ring.adapter.jetty9 :as jetty] - [ring.middleware.cookies :refer [wrap-cookies]] - [ring.middleware.keyword-params :refer [wrap-keyword-params]] - [ring.middleware.params :refer [wrap-params]] [app.common.spec :as us] [app.db :as db] [app.http.session :refer [wrap-session]] - [app.services.notifications :as nf])) + [app.services.notifications :as nf] + [clojure.spec.alpha :as s] + [ring.middleware.cookies :refer [wrap-cookies]] + [ring.middleware.keyword-params :refer [wrap-keyword-params]] + [ring.middleware.params :refer [wrap-params]])) (s/def ::file-id ::us/uuid) (s/def ::session-id ::us/uuid) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 454cc68bfc..a782b91187 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -25,7 +25,7 @@ ;; --- Entry point (defn run - [params] + [_params] (require 'app.config 'app.srepl.server 'app.migrations @@ -37,5 +37,5 @@ (defn -main - [& args] + [& _args] (run {})) diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index dd8002e713..51b7186d35 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -10,14 +10,11 @@ (ns app.media "Media postprocessing." (:require - [app.common.data :as d] [app.common.exceptions :as ex] [app.common.media :as cm] [app.common.spec :as us] [app.config :as cfg] - [app.media-storage :as mst] [app.util.http :as http] - [app.util.storage :as ust] [clojure.core.async :as a] [clojure.java.io :as io] [clojure.spec.alpha :as s] @@ -25,11 +22,12 @@ [mount.core :refer [defstate]]) (:import java.io.ByteArrayInputStream - java.io.InputStream java.util.concurrent.Semaphore org.im4java.core.ConvertCmd - org.im4java.core.Info - org.im4java.core.IMOperation)) + org.im4java.core.IMOperation + org.im4java.core.Info)) + +(declare semaphore) (defstate semaphore :start (Semaphore. (:image-process-max-threads cfg/config 1))) @@ -73,7 +71,7 @@ ;; http://www.imagemagick.org/Usage/thumbnails/ (defn- generic-process - [{:keys [input format quality operation] :as params}] + [{:keys [input format operation] :as params}] (let [{:keys [path mtype]} input format (or (cm/mtype->format mtype) format) ext (cm/format->extension format) diff --git a/backend/src/app/media_storage.clj b/backend/src/app/media_storage.clj index 3accc30267..df763c9991 100644 --- a/backend/src/app/media_storage.clj +++ b/backend/src/app/media_storage.clj @@ -5,24 +5,25 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2017-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.media-storage "A media storage impl for app." (:require - [mount.core :refer [defstate]] - [clojure.java.io :as io] - [cuerdas.core :as str] - [datoteka.core :as fs] + [app.config :refer [config]] [app.util.storage :as ust] - [app.config :refer [config]])) + [mount.core :refer [defstate]])) ;; --- State +(declare assets-storage) + (defstate assets-storage :start (ust/create {:base-path (:assets-directory config) :base-uri (:assets-uri config)})) +(declare media-storage) + (defstate media-storage :start (ust/create {:base-path (:media-directory config) :base-uri (:media-uri config) diff --git a/backend/src/app/metrics.clj b/backend/src/app/metrics.clj index 39d08970c1..4f9a30ad2a 100644 --- a/backend/src/app/metrics.clj +++ b/backend/src/app/metrics.clj @@ -8,9 +8,6 @@ ;; Copyright (c) 2020 UXBOX Labs SL (ns app.metrics - (:require - [clojure.tools.logging :as log] - [cuerdas.core :as str]) (:import io.prometheus.client.CollectorRegistry io.prometheus.client.Counter @@ -172,7 +169,7 @@ (assoc mdata ::summary-original original))))))) (defn dump - [& args] + [& _args] (let [samples (.metricFamilySamples ^CollectorRegistry registry) writer (StringWriter.)] (TextFormat/write004 writer samples) diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index 6c9ebdba2d..94d3aaa3ac 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -9,11 +9,10 @@ (ns app.migrations (:require - [mount.core :as mount :refer [defstate]] [app.db :as db] - [app.config :as cfg] [app.migrations.migration-0023 :as mg0023] - [app.util.migrations :as mg])) + [app.util.migrations :as mg] + [mount.core :as mount :refer [defstate]])) (def +migrations+ {:name "uxbox-main" diff --git a/backend/src/app/redis.clj b/backend/src/app/redis.clj index 39345e5a19..3edb30047d 100644 --- a/backend/src/app/redis.clj +++ b/backend/src/app/redis.clj @@ -7,13 +7,9 @@ (ns app.redis (:refer-clojure :exclude [run!]) (:require - [clojure.tools.logging :as log] - [lambdaisland.uri :refer [uri]] - [mount.core :as mount :refer [defstate]] - [app.common.exceptions :as ex] [app.config :as cfg] - [app.util.data :as data] - [app.util.redis :as redis]) + [app.util.redis :as redis] + [mount.core :as mount :refer [defstate]]) (:import java.lang.AutoCloseable)) @@ -24,10 +20,14 @@ (let [uri (:redis-uri config "redis://redis/0")] (redis/client uri))) +(declare client) + (defstate client :start (create-client cfg/config) :stop (.close ^AutoCloseable client)) +(declare conn) + (defstate conn :start (redis/connect client) :stop (.close ^AutoCloseable conn)) diff --git a/backend/src/app/services/middleware.clj b/backend/src/app/services/middleware.clj index 098020b756..916d791a66 100644 --- a/backend/src/app/services/middleware.clj +++ b/backend/src/app/services/middleware.clj @@ -10,13 +10,11 @@ (ns app.services.middleware "Common middleware for services." (:require - [clojure.tools.logging :as log] - [clojure.spec.alpha :as s] - [cuerdas.core :as str] - [expound.alpha :as expound] [app.common.exceptions :as ex] [app.common.spec :as us] - [app.metrics :as mtx])) + [app.metrics :as mtx] + [clojure.spec.alpha :as s] + [cuerdas.core :as str])) (defn wrap-spec [handler] @@ -45,7 +43,7 @@ (defn- get-prefix [nsname] - (let [[a b c] (str/split nsname ".")] + (let [[_ _ c] (str/split nsname ".")] c)) (defn wrap-metrics diff --git a/backend/src/app/services/mutations/comments.clj b/backend/src/app/services/mutations/comments.clj index 5838ab7c52..b30f510818 100644 --- a/backend/src/app/services/mutations/comments.clj +++ b/backend/src/app/services/mutations/comments.clj @@ -9,21 +9,15 @@ (ns app.services.mutations.comments (:require - [clojure.spec.alpha :as s] [app.common.exceptions :as ex] [app.common.spec :as us] - [app.common.uuid :as uuid] - [app.config :as cfg] [app.db :as db] [app.services.mutations :as sm] - [app.services.queries.projects :as proj] - [app.services.queries.files :as files] [app.services.queries.comments :as comments] - [app.tasks :as tasks] + [app.services.queries.files :as files] [app.util.blob :as blob] - [app.util.storage :as ust] - [app.util.transit :as t] - [app.util.time :as dt])) + [app.util.time :as dt] + [clojure.spec.alpha :as s])) ;; --- Mutation: Create Comment Thread @@ -66,14 +60,16 @@ :created-at now :modified-at now :seqn seqn - :position (db/pgpoint position)}) - ;; Create a comment entry - comment (db/insert! conn :comment - {:thread-id (:id thread) - :owner-id profile-id - :created-at now - :modified-at now - :content content})] + :position (db/pgpoint position)})] + + + ;; Create a comment entry + (db/insert! conn :comment + {:thread-id (:id thread) + :owner-id profile-id + :created-at now + :modified-at now + :content content}) ;; Make the current thread as read. (upsert-comment-thread-status! conn profile-id (:id thread)) diff --git a/backend/src/app/services/mutations/demo.clj b/backend/src/app/services/mutations/demo.clj index 839deae817..95471c13f7 100644 --- a/backend/src/app/services/mutations/demo.clj +++ b/backend/src/app/services/mutations/demo.clj @@ -10,17 +10,14 @@ (ns app.services.mutations.demo "A demo specific mutations." (:require - [clojure.spec.alpha :as s] - [buddy.core.codecs :as bc] - [buddy.core.nonce :as bn] - [app.common.exceptions :as ex] + [app.common.uuid :as uuid] [app.config :as cfg] [app.db :as db] [app.services.mutations :as sm] [app.services.mutations.profile :as profile] [app.tasks :as tasks] - [app.common.uuid :as uuid] - [app.util.time :as tm])) + [buddy.core.codecs :as bc] + [buddy.core.nonce :as bn])) (sm/defmutation ::create-demo-profile [_] diff --git a/backend/src/app/services/mutations/files.clj b/backend/src/app/services/mutations/files.clj index 38d971c0e3..ff1d243967 100644 --- a/backend/src/app/services/mutations/files.clj +++ b/backend/src/app/services/mutations/files.clj @@ -9,9 +9,6 @@ (ns app.services.mutations.files (:require - [clojure.spec.alpha :as s] - [datoteka.core :as fs] - [promesa.core :as p] [app.common.exceptions :as ex] [app.common.pages :as cp] [app.common.pages-migrations :as pmg] @@ -21,13 +18,13 @@ [app.db :as db] [app.redis :as redis] [app.services.mutations :as sm] - [app.services.queries.projects :as proj] [app.services.queries.files :as files] + [app.services.queries.projects :as proj] [app.tasks :as tasks] [app.util.blob :as blob] - [app.util.storage :as ust] + [app.util.time :as dt] [app.util.transit :as t] - [app.util.time :as dt])) + [clojure.spec.alpha :as s])) ;; --- Helpers & Specs @@ -62,7 +59,7 @@ :can-edit true})) (defn create-file - [conn {:keys [id profile-id name project-id is-shared] + [conn {:keys [id name project-id is-shared] :or {is-shared false} :as params}] (let [id (or id (uuid/next)) @@ -286,7 +283,7 @@ (assoc :changes (blob/encode changes) :session-id sid)) - chng (insert-change conn file) + _ (insert-change conn file) msg {:type :file-change :profile-id (:profile-id params) :file-id (:id file) @@ -319,7 +316,7 @@ :data (:data file)} {:id (:id file)}) - (retrieve-lagged-changes conn chng params))) + (retrieve-lagged-changes conn params))) (defn- insert-change [conn {:keys [revn data changes session-id] :as file}] @@ -343,7 +340,7 @@ order by s.created_at asc") (defn- retrieve-lagged-changes - [conn snapshot params] + [conn params] (->> (db/exec! conn [sql:lagged-changes (:id params) (:revn params)]) (mapv files/decode-row))) diff --git a/backend/src/app/services/mutations/media.clj b/backend/src/app/services/mutations/media.clj index 3dd65fb9b5..e50e7a500d 100644 --- a/backend/src/app/services/mutations/media.clj +++ b/backend/src/app/services/mutations/media.clj @@ -9,21 +9,18 @@ (ns app.services.mutations.media (:require - [clojure.spec.alpha :as s] - [datoteka.core :as fs] - [app.common.media :as cm] [app.common.exceptions :as ex] + [app.common.media :as cm] [app.common.spec :as us] [app.common.uuid :as uuid] - [app.config :as cfg] [app.db :as db] [app.media :as media] + [app.media-storage :as mst] [app.services.mutations :as sm] [app.services.queries.teams :as teams] - [app.tasks :as tasks] - [app.media-storage :as mst] [app.util.storage :as ust] - [app.util.time :as dt])) + [clojure.spec.alpha :as s] + [datoteka.core :as fs])) (def thumbnail-options {:width 100 diff --git a/backend/src/app/services/mutations/profile.clj b/backend/src/app/services/mutations/profile.clj index a2f587cac3..2585ba8111 100644 --- a/backend/src/app/services/mutations/profile.clj +++ b/backend/src/app/services/mutations/profile.clj @@ -10,24 +10,20 @@ (ns app.services.mutations.profile (:require [app.common.exceptions :as ex] - [app.common.media :as cm] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cfg] [app.db :as db] [app.emails :as emails] - [app.media :as media] - [app.media-storage :as mst] [app.http.session :as session] + [app.media :as media] [app.services.mutations :as sm] [app.services.mutations.projects :as projects] [app.services.mutations.teams :as teams] + [app.services.mutations.verify-token :refer [process-token]] [app.services.queries.profile :as profile] [app.services.tokens :as tokens] - [app.services.mutations.verify-token :refer [process-token]] [app.tasks :as tasks] - [app.util.blob :as blob] - [app.util.storage :as ust] [app.util.time :as dt] [buddy.hashers :as hashers] [clojure.spec.alpha :as s] @@ -361,7 +357,7 @@ (sm/defmutation ::request-profile-recovery [{:keys [email] :as params}] - (letfn [(create-recovery-token [conn {:keys [id] :as profile}] + (letfn [(create-recovery-token [{:keys [id] :as profile}] (let [token (tokens/generate {:iss :password-recovery :exp (dt/in-future "15m") @@ -377,7 +373,7 @@ (db/with-atomic [conn db/pool] (some->> email (profile/retrieve-profile-data-by-email conn) - (create-recovery-token conn) + (create-recovery-token) (send-email-notification conn)) nil))) @@ -390,7 +386,7 @@ (sm/defmutation ::recover-profile [{:keys [token password]}] - (letfn [(validate-token [conn token] + (letfn [(validate-token [token] (let [tdata (tokens/verify token {:iss :password-recovery})] (:profile-id tdata))) @@ -399,7 +395,7 @@ (db/update! conn :profile {:password pwd} {:id profile-id})))] (db/with-atomic [conn db/pool] - (->> (validate-token conn token) + (->> (validate-token token) (update-password conn)) nil))) diff --git a/backend/src/app/services/mutations/projects.clj b/backend/src/app/services/mutations/projects.clj index bb36b89776..211da43003 100644 --- a/backend/src/app/services/mutations/projects.clj +++ b/backend/src/app/services/mutations/projects.clj @@ -5,12 +5,10 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2019-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.services.mutations.projects (:require - [clojure.spec.alpha :as s] - [app.common.exceptions :as ex] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cfg] @@ -18,7 +16,7 @@ [app.services.mutations :as sm] [app.services.queries.projects :as proj] [app.tasks :as tasks] - [app.util.blob :as blob])) + [clojure.spec.alpha :as s])) ;; --- Helpers & Specs @@ -48,7 +46,7 @@ (assoc proj :is-pinned true)))) (defn create-project - [conn {:keys [id profile-id team-id name default?] :as params}] + [conn {:keys [id team-id name default?] :as params}] (let [id (or id (uuid/next)) default? (if (boolean? default?) default? false)] (db/insert! conn :project @@ -107,11 +105,10 @@ (sm/defmutation ::rename-project [{:keys [id profile-id name] :as params}] (db/with-atomic [conn db/pool] - (let [project (db/get-by-id conn :project id {:for-update true})] - (proj/check-edition-permissions! conn profile-id id) - (db/update! conn :project - {:name name} - {:id id})))) + (proj/check-edition-permissions! conn profile-id id) + (db/update! conn :project + {:name name} + {:id id}))) ;; --- Mutation: Delete Project @@ -139,6 +136,6 @@ returning id") (defn mark-project-deleted - [conn {:keys [id profile-id] :as params}] + [conn {:keys [id] :as params}] (db/exec! conn [sql:mark-project-deleted id]) nil) diff --git a/backend/src/app/services/mutations/teams.clj b/backend/src/app/services/mutations/teams.clj index 305b702753..a7ecdf09cf 100644 --- a/backend/src/app/services/mutations/teams.clj +++ b/backend/src/app/services/mutations/teams.clj @@ -20,9 +20,9 @@ [app.media-storage :as mst] [app.services.mutations :as sm] [app.services.mutations.projects :as projects] + [app.services.queries.profile :as profile] [app.services.queries.teams :as teams] [app.services.tokens :as tokens] - [app.services.queries.profile :as profile] [app.tasks :as tasks] [app.util.storage :as ust] [app.util.time :as dt] @@ -58,7 +58,7 @@ team))) (defn create-team - [conn {:keys [id profile-id name default?] :as params}] + [conn {:keys [id name default?] :as params}] (let [id (or id (uuid/next)) default? (if (boolean? default?) default? false)] (db/insert! conn :team @@ -268,7 +268,7 @@ (assoc team :photo (str photo))))) (defn upload-photo - [conn {:keys [file profile-id]}] + [_conn {:keys [file]}] (let [prefix (-> (bn/random-bytes 8) (bc/bytes->b64u) (bc/bytes->str)) diff --git a/backend/src/app/services/mutations/verify_token.clj b/backend/src/app/services/mutations/verify_token.clj index 638a048794..87dda705ac 100644 --- a/backend/src/app/services/mutations/verify_token.clj +++ b/backend/src/app/services/mutations/verify_token.clj @@ -10,28 +10,16 @@ (ns app.services.mutations.verify-token (:require [app.common.exceptions :as ex] - [app.common.media :as cm] [app.common.spec :as us] - [app.common.uuid :as uuid] - [app.config :as cfg] [app.db :as db] - [app.emails :as emails] [app.http.session :as session] - [app.media :as media] - [app.media-storage :as mst] [app.services.mutations :as sm] [app.services.mutations.teams :as teams] [app.services.queries.profile :as profile] [app.services.tokens :as tokens] - [app.tasks :as tasks] - [app.util.blob :as blob] - [app.util.storage :as ust] - [app.util.time :as dt] - [buddy.hashers :as hashers] - [clojure.spec.alpha :as s] - [cuerdas.core :as str])) + [clojure.spec.alpha :as s])) -(defmulti process-token (fn [conn params claims] (:iss claims))) +(defmulti process-token (fn [_ _ claims] (:iss claims))) (s/def ::verify-token (s/keys :req-un [::token] @@ -44,18 +32,17 @@ (process-token conn params claims)))) (defmethod process-token :change-email - [conn params {:keys [profile-id email] :as claims}] - (let [profile (db/get-by-id conn :profile profile-id {:for-update true})] - (when (profile/retrieve-profile-data-by-email conn email) - (ex/raise :type :validation - :code :email-already-exists)) - (db/update! conn :profile - {:email email} - {:id profile-id}) - claims)) + [conn _params {:keys [profile-id email] :as claims}] + (when (profile/retrieve-profile-data-by-email conn email) + (ex/raise :type :validation + :code :email-already-exists)) + (db/update! conn :profile + {:email email} + {:id profile-id}) + claims) (defmethod process-token :verify-email - [conn params {:keys [profile-id] :as claims}] + [conn _params {:keys [profile-id] :as claims}] (let [profile (db/get-by-id conn :profile profile-id {:for-update true})] (when (:is-active profile) (ex/raise :type :validation @@ -71,7 +58,7 @@ claims)) (defmethod process-token :auth - [conn params {:keys [profile-id] :as claims}] + [conn _params {:keys [profile-id] :as claims}] (let [profile (profile/retrieve-profile conn profile-id)] (assoc claims :profile profile))) @@ -137,7 +124,7 @@ ;; --- Default (defmethod process-token :default - [conn params claims] + [_ _ _] (ex/raise :type :validation :code :invalid-token)) diff --git a/backend/src/app/services/mutations/viewer.clj b/backend/src/app/services/mutations/viewer.clj index 71d1892600..82ebb17b16 100644 --- a/backend/src/app/services/mutations/viewer.clj +++ b/backend/src/app/services/mutations/viewer.clj @@ -9,10 +9,7 @@ (ns app.services.mutations.viewer (:require - [app.common.exceptions :as ex] - [app.common.pages :as cp] [app.common.spec :as us] - [app.config :as cfg] [app.db :as db] [app.services.mutations :as sm] [app.services.queries.files :as files] diff --git a/backend/src/app/services/notifications.clj b/backend/src/app/services/notifications.clj index 3f837c9828..4c2d18e238 100644 --- a/backend/src/app/services/notifications.clj +++ b/backend/src/app/services/notifications.clj @@ -10,17 +10,13 @@ (ns app.services.notifications "A websocket based notifications mechanism." (:require - [app.common.exceptions :as ex] - [app.common.uuid :as uuid] [app.db :as db] [app.metrics :as mtx] [app.redis :as redis] [app.util.async :as aa] - [app.util.time :as dt] [app.util.transit :as t] [clojure.core.async :as a] [clojure.tools.logging :as log] - [promesa.core :as p] [ring.adapter.jetty9 :as jetty])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -40,7 +36,7 @@ :help "A total number of messages handled by the notifications service."})) (defn websocket - [{:keys [file-id team-id profile-id] :as params}] + [{:keys [file-id team-id] :as params}] (let [in (a/chan 32) out (a/chan 32)] {:on-connect @@ -62,18 +58,18 @@ (a/close! sub)))) :on-error - (fn [conn e] + (fn [_conn _e] (a/close! out) (a/close! in)) :on-close - (fn [conn status-code reason] + (fn [_conn _status _reason] (metrics-active-connections :dec) (a/close! out) (a/close! in)) :on-text - (fn [ws message] + (fn [_ws message] (metrics-message-counter :inc) (let [message (t/decode-str message)] (a/>!! in message))) @@ -165,8 +161,7 @@ (defn- update-presence [file-id session-id profile-id] (aa/thread-try - (let [now (dt/now) - sql [sql:update-presence file-id session-id profile-id]] + (let [sql [sql:update-presence file-id session-id profile-id]] (db/exec-one! db/pool sql)))) (defn- delete-presence @@ -177,13 +172,13 @@ :session-id session-id}))) (defmulti handle-message - (fn [ws message] (:type message))) + (fn [_ message] (:type message))) ;; TODO: check permissions for join a file-id channel (probably using ;; single use token for avoid explicit database query). (defmethod handle-message :connect - [{:keys [file-id profile-id session-id output] :as ws} message] + [{:keys [file-id profile-id session-id] :as ws} _message] (log/debugf "profile '%s' is connected to file '%s'" profile-id file-id) (aa/go-try (aa/> (db/exec! conn [sql:comment-threads profile-id file-id]) (into [] (map decode-row)))) diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index 8047e37d91..73dddf0769 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -5,20 +5,18 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2019-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.services.queries.files (:require - [clojure.spec.alpha :as s] - [promesa.core :as p] - [app.common.pages-migrations :as pmg] [app.common.exceptions :as ex] + [app.common.pages-migrations :as pmg] [app.common.spec :as us] [app.db :as db] - [app.media :as media] [app.services.queries :as sq] [app.services.queries.projects :as projects] - [app.util.blob :as blob])) + [app.util.blob :as blob] + [clojure.spec.alpha :as s])) (declare decode-row) (declare decode-row-xf) diff --git a/backend/src/app/services/queries/projects.clj b/backend/src/app/services/queries/projects.clj index 892a122b53..1b3b36997f 100644 --- a/backend/src/app/services/queries/projects.clj +++ b/backend/src/app/services/queries/projects.clj @@ -9,12 +9,12 @@ (ns app.services.queries.projects (:require - [clojure.spec.alpha :as s] - [app.common.spec :as us] [app.common.exceptions :as ex] + [app.common.spec :as us] [app.db :as db] [app.services.queries :as sq] - [app.services.queries.teams :as teams])) + [app.services.queries.teams :as teams] + [clojure.spec.alpha :as s])) ;; --- Check Project Permissions diff --git a/backend/src/app/services/queries/recent_files.clj b/backend/src/app/services/queries/recent_files.clj index 159bd3025c..e52fd9ee9c 100644 --- a/backend/src/app/services/queries/recent_files.clj +++ b/backend/src/app/services/queries/recent_files.clj @@ -5,18 +5,16 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2019-2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.services.queries.recent-files (:require - [clojure.spec.alpha :as s] - [promesa.core :as p] - [app.db :as db] [app.common.spec :as us] + [app.db :as db] [app.services.queries :as sq] + [app.services.queries.files :refer [decode-row-xf]] [app.services.queries.teams :as teams] - [app.services.queries.projects :as projects :refer [retrieve-projects]] - [app.services.queries.files :refer [decode-row-xf]])) + [clojure.spec.alpha :as s])) (def sql:recent-files "with recent_files as ( diff --git a/backend/src/app/services/queries/teams.clj b/backend/src/app/services/queries/teams.clj index e5191bca3f..e3fc6b85bf 100644 --- a/backend/src/app/services/queries/teams.clj +++ b/backend/src/app/services/queries/teams.clj @@ -5,18 +5,16 @@ ;; This Source Code Form is "Incompatible With Secondary Licenses", as ;; defined by the Mozilla Public License, v. 2.0. ;; -;; Copyright (c) 2020 Andrey Antukh +;; Copyright (c) 2020 UXBOX Labs SL (ns app.services.queries.teams (:require - [clojure.spec.alpha :as s] [app.common.exceptions :as ex] [app.common.spec :as us] - [app.common.uuid :as uuid] [app.db :as db] [app.services.queries :as sq] [app.services.queries.profile :as profile] - [app.util.blob :as blob])) + [clojure.spec.alpha :as s])) ;; --- Team Edition Permissions diff --git a/backend/src/app/services/tokens.clj b/backend/src/app/services/tokens.clj index 4c57a3da02..fe0967156f 100644 --- a/backend/src/app/services/tokens.clj +++ b/backend/src/app/services/tokens.clj @@ -10,16 +10,11 @@ (ns app.services.tokens (:require [app.common.exceptions :as ex] - [app.common.spec :as us] [app.config :as cfg] - [app.db :as db] [app.util.time :as dt] [app.util.transit :as t] - [buddy.core.codecs :as bc] [buddy.core.kdf :as bk] - [buddy.core.nonce :as bn] [buddy.sign.jwe :as jwe] - [clojure.spec.alpha :as s] [clojure.tools.logging :as log])) (defn- derive-tokens-secret diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj index 5227aba171..94f10626c4 100644 --- a/backend/src/app/srepl/main.clj +++ b/backend/src/app/srepl/main.clj @@ -1,5 +1,6 @@ (ns app.srepl.main "A main namespace for server repl." + #_:clj-kondo/ignore (:require [clojure.pprint :refer [pprint]] [app.db :as db])) diff --git a/backend/src/app/srepl/server.clj b/backend/src/app/srepl/server.clj index 52a69538f4..51d23050f1 100644 --- a/backend/src/app/srepl/server.clj +++ b/backend/src/app/srepl/server.clj @@ -1,10 +1,18 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + (ns app.srepl.server "Server Repl." (:require - [clojure.pprint :refer [pprint]] - [clojure.main :as cm] - [clojure.core.server :as ccs] [app.srepl.main] + [clojure.core.server :as ccs] + [clojure.main :as cm] [mount.core :as mount :refer [defstate]])) (defn- repl-init diff --git a/backend/src/app/tasks.clj b/backend/src/app/tasks.clj index 02b0164d4e..c074358e27 100644 --- a/backend/src/app/tasks.clj +++ b/backend/src/app/tasks.clj @@ -11,7 +11,6 @@ (:require [app.common.spec :as us] [app.common.uuid :as uuid] - [app.config :as cfg] [app.db :as db] [app.metrics :as mtx] [app.util.time :as dt] diff --git a/backend/src/app/worker.clj b/backend/src/app/worker.clj index b3bd38016a..5ee7d9d187 100644 --- a/backend/src/app/worker.clj +++ b/backend/src/app/worker.clj @@ -68,8 +68,7 @@ ]) (defstate executor - :start (thread-pool {:idle-timeout 10000 - :min-threads 0 + :start (thread-pool {:min-threads 0 :max-threads 256}) :stop (stop! executor)) @@ -381,7 +380,7 @@ (defn thread-pool ([] (thread-pool {})) ([{:keys [min-threads max-threads name] - :or {min-threads 0 max-threads 128 idle-timeout 60000}}] + :or {min-threads 0 max-threads 128}}] (let [executor (QueuedThreadPool. max-threads min-threads)] (.setName executor (or name "default-tp")) (.start executor) From e0cc0a7f3a1cf9bd8bf96a41d9fe2cc857fa7342 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 14:34:47 +0100 Subject: [PATCH 131/195] :bug: Don't allow create frames inside frames. --- frontend/src/app/main/data/workspace/common.cljs | 8 ++++++-- frontend/src/app/main/ui/viewer/shapes.cljs | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 7b42338ff5..0cdd800186 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -532,8 +532,12 @@ unames (retrieve-used-names objects) name (generate-unique-name unames (:name shape)) - frame-id (or (:frame-id attrs) - (cph/frame-id-by-position objects attrs)) + + + frame-id (if (= :frame (:type attrs)) + uuid/zero + (or (:frame-id attrs) + (cph/frame-id-by-position objects attrs))) shape (merge (if (= :frame (:type shape)) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 9ec1931e2d..84a45ba976 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -154,6 +154,7 @@ (geom/translate-to-frame frame)) opts #js {:shape shape}] (case (:type shape) + :frame [:g.empty] :text [:> text-wrapper opts] :rect [:> rect-wrapper opts] :path [:> path-wrapper opts] From 247273631c29897c325be3ead2a910e8b490d799 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 14:36:00 +0100 Subject: [PATCH 132/195] :sparkles: Minor change on devenv nginx config. --- docker/devenv/files/nginx.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/devenv/files/nginx.conf b/docker/devenv/files/nginx.conf index 2ae400e691..cc33ec4760 100644 --- a/docker/devenv/files/nginx.conf +++ b/docker/devenv/files/nginx.conf @@ -61,7 +61,6 @@ http { location / { root /home/penpot/penpot/frontend/resources/public; - try_files $uri /index.html; add_header Cache-Control "no-cache, max-age=0"; } From 7b1f84f50943f651d54802cd69a9c8b6a74f44dd Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 14:36:50 +0100 Subject: [PATCH 133/195] :lipstick: Minor cosmetic changes on shapes related namespaces. --- frontend/src/app/main/ui/shapes/shape.cljs | 19 +++--- frontend/src/app/main/ui/viewer/shapes.cljs | 2 +- .../src/app/main/ui/workspace/shapes.cljs | 67 ++++++++++--------- 3 files changed, 43 insertions(+), 45 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 830a7057b2..56af59aad2 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -9,25 +9,23 @@ (ns app.main.ui.shapes.shape (:require - [rumext.alpha :as mf] - [cuerdas.core :as str] - [app.util.object :as obj] - [app.common.uuid :as uuid] [app.common.geom.shapes :as geom] + [app.common.uuid :as uuid] + [app.main.ui.context :as muc] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.gradients :as grad] - [app.main.ui.context :as muc])) + [app.util.object :as obj] + [cuerdas.core :as str] + [rumext.alpha :as mf])) (mf/defc shape-container {::mf/wrap-props false} [props] - - (let [shape (unchecked-get props "shape") - children (unchecked-get props "children") + (let [shape (obj/get props "shape") + children (obj/get props "children") render-id (mf/use-memo #(str (uuid/next))) filter-id (str "filter_" render-id) - group-props (-> props - (obj/clone) + group-props (-> (obj/clone props) (obj/without ["shape" "children"]) (obj/set! "id" (str "shape-" (:id shape))) (obj/set! "className" "shape") @@ -38,5 +36,4 @@ [:& filters/filters {:shape shape :filter-id filter-id}] [:& grad/gradient {:shape shape :attr :fill-color-gradient}] [:& grad/gradient {:shape shape :attr :stroke-color-gradient}]] - children]])) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 84a45ba976..6327a66d9a 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -111,7 +111,7 @@ (mf/fnc frame-container {::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") + (let [shape (obj/get props "shape") childs (mapv #(get objects %) (:shapes shape)) shape (geom/transform-shape shape) props (obj/merge! #js {} props diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index a8d65e2e97..0b561e58aa 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -8,31 +8,32 @@ ;; Copyright (c) 2020 UXBOX Labs SL (ns app.main.ui.workspace.shapes - "A workspace specific shapes wrappers." + "A workspace specific shapes wrappers. + + Shapes that has some peculiarities are defined in its own + namespace under app.ui.workspace.shapes.* prefix, all the + others are defined using a generic wrapper implemented in + common." (:require - [rumext.alpha :as mf] - [okulary.core :as l] - [beicon.core :as rx] + [app.common.geom.shapes :as geom] + [app.main.refs :as refs] + [app.main.store :as st] [app.main.streams :as ms] - [app.main.ui.hooks :as hooks] [app.main.ui.cursors :as cur] - [app.main.ui.shapes.rect :as rect] + [app.main.ui.hooks :as hooks] [app.main.ui.shapes.circle :as circle] [app.main.ui.shapes.image :as image] - [app.main.store :as st] - [app.main.refs :as refs] - - ;; Shapes that has some peculiarities are defined in its own - ;; namespace under app.ui.workspace.shapes.* prefix, all the - ;; others are defined using a generic wrapper implemented in - ;; common. + [app.main.ui.shapes.rect :as rect] [app.main.ui.workspace.shapes.bounding-box :refer [bounding-box]] [app.main.ui.workspace.shapes.common :as common] [app.main.ui.workspace.shapes.frame :as frame] [app.main.ui.workspace.shapes.group :as group] [app.main.ui.workspace.shapes.path :as path] [app.main.ui.workspace.shapes.text :as text] - [app.common.geom.shapes :as geom])) + [app.util.object :as obj] + [beicon.core :as rx] + [okulary.core :as l] + [rumext.alpha :as mf])) (declare group-wrapper) (declare frame-wrapper) @@ -43,10 +44,10 @@ (defn- shape-wrapper-memo-equals? [np op] - (let [n-shape (unchecked-get np "shape") - o-shape (unchecked-get op "shape") - n-frame (unchecked-get np "frame") - o-frame (unchecked-get op "frame")] + (let [n-shape (obj/get np "shape") + o-shape (obj/get op "shape") + n-frame (obj/get np "frame") + o-frame (obj/get op "frame")] ;; (prn "shape-wrapper-memo-equals?" (identical? n-frame o-frame)) (if (= (:type n-shape) :group) false @@ -55,28 +56,28 @@ (defn make-is-moving-ref [id] - (let [check-moving (fn [local] - (and (= :move (:transform local)) - (contains? (:selected local) id)))] - (l/derived check-moving refs/workspace-local))) + (fn [] + (let [check-moving (fn [local] + (and (= :move (:transform local)) + (contains? (:selected local) id)))] + (l/derived check-moving refs/workspace-local)))) (mf/defc shape-wrapper {::mf/wrap [#(mf/memo' % shape-wrapper-memo-equals?)] ::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") - frame (unchecked-get props "frame") - ghost? (unchecked-get props "ghost?") - shape (-> (geom/transform-shape shape) - (geom/translate-to-frame frame)) - opts #js {:shape shape - :frame frame} + (let [shape (obj/get props "shape") + frame (obj/get props "frame") + ghost? (obj/get props "ghost?") + shape (-> (geom/transform-shape shape) + (geom/translate-to-frame frame)) + opts #js {:shape shape + :frame frame} - alt? (hooks/use-rxsub ms/keyboard-alt) + alt? (hooks/use-rxsub ms/keyboard-alt) - moving-iref (mf/use-memo (mf/deps (:id shape)) - #(make-is-moving-ref (:id shape))) - moving? (mf/deref moving-iref)] + moving-iref (mf/use-memo (mf/deps (:id shape)) (make-is-moving-ref (:id shape))) + moving? (mf/deref moving-iref)] (when (and shape (or ghost? (not moving?)) From 590c57c18db9a4b1c1efaa75cd43b86ff803f4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 2 Dec 2020 15:32:58 +0100 Subject: [PATCH 134/195] :bugfix: Add require macros --- common/app/common/exceptions.cljc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/app/common/exceptions.cljc b/common/app/common/exceptions.cljc index 8f74d09225..69885361bb 100644 --- a/common/app/common/exceptions.cljc +++ b/common/app/common/exceptions.cljc @@ -6,6 +6,8 @@ (ns app.common.exceptions "A helpers for work with exceptions." + #?(:cljs + (:require-macros [app.common.exceptions])) (:require [clojure.spec.alpha :as s])) (s/def ::type keyword?) From e165ca7c3b30ceb20e93196f8d8f365ef1a65c40 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 16:44:21 +0100 Subject: [PATCH 135/195] :sparkles: Add improvements to manage.sh and devenv related to deployment. --- docker/devenv/Dockerfile | 1 + docker/devenv/files/bashrc | 2 ++ frontend/scripts/build.sh | 3 ++- manage.sh | 22 ++++++++++++---------- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docker/devenv/Dockerfile b/docker/devenv/Dockerfile index 211f97f7f2..6d345686d8 100644 --- a/docker/devenv/Dockerfile +++ b/docker/devenv/Dockerfile @@ -150,6 +150,7 @@ EXPOSE 9090 COPY files/start-tmux.sh /home/start-tmux.sh COPY files/entrypoint.sh /home/entrypoint.sh COPY files/init.sh /home/init.sh +COPY files/bashrc /home/penpot/.bashrc ENTRYPOINT ["/home/entrypoint.sh"] CMD ["/home/init.sh"] diff --git a/docker/devenv/files/bashrc b/docker/devenv/files/bashrc index 526ef9db59..8b623d9029 100644 --- a/docker/devenv/files/bashrc +++ b/docker/devenv/files/bashrc @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + export PATH=$HOME/.local/bin:/usr/local/nodejs/bin:$PATH alias l='ls --color -GFlh' diff --git a/frontend/scripts/build.sh b/frontend/scripts/build.sh index bfbadbcf32..11fd4341ef 100755 --- a/frontend/scripts/build.sh +++ b/frontend/scripts/build.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash source ~/.bashrc + set -ex if [ -z "${TAG}" ]; then - export TAG=`git log -n 1 --pretty=format:%H -- ./` + export TAG=$(git log -n 1 --pretty=format:%H -- ./); fi yarn install diff --git a/manage.sh b/manage.sh index 870a1f39b3..c29dcb5f33 100755 --- a/manage.sh +++ b/manage.sh @@ -63,10 +63,8 @@ function run-devenv { function build { pull-devenv-if-not-exists; docker volume create $DEVENV_PNAME_user_data; - - echo "Running development image $IMAGE to build frontend." docker run -t --rm \ - --mount source=$DEVENV_PNAME_user_data,type=volume,target=/home/penpot/ \ + --mount source=${DEVENV_PNAME}_user_data,type=volume,target=/home/penpot/ \ --mount source=`pwd`,type=bind,target=/home/penpot/penpot \ -e EXTERNAL_UID=$CURRENT_USER_ID \ -w /home/penpot/penpot/$1 \ @@ -103,15 +101,19 @@ function build-bundle { echo $CURRENT_GIT_TAG > ./bundle/exporter/version.txt echo $CURRENT_GIT_TAG > ./bundle/version.txt - pushd bundle/ - tar -cvf ../$name.tar *; - popd + local generate_tar=${PENPOT_BUILD_GENERATE_TAR:-"true"}; - xz -vez1f -T4 $name.tar + if [ $generate_tar == "true" ]; then + pushd bundle/ + tar -cvf ../$name.tar *; + popd - echo "##############################################################"; - echo "# Generated $name.tar.xz"; - echo "##############################################################"; + xz -vez1f -T4 $name.tar + + echo "##############################################################"; + echo "# Generated $name.tar.xz"; + echo "##############################################################"; + fi } function build-image { From 1f5050eb012d0a5b373a60c7039f7f1492171006 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 17:06:07 +0100 Subject: [PATCH 136/195] :lipstick: Minor fixes on manage.sh --- manage.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/manage.sh b/manage.sh index c29dcb5f33..0bae480bc6 100755 --- a/manage.sh +++ b/manage.sh @@ -67,8 +67,9 @@ function build { --mount source=${DEVENV_PNAME}_user_data,type=volume,target=/home/penpot/ \ --mount source=`pwd`,type=bind,target=/home/penpot/penpot \ -e EXTERNAL_UID=$CURRENT_USER_ID \ + -e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \ -w /home/penpot/penpot/$1 \ - $DEVENV_IMGNAME:latest sudo -u penpot ./scripts/build.sh + $DEVENV_IMGNAME:latest sudo -EH -u penpot ./scripts/build.sh } function build-frontend { From 8caa5c6a65042d71c002f3cec4cecdec49b6ac4e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 17:48:47 +0100 Subject: [PATCH 137/195] :sparkles: Add missing environment var on frontend build. --- frontend/scripts/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/scripts/build.sh b/frontend/scripts/build.sh index 11fd4341ef..4587970b3d 100755 --- a/frontend/scripts/build.sh +++ b/frontend/scripts/build.sh @@ -15,7 +15,7 @@ export NODE_ENV=production; # Clean the output directory npx gulp clean || exit 1; -npx shadow-cljs release main --config-merge "{:release-version \"${TAG}\"}" +npx shadow-cljs release main --config-merge "{:release-version \"${TAG}\"}" $SHADOWCLJS_EXTRA_PARAMS npx gulp build || exit 1; npx gulp dist:clean || exit 1; npx gulp dist:copy || exit 1; From 34d15e4192349509b441aac601a35a44202511f4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 2 Dec 2020 23:31:25 +0100 Subject: [PATCH 138/195] :books: Update documentation. --- docs/00-Getting-Started.md | 56 ++++++++++++++++++++++++++++++ docs/01-Development-Environment.md | 49 ++------------------------ docs/05-Management-Guide.md | 52 ++++----------------------- docs/06-Testing-Guide.md | 14 +++++--- 4 files changed, 76 insertions(+), 95 deletions(-) create mode 100644 docs/00-Getting-Started.md diff --git a/docs/00-Getting-Started.md b/docs/00-Getting-Started.md new file mode 100644 index 0000000000..5573e4c003 --- /dev/null +++ b/docs/00-Getting-Started.md @@ -0,0 +1,56 @@ +# Getting Started ## + +This documentation intends to explain how to get penpot application and run it locally. + +The simplest approach is using docker and docker-compose. + +## Install Docker ## + +Skip this section if you alreasdy have docker installed, up and running. + +You can install docker and its dependencies from your distribution +repositores with: + +```bash +sudo apt-get install docker docker-compose +``` + +Or follow installation instructions from docker.com; (for debian +https://docs.docker.com/engine/install/debian/). + +Ensure that the docker is started and optionally enable it to start +with the system: + +```bash +sudo systemctl start docker +sudo systemctl enable docker +``` + +And finally, add your user to the docker group: + +```basb +sudo usermod -aG docker $USER +``` + +This will make use the docker without `sudo` command all the time. + +NOTE: probably you will need to relogin again to make this change +take effect. + + +## Start penpot application ## + +You can create it from scratch or take a base from the [penpot +repository][1] + +[1]: https://raw.githubusercontent.com/penpot/penpot/develop/docker/images/docker-compose.yaml + +```bash +wget https://raw.githubusercontent.com/penpot/penpot/develop/docker/images/docker-compose.yaml +``` + +And then: + +```bash +docker-compose -p penpotest -f docker-compose.yaml up +``` diff --git a/docs/01-Development-Environment.md b/docs/01-Development-Environment.md index bb5771ebf3..4115112f21 100644 --- a/docs/01-Development-Environment.md +++ b/docs/01-Development-Environment.md @@ -54,12 +54,13 @@ development environment.** For start it, staying in this repository, execute: ```bash +./manage.sh pull-devenv ./manage.sh run-devenv ``` This will do the following: -- Build the images if it is not done before. +- Pulls the latest devenv image. - Starts all the containers in the background. - Attaches to the **devenv** container and executes the tmux session. - The tmux session automatically starts all the necessary services. @@ -67,7 +68,7 @@ This will do the following: You can execute the individual steps manully if you want: ```bash -./manage.sh build-devenv # builds the devenv docker image +./manage.sh build-devenv # builds the devenv docker image (not necessary in normal sircumstances) ./manage.sh start-devenv # starts background running containers ./manage.sh run-devenv # enters to new tmux session inside of one of the running containers ./manage.sh stop-devenv # stops background running containers @@ -143,47 +144,3 @@ If some exception is raised when code is reloaded, just use later use `(restart)` again. For more information, please refer to: `03-Backend-Guide.md`. - - -## Start the testenv ## - -The purpose of the testenv (Test Environment) is provide an easy way -to get Penpot running in local pc without getting into the full -development environment. - -As first step we still need to build devenv image because that image -is used to produce the production-like bundle of the application: - -```bash -./manage.sh build-devenv -``` - -Once the image is build, you no longer need to rebuilt it until the -devenv image is changed and this happens we make some structural -changes or upgrading some dependencies. - -Them, let's proceed to build the bundle (a directory that contains all -the sources and dependencies of the platform ready to be deployed): - -```bash -./manage.sh build-bundle -``` - -This will generate on current directory one file and one -directory. The most important is the file like -`uxbox-2020.09.09-1343.tar.xz`. - -Then, let's proceed to build the docker images with the bundle -generated from the previous step. - -```bash -./manage.sh build-testenv ./uxbox-2020.09.09-1343.tar.xz -``` - -This will generate the necessary docker images ready to be executed. - -And finally, start the docker-compose: - -```bash -./manage.sh start-testenv -``` diff --git a/docs/05-Management-Guide.md b/docs/05-Management-Guide.md index 485f86cdee..f63800a97c 100644 --- a/docs/05-Management-Guide.md +++ b/docs/05-Management-Guide.md @@ -13,7 +13,6 @@ Backend accepts a bunch of configuration parameters (detailed above), that can be passed in different ways. The preferred one is using environment variables. - This is a probably incomplete list of available options (with respective defaults): @@ -21,20 +20,19 @@ respective defaults): - `APP_PUBLIC_URI=http://localhost:3449` - `APP_DATABASE_USERNAME=` (default undefined, used from uri) - `APP_DATABASE_PASSWORD=` (default undefined, used from uri) -- `APP_DATABASE_URI=postgresql://127.0.0.1/app` +- `APP_DATABASE_URI=postgresql://127.0.0.1/penpot` - `APP_MEDIA_DIRECTORY=resources/public/media` - `APP_MEDIA_URI=http://localhost:6060/media/` -- `APP_ASSETS_DIRECTORY=resources/public/static` -- `APP_ASSETS_URI=ehttp://localhost:6060/static/` -- `APP_SENDMAIL_BACKEND=console` -- `APP_SENDMAIL_REPLY_TO=no-reply@nodomain.com` -- `APP_SENDMAIL_FROM=no-reply@nodomain.com` +- `APP_SMTP_DEFAULT_REPLY_TO=no-reply@example.com` +- `APP_SMTP_DEFAULT_FROM=no-reply@example.com` +- `APP_SMTP_ENABLED=` (default false, prints to console) - `APP_SMTP_HOST=` (default undefined) - `APP_SMTP_PORT=` (default undefined) - `APP_SMTP_USER=` (default undefined) - `APP_SMTP_PASSWORD=` (default undefined) - `APP_SMTP_SSL=` (default to `false`) - `APP_SMTP_TLS=` (default to `false`) +- `APP_REDIS_URI=redis://localhost/0` - `APP_REGISTRATION_ENABLED=true` - `APP_REGISTRATION_DOMAIN_WHITELIST=""` (comma-separated domains, defaults to `""` which means that all domains are allowed) - `APP_DEBUG_HUMANIZE_TRANSIT=true` @@ -57,6 +55,7 @@ respective defaults): - `APP_GITLAB_CLIENT_SECRET=` (default undefined) - `APP_GITLAB_BASE_URI=` (default https://gitlab.com) + ## REPL ## The production environment by default starts a server REPL where you @@ -64,43 +63,6 @@ can connect and perform diagnosis operations. For this you will need `netcat` or `telnet` installed in the server. ```bash -$ rlwrap netcat localhost 5555 +$ rlwrap netcat localhost 6062 user=> ``` - - -## Import collections ## - -This is the way we can preload default collections of images and icons to the -running platform. - -First of that, you need to have a configuration file (edn format) like -this: - -```clojure -{:icons - [{:name "Generic Icons 1" - :path "./icons/my-icons-collection/" - :regex #"^.*_48px\.svg$"} - ] - :images - [{:name "Generic Images 1" - :path "./images/my-images-collection/" - :regex #"^.*\.(png|jpg|webp)$"}]} -``` - -You can found a real example in `sample_media/config.edn` (that also -has all the material design icon collections). - -Then, you need to execute: - -```bash -clojure -Adev -X:fn-media-loader :path ../path/to/config.edn -``` - -If you have a REPL access to the running process, you can execute it from there: - -```clojure -(require 'app.cli.media-loader) -(uxbox.media-loader/run* "/path/to/config.edn") -``` diff --git a/docs/06-Testing-Guide.md b/docs/06-Testing-Guide.md index 66390b4091..5dc10cf704 100644 --- a/docs/06-Testing-Guide.md +++ b/docs/06-Testing-Guide.md @@ -30,10 +30,16 @@ Frontend tests have to be compiled first, and then run with node. npx shadow-cljs compile tests && node target/tests.js ``` -## Linter - -We can execute the linter for the whole codebase with the following command +Or run the watch (that automatically runs the test): ```bash -npx clj-kondo --lint common:backend/src:frontend/src +npx shadow-cljs watch tests +``` + +## Linter + +We can execute the linter for the whole codebase with the following command: + +```bash +clj-kondo --lint common:backend/src:frontend/src ``` From ba529b9fd66a211015e1274e3bd4b5ffcfb1fe13 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 09:04:43 +0100 Subject: [PATCH 139/195] :paperclip: Temprary comment some assertions. --- common/app/common/geom/shapes/rect.cljc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/app/common/geom/shapes/rect.cljc b/common/app/common/geom/shapes/rect.cljc index c788bb3630..b7a56e6fa9 100644 --- a/common/app/common/geom/shapes/rect.cljc +++ b/common/app/common/geom/shapes/rect.cljc @@ -13,10 +13,10 @@ [app.common.geom.shapes.common :as gco])) (defn rect->points [{:keys [x y width height]}] - (assert (number? x)) - (assert (number? y)) - (assert (and (number? width) (> width 0))) - (assert (and (number? height) (> height 0))) + ;; (assert (number? x)) + ;; (assert (number? y)) + ;; (assert (and (number? width) (> width 0))) + ;; (assert (and (number? height) (> height 0))) [(gpt/point x y) (gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height)) From 264811c5ee29210231e3f900d86ba5a1b4af21fd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 2 Dec 2020 15:37:11 +0100 Subject: [PATCH 140/195] :bug: Fixes problems with the picker for Safari and Firefox --- .../resources/polyfills/createImageBitmap.js | 33 +++ frontend/src/app/main/data/workspace.cljs | 3 +- frontend/src/app/main/ui/confirm.cljs | 2 +- frontend/src/app/main/ui/modal.cljs | 2 +- .../workspace/colorpicker/pixel_overlay.cljs | 212 ++++++++++-------- .../workspace/colorpicker/pixel_picker.cljs | 29 --- .../src/app/main/ui/workspace/viewport.cljs | 4 +- 7 files changed, 158 insertions(+), 127 deletions(-) create mode 100644 frontend/resources/polyfills/createImageBitmap.js delete mode 100644 frontend/src/app/main/ui/workspace/colorpicker/pixel_picker.cljs diff --git a/frontend/resources/polyfills/createImageBitmap.js b/frontend/resources/polyfills/createImageBitmap.js new file mode 100644 index 0000000000..0ddf17c321 --- /dev/null +++ b/frontend/resources/polyfills/createImageBitmap.js @@ -0,0 +1,33 @@ +/* + * Safari and Edge polyfill for createImageBitmap + * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap + * + * Support source image types Blob and ImageData. + * + * From: https://dev.to/nektro/createimagebitmap-polyfill-for-safari-and-edge-228 + * Updated by Yoan Tournade + */ +if (!('createImageBitmap' in window)) { + window.createImageBitmap = async function (data) { + return new Promise((resolve,reject) => { + let dataURL; + if (data instanceof Blob) { + dataURL = URL.createObjectURL(data); + } else if (data instanceof ImageData) { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + canvas.width = data.width; + canvas.height = data.height; + ctx.putImageData(data,0,0); + dataURL = canvas.toDataURL(); + } else { + throw new Error('createImageBitmap does not handle the provided image source type'); + } + const img = document.createElement('img'); + img.addEventListener('load',function () { + resolve(this); + }); + img.src = dataURL; + }); + }; +} diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index bd4251ffe7..31ec93f3f7 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1621,8 +1621,7 @@ (let [edition-id (get-in state [:workspace-local :edition]) path-edit-mode (get-in state [:workspace-local :edit-path edition-id :edit-mode])] (if-not (= :draw path-edit-mode) - (rx/of :interrupt - (deselect-all true)) + (rx/of :interrupt (deselect-all true)) (rx/empty)))))) (defn c-mod diff --git a/frontend/src/app/main/ui/confirm.cljs b/frontend/src/app/main/ui/confirm.cljs index d791de0f4f..73bf41bcc0 100644 --- a/frontend/src/app/main/ui/confirm.cljs +++ b/frontend/src/app/main/ui/confirm.cljs @@ -64,7 +64,7 @@ (dom/stop-propagation event) (st/emit! (modal/hide)) (on-accept props)))) - key (events/listen (dom/get-root) EventType.KEYDOWN on-keydown)] + key (events/listen js/document EventType.KEYDOWN on-keydown)] #(events/unlistenByKey key)))) [:div.modal-overlay diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs index 908ebced87..07d3849a6f 100644 --- a/frontend/src/app/main/ui/modal.cljs +++ b/frontend/src/app/main/ui/modal.cljs @@ -76,7 +76,7 @@ (mf/deps allow-click-outside) (fn [] (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) - (events/listen (dom/get-root) EventType.KEYDOWN handle-keydown) + (events/listen js/document EventType.KEYDOWN handle-keydown) (events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] #(doseq [key keys] (events/unlistenByKey key))))) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/pixel_overlay.cljs b/frontend/src/app/main/ui/workspace/colorpicker/pixel_overlay.cljs index 3599660a05..84a9a5dbf4 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/pixel_overlay.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/pixel_overlay.cljs @@ -54,106 +54,124 @@ [:& shape-wrapper {:shape item :key (:id item)}]))]])) -(defn draw-picker-canvas [svg-node canvas-node] - (let [canvas-context (.getContext canvas-node "2d") - xml (.serializeToString (js/XMLSerializer.) svg-node) - img-src (str "data:image/svg+xml;base64," - (-> xml js/encodeURIComponent js/unescape js/btoa)) - img (js/Image.) - - on-error (fn [err] (.error js/console "ERROR" err)) - on-load (fn [] (.drawImage canvas-context img 0 0))] - (.addEventListener img "error" on-error) - (.addEventListener img "load" on-load) - (obj/set! img "src" img-src))) - (mf/defc pixel-overlay {::mf/wrap-props false} [props] - (let [vport (unchecked-get props "vport") - vbox (unchecked-get props "vbox") + (let [vport (unchecked-get props "vport") + vbox (unchecked-get props "vbox") viewport-ref (unchecked-get props "viewport-ref") - options (unchecked-get props "options") - svg-ref (mf/use-ref nil) - canvas-ref (mf/use-ref nil) - fetch-pending (mf/deref (mdf/pending-ref)) + options (unchecked-get props "options") + svg-ref (mf/use-ref nil) + canvas-ref (mf/use-ref nil) + img-ref (mf/use-ref nil) - update-canvas-stream (rx/subject) + update-str (rx/subject) handle-keydown - (fn [event] - (when (and (kbd/esc? event)) - (do (dom/stop-propagation event) - (dom/prevent-default event) - (st/emit! (dwc/stop-picker)) - (modal/disallow-click-outside!)))) + (mf/use-callback + (fn [event] + (when (and (kbd/esc? event)) + (do (dom/stop-propagation event) + (dom/prevent-default event) + (st/emit! (dwc/stop-picker)) + (modal/disallow-click-outside!))))) - on-mouse-move-picker - (fn [event] - (when-let [zoom-view-node (.getElementById js/document "picker-detail")] - (let [{brx :left bry :top} (dom/get-bounding-rect (mf/ref-val viewport-ref)) - x (- (.-clientX event) brx) - y (- (.-clientY event) bry) + handle-mouse-move-picker + (mf/use-callback + (mf/deps viewport-ref) + (fn [event] + (when-let [zoom-view-node (.getElementById js/document "picker-detail")] + (let [viewport-node (mf/ref-val viewport-ref) + canvas-node (mf/ref-val canvas-ref) - zoom-context (.getContext zoom-view-node "2d") - canvas-node (mf/ref-val canvas-ref) - canvas-context (.getContext canvas-node "2d") - pixel-data (.getImageData canvas-context x y 1 1) - rgba (.-data pixel-data) - r (obj/get rgba 0) - g (obj/get rgba 1) - b (obj/get rgba 2) - a (obj/get rgba 3) + {brx :left bry :top} (dom/get-bounding-rect viewport-node) + x (- (.-clientX event) brx) + y (- (.-clientY event) bry) - area-data (.getImageData canvas-context (- x 25) (- y 20) 50 40)] + zoom-context (.getContext zoom-view-node "2d") + canvas-context (.getContext canvas-node "2d") + pixel-data (.getImageData canvas-context x y 1 1) + rgba (.-data pixel-data) + r (obj/get rgba 0) + g (obj/get rgba 1) + b (obj/get rgba 2) + a (obj/get rgba 3) + area-data (.getImageData canvas-context (- x 25) (- y 20) 50 40)] + (-> (js/createImageBitmap area-data) + (p/then + (fn [image] + ;; Draw area + (obj/set! zoom-context "imageSmoothingEnabled" false) + (.drawImage zoom-context image 0 0 200 160)))) + (st/emit! (dwc/pick-color [r g b a])))))) - (-> (js/createImageBitmap area-data) - (p/then (fn [image] - ;; Draw area - (obj/set! zoom-context "imageSmoothingEnabled" false) - (.drawImage zoom-context image 0 0 200 160)))) - (st/emit! (dwc/pick-color [r g b a]))))) + handle-mouse-down-picker + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (st/emit! (dwc/pick-color-select true (kbd/shift? event))))) - on-mouse-down-picker - (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - (st/emit! (dwc/pick-color-select true (kbd/shift? event)))) + handle-mouse-up-picker + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (st/emit! (dwc/stop-picker)) + (modal/disallow-click-outside!))) - on-mouse-up-picker - (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - (st/emit! (dwc/stop-picker)) - (modal/disallow-click-outside!))] + handle-image-load + (mf/use-callback + (mf/deps img-ref) + (fn [] + (let [canvas-node (mf/ref-val canvas-ref) + img-node (mf/ref-val img-ref) + canvas-context (.getContext canvas-node "2d")] + (.drawImage canvas-context img-node 0 0)))) + + handle-draw-picker-canvas + (mf/use-callback + (mf/deps img-ref) + (fn [] + (let [img-node (mf/ref-val img-ref) + svg-node (mf/ref-val svg-ref) + xml (-> (js/XMLSerializer.) + (.serializeToString svg-node) + js/encodeURIComponent + js/unescape + js/btoa) + img-src (str "data:image/svg+xml;base64," xml)] + (obj/set! img-node "src" img-src)))) + + handle-svg-change + (mf/use-callback + (fn [] + (rx/push! update-str :update)))] (mf/use-effect (fn [] - (let [listener (events/listen (dom/get-root) EventType.KEYDOWN handle-keydown)] + (let [listener (events/listen js/document EventType.KEYDOWN handle-keydown)] #(events/unlistenByKey listener)))) (mf/use-effect (fn [] - (let [sub (->> update-canvas-stream + (let [sub (->> update-str (rx/debounce 10) - (rx/subs #(draw-picker-canvas (mf/ref-val svg-ref) - (mf/ref-val canvas-ref))))] - + (rx/subs handle-draw-picker-canvas))] #(rx/dispose! sub)))) (mf/use-effect - (mf/deps svg-ref canvas-ref) + (mf/deps svg-ref) (fn [] - (when (and svg-ref canvas-ref) - - (let [config (clj->js {:attributes true - :childList true - :subtree true - :characterData true}) - on-svg-change (fn [mutation-list] (rx/push! update-canvas-stream :update)) - observer (js/MutationObserver. on-svg-change)] - - (.observe observer (mf/ref-val svg-ref) config) + (when svg-ref + (let [config #js {:attributes true + :childList true + :subtree true + :characterData true} + svg-node (mf/ref-val svg-ref) + observer (js/MutationObserver. handle-svg-change)] + (.observe observer svg-node config) + (handle-svg-change) ;; Disconnect on unmount #(.disconnect observer))))) @@ -167,21 +185,31 @@ :width "100%" :height "100%" :cursor cur/picker} - :on-mouse-down on-mouse-down-picker - :on-mouse-up on-mouse-up-picker - :on-mouse-move on-mouse-move-picker}] - [:canvas {:ref canvas-ref - :width (:width vport 0) - :height (:height vport 0) - :style {:display "none"}}] + :on-mouse-down handle-mouse-down-picker + :on-mouse-up handle-mouse-up-picker + :on-mouse-move handle-mouse-move-picker} + [:div {:style {:display "none"}} + [:img {:ref img-ref + :on-load handle-image-load + :style {:position "absolute" + :width "100%" + :height "100%"}}] + [:canvas {:ref canvas-ref + :width (:width vport 0) + :height (:height vport 0) + :style {:position "absolute" + :width "100%" + :height "100%"}}] - [:& (mf/provider muc/embed-ctx) {:value true} - [:svg.viewport - {:ref svg-ref - :preserveAspectRatio "xMidYMid meet" - :width (:width vport 0) - :height (:height vport 0) - :view-box (format-viewbox vbox) - :style {:display "none" - :background-color (get options :background "#E8E9EA")}} - [:& overlay-frames]]]])) + [:& (mf/provider muc/embed-ctx) {:value true} + [:svg.viewport + {:ref svg-ref + :preserveAspectRatio "xMidYMid meet" + :width (:width vport 0) + :height (:height vport 0) + :view-box (format-viewbox vbox) + :style {:position "absolute" + :width "100%" + :height "100%" + :background-color (get options :background "#E8E9EA")}} + [:& overlay-frames]]]]]])) diff --git a/frontend/src/app/main/ui/workspace/colorpicker/pixel_picker.cljs b/frontend/src/app/main/ui/workspace/colorpicker/pixel_picker.cljs deleted file mode 100644 index 21a35a0fc5..0000000000 --- a/frontend/src/app/main/ui/workspace/colorpicker/pixel_picker.cljs +++ /dev/null @@ -1,29 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; This Source Code Form is "Incompatible With Secondary Licenses", as -;; defined by the Mozilla Public License, v. 2.0. -;; -;; Copyright (c) 2020 UXBOX Labs SL - -(ns app.main.ui.workspace.colorpicker.pixel-picker - (:require - [rumext.alpha :as mf] - [okulary.core :as l] - [cuerdas.core :as str] - [app.common.geom.point :as gpt] - [app.common.math :as math] - [app.common.uuid :refer [uuid]] - [app.util.dom :as dom] - [app.util.color :as uc] - [app.util.object :as obj] - [app.main.store :as st] - [app.main.refs :as refs] - [app.main.data.workspace.libraries :as dwl] - [app.main.data.colors :as dc] - [app.main.data.modal :as modal] - [app.main.ui.icons :as i] - [app.util.i18n :as i18n :refer [t]])) - - diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index a6886f9144..21173e1c94 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -490,8 +490,8 @@ (let [node (mf/ref-val viewport-ref) prnt (dom/get-parent node) - keys [(events/listen (dom/get-root) EventType.KEYDOWN on-key-down) - (events/listen (dom/get-root) EventType.KEYUP on-key-up) + keys [(events/listen js/document EventType.KEYDOWN on-key-down) + (events/listen js/document EventType.KEYUP on-key-up) (events/listen node EventType.MOUSEMOVE on-mouse-move) ;; bind with passive=false to allow the event to be cancelled ;; https://stackoverflow.com/a/57582286/3219895 From 6186d82151d560fbc17923ad8ac5007521e97ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 2 Dec 2020 08:44:39 +0100 Subject: [PATCH 141/195] :recycle: Change paste implementation to work with more browsers --- frontend/resources/locales.json | 8 + frontend/src/app/main/data/workspace.cljs | 186 ++++++++++-------- .../src/app/main/ui/workspace/viewport.cljs | 7 +- frontend/src/app/util/webapi.cljs | 31 ++- 4 files changed, 149 insertions(+), 83 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 0bf7355417..ceddb5b7b7 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -769,6 +769,14 @@ "es" : "Actualizado: %s" } }, + "errors.clipboard-not-implemented" : { + "translations" : { + "en" : "Your browser cannot do this operation, please use Ctrl-V", + "fr" : "", + "ru" : "", + "es" : "Tu navegador no puede realizar esta operación, por favor usa Ctrl-V." + } + }, "errors.auth.unauthorized" : { "used-in" : [ "src/app/main/ui/auth/login.cljs:82" ], "translations" : { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 31ec93f3f7..71fc3a70f1 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -24,6 +24,7 @@ [app.config :as cfg] [app.main.constants :as c] [app.main.data.colors :as mdc] + [app.main.data.messages :as dm] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.notifications :as dwn] @@ -42,6 +43,7 @@ [app.util.timers :as ts] [app.util.transit :as t] [app.util.webapi :as wapi] + [app.util.i18n :refer [tr] :as i18n] [beicon.core :as rx] [cljs.spec.alpha :as s] [clojure.set :as set] @@ -1016,7 +1018,6 @@ (watch [_ state stream] (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) - ;; --- Shape Proportions (defn set-shape-proportion-lock @@ -1029,6 +1030,7 @@ (assoc shape :proportion-lock false) (-> (assoc shape :proportion-lock true) (gpr/assign-proportions))))))))) + ;; --- Update Shape Position (s/def ::x number?) @@ -1053,6 +1055,21 @@ (rx/of (dwt/set-modifiers [id] {:displacement displ}) (dwt/apply-modifiers [id])))))) +;; --- Update Shape Flags + +(defn update-shape-flags + [id {:keys [blocked hidden] :as flags}] + (s/assert ::us/uuid id) + (s/assert ::shape-attrs flags) + (ptk/reify ::update-shape-flags + ptk/WatchEvent + (watch [_ state stream] + (letfn [(update-fn [obj] + (cond-> obj + (boolean? blocked) (assoc :blocked blocked) + (boolean? hidden) (assoc :hidden hidden)))] + (rx/of (dwc/update-shapes-recursive [id] update-fn)))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Navigation @@ -1195,6 +1212,68 @@ (rx/catch on-copy-error) (rx/ignore))))))) +(declare paste-shape) +(declare paste-text) +(declare paste-image) + +(def paste + (ptk/reify ::paste + ptk/WatchEvent + (watch [_ state stream] + (try + (let [clipboard-str (wapi/read-from-clipboard) + + paste-transit-str + (->> clipboard-str + (rx/filter t/transit?) + (rx/map t/decode) + (rx/filter #(= :copied-shapes (:type %))) + (rx/map #(select-keys % [:selected :objects])) + (rx/map paste-shape)) + + paste-plain-text-str + (->> clipboard-str + (rx/filter (comp not empty?)) + (rx/map paste-text)) + + paste-image-str + (->> (wapi/read-image-from-clipboard) + (rx/map paste-image))] + + (->> (rx/concat paste-transit-str + paste-plain-text-str + paste-image-str) + (rx/first) + (rx/catch + (fn [err] + (js/console.error "Clipboard error:" err) + (rx/empty))))) + (catch :default e + (let [data (ex-data e)] + (if (:not-implemented data) + (rx/of (dm/warn (tr "errors.clipboard-not-implemented"))) + (js/console.error "ERROR" e)))))))) + +(defn paste-from-event + [event] + (ptk/reify ::paste-from-event + ptk/WatchEvent + (watch [_ state stream] + (try + (let [paste-data (wapi/read-from-paste-event event)] + (when paste-data + (let [text-data (wapi/extract-text paste-data) + decoded-data (when (and paste-data (t/transit? text-data)) + (t/decode text-data))] + (if (and decoded-data (= (:type decoded-data) :copied-shapes)) + (rx/of (paste-shape decoded-data)) + (if-not (empty? text-data) + (rx/of (paste-text text-data)) + (let [images (wapi/extract-images paste-data)] + (rx/from (map paste-image images)))))))) + (catch :default err + (js/console.error "Clipboard error:" err)))))) + (defn selected-frame? [state] (let [selected (get-in state [:workspace-local :selected]) page-id (:current-page-id state) @@ -1202,9 +1281,9 @@ (and (and (= 1 (count selected)) (= :frame (get-in objects [(first selected) :type])))))) -(defn- paste-impl +(defn- paste-shape [{:keys [selected objects] :as data}] - (ptk/reify ::paste-impl + (ptk/reify ::paste-shape ptk/WatchEvent (watch [_ state stream] (let [selected-objs (map #(get objects %) selected) @@ -1240,71 +1319,6 @@ (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (dwc/select-shapes selected)))))) -(defn- image-uploaded - [image] - (let [{:keys [x y]} @ms/mouse-position - {:keys [width height]} image - shape {:name (:name image) - :width width - :height height - :x (- x (/ width 2)) - :y (- y (/ height 2)) - :metadata {:width width - :height height - :id (:id image) - :path (:path image)}}] - (st/emit! (create-and-add-shape :image x y shape)))) - -(defn- paste-image-impl - [image] - (ptk/reify ::paste-bin-impl - ptk/WatchEvent - (watch [_ state stream] - (let [file-id (get-in state [:workspace-file :id]) - params {:file-id file-id - :local? true - :js-files [image]}] - (rx/of (dwp/upload-media-objects - (with-meta params - {:on-success image-uploaded}))))))) - -(declare paste-text) - -(def paste - (ptk/reify ::paste - ptk/WatchEvent - (watch [_ state stream] - (try - (let [clipboard-str (wapi/read-from-clipboard) - - paste-transit-str - (->> clipboard-str - (rx/filter t/transit?) - (rx/map t/decode) - (rx/filter #(= :copied-shapes (:type %))) - (rx/map #(select-keys % [:selected :objects])) - (rx/map paste-impl)) - - paste-plain-text-str - (->> clipboard-str - (rx/filter (comp not empty?)) - (rx/map paste-text)) - - paste-image-str - (->> (wapi/read-image-from-clipboard) - (rx/map paste-image-impl))] - - (->> (rx/concat paste-transit-str - paste-plain-text-str - paste-image-str) - (rx/first) - (rx/catch - (fn [err] - (js/console.error "Clipboard error:" err) - (rx/empty))))) - (catch :default e - (.error js/console "ERROR" e)))))) - (defn as-content [text] (let [paragraphs (->> (str/lines text) (map str/trim) @@ -1341,18 +1355,33 @@ (dwc/add-shape shape) dwc/commit-undo-transaction))))) -(defn update-shape-flags - [id {:keys [blocked hidden] :as flags}] - (s/assert ::us/uuid id) - (s/assert ::shape-attrs flags) - (ptk/reify ::update-shape-flags +(defn- image-uploaded + [image] + (let [{:keys [x y]} @ms/mouse-position + {:keys [width height]} image + shape {:name (:name image) + :width width + :height height + :x (- x (/ width 2)) + :y (- y (/ height 2)) + :metadata {:width width + :height height + :id (:id image) + :path (:path image)}}] + (st/emit! (create-and-add-shape :image x y shape)))) + +(defn- paste-image + [image] + (ptk/reify ::paste-bin-impl ptk/WatchEvent (watch [_ state stream] - (letfn [(update-fn [obj] - (cond-> obj - (boolean? blocked) (assoc :blocked blocked) - (boolean? hidden) (assoc :hidden hidden)))] - (rx/of (dwc/update-shapes-recursive [id] update-fn)))))) + (let [file-id (get-in state [:workspace-file :id]) + params {:file-id file-id + :local? true + :js-files [image]}] + (rx/of (dwp/upload-media-objects + (with-meta params + {:on-success image-uploaded}))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GROUPS @@ -1662,7 +1691,6 @@ (dwd/select-for-drawing :text)) "p" #(st/emit! (dwd/select-for-drawing :path)) (c-mod "c") #(st/emit! copy-selected) - (c-mod "v") #(st/emit! paste) (c-mod "x") #(st/emit! copy-selected delete-selected) "escape" #(st/emit! (esc-pressed)) "del" #(st/emit! delete-selected) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 21173e1c94..0620f626f7 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -475,6 +475,10 @@ (with-meta params {:on-success #(on-uploaded % viewport-coord)}))))))) + on-paste + (fn [event] + (st/emit! (dw/paste-from-event event))) + on-resize (fn [event] (let [node (mf/ref-val viewport-ref) @@ -496,7 +500,8 @@ ;; bind with passive=false to allow the event to be cancelled ;; https://stackoverflow.com/a/57582286/3219895 (events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false}) - (events/listen js/window EventType.RESIZE on-resize)]] + (events/listen js/window EventType.RESIZE on-resize) + (events/listen js/window EventType.PASTE on-paste)]] (fn [] (doseq [key keys] diff --git a/frontend/src/app/util/webapi.cljs b/frontend/src/app/util/webapi.cljs index f18cc56082..a08e9889fd 100644 --- a/frontend/src/app/util/webapi.cljs +++ b/frontend/src/app/util/webapi.cljs @@ -79,12 +79,15 @@ (let [cboard (unchecked-get js/navigator "clipboard")] (.writeText ^js cboard data))) -(defn- read-from-clipboard +(defn read-from-clipboard [] (let [cboard (unchecked-get js/navigator "clipboard")] - (rx/from (.readText ^js cboard)))) + (if (.-readText ^js cboard) + (rx/from (.readText ^js cboard)) + (throw (ex-info "This browser does not implement read from clipboard protocol" + {:not-implemented true}))))) -(defn- read-image-from-clipboard +(defn read-image-from-clipboard [] (let [cboard (unchecked-get js/navigator "clipboard") read-item (fn [item] @@ -97,6 +100,28 @@ (rx/mapcat identity) ;; Convert each item into an emission (rx/switch-map read-item)))) +(defn read-from-paste-event + [event] + (let [target (.-target ^js event)] + (when (and (not (.-isContentEditable target)) ;; ignore when pasting into + (not= (.-tagName target) "INPUT")) ;; an editable control + (-> ^js event + (.getBrowserEvent) + (.-clipboardData))))) + +(defn extract-text + [clipboard-data] + (when clipboard-data + (.getData clipboard-data "text"))) + +(defn extract-images + [clipboard-data] + (when clipboard-data + (let [file-list (-> (.-files ^js clipboard-data))] + (->> (range (.-length file-list)) + (map #(.item file-list %)) + (filter #(str/starts-with? (.-type %) "image/")))))) + (defn request-fullscreen [el] (cond From e581cf8aebbca9df26c5392d9a2b8c296e771a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 3 Dec 2020 09:04:35 +0100 Subject: [PATCH 142/195] :recycle: Refactor paste function --- frontend/src/app/main/data/workspace.cljs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 71fc3a70f1..817afccaa5 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1260,17 +1260,15 @@ ptk/WatchEvent (watch [_ state stream] (try - (let [paste-data (wapi/read-from-paste-event event)] - (when paste-data - (let [text-data (wapi/extract-text paste-data) - decoded-data (when (and paste-data (t/transit? text-data)) - (t/decode text-data))] - (if (and decoded-data (= (:type decoded-data) :copied-shapes)) - (rx/of (paste-shape decoded-data)) - (if-not (empty? text-data) - (rx/of (paste-text text-data)) - (let [images (wapi/extract-images paste-data)] - (rx/from (map paste-image images)))))))) + (let [paste-data (wapi/read-from-paste-event event) + image-data (wapi/extract-images paste-data) + text-data (wapi/extract-text paste-data) + decoded-data (and (t/transit? text-data) (t/decode text-data))] + (cond + (seq image-data) (rx/from (map paste-image image-data)) + decoded-data (rx/of (paste-shape decoded-data)) + (string? text-data) (rx/of (paste-text text-data)) + :else (rx/empty))) (catch :default err (js/console.error "Clipboard error:" err)))))) From 0f62bcf25f5f6170fa86ca51a96de369cdfe921d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 3 Dec 2020 10:47:58 +0100 Subject: [PATCH 143/195] :bug: Fixed problem with mouse wheel button --- frontend/src/app/main/ui/workspace/viewport.cljs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 0620f626f7..d90da22a83 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -263,8 +263,10 @@ (st/emit! (ms/->MouseEvent :up ctrl? shift? alt?)) (when (= 2 (.-which event)) - (st/emit! dw/finish-pan - ::finish-positioning))))) + (do + (dom/prevent-default event) + (st/emit! dw/finish-pan + ::finish-positioning)))))) on-pointer-down (mf/use-callback From 718a187c1e146157adfcbc86559010f22afcb2b2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 3 Dec 2020 13:12:29 +0100 Subject: [PATCH 144/195] :sparkles: Reduces the snap-distances feedback --- common/app/common/geom/shapes.cljc | 20 +++++++--- .../app/main/ui/workspace/snap_distances.cljs | 37 +++++++++++-------- frontend/src/app/worker.cljs | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 4f633ed60f..5dbb6260e7 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -201,14 +201,22 @@ (defn selrect->areas [bounds selrect] (let [make-selrect (fn [x1 y1 x2 y2] - {:x1 x1 :y1 y1 :x2 x2 :y2 y2 :x x1 :y y1 - :width (- x2 x1) :height (- y2 y1) :type :rect}) + (let [x1 (min x1 x2) + x2 (max x1 x2) + y1 (min y1 y2) + y2 (max y1 y2)] + {:x1 x1 :y1 y1 + :x2 x2 :y2 y2 + :x x1 :y y1 + :width (- x2 x1) + :height (- y2 y1) + :type :rect})) {frame-x1 :x1 frame-x2 :x2 frame-y1 :y1 frame-y2 :y2} bounds {sr-x1 :x1 sr-x2 :x2 sr-y1 :y1 sr-y2 :y2} selrect] - {:left (make-selrect frame-x1 sr-y1 sr-x1 sr-y2) - :top (make-selrect sr-x1 frame-y1 sr-x2 sr-y1) - :right (make-selrect sr-x2 sr-y1 frame-x2 sr-y2) - :bottom (make-selrect sr-x1 sr-y2 sr-x2 frame-y2)})) + {:left (make-selrect frame-x1 sr-y1 (- sr-x1 2) sr-y2) + :top (make-selrect sr-x1 frame-y1 sr-x2 (- sr-y1 2)) + :right (make-selrect (+ sr-x2 2) sr-y1 frame-x2 sr-y2) + :bottom (make-selrect sr-x1 (+ sr-y2 2) sr-x2 frame-y2)})) (defn distance-selrect [selrect other] (let [{:keys [x1 y1]} other diff --git a/frontend/src/app/main/ui/workspace/snap_distances.cljs b/frontend/src/app/main/ui/workspace/snap_distances.cljs index 442131450e..139b9c289e 100644 --- a/frontend/src/app/main/ui/workspace/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/snap_distances.cljs @@ -145,12 +145,15 @@ (gsh/rect->selrect @refs/vbox)) areas (gsh/selrect->areas container-selrec selrect) query-side (fn [side] - (->> (uw/ask! {:cmd :selection/query - :page-id page-id - :frame-id (:id frame) - :rect (gsh/pad-selrec (areas side))}) - (rx/map #(set/difference % selected)) - (rx/map #(->> % (map (partial get @refs/workspace-page-objects))))))] + (let [rect (gsh/pad-selrec (areas side))] + (if (and (> (:width rect) 0) (> (:height rect) 0)) + (->> (uw/ask! {:cmd :selection/query + :page-id page-id + :frame-id (:id frame) + :rect rect}) + (rx/map #(set/difference % selected)) + (rx/map #(->> % (map (partial get @refs/workspace-page-objects))))) + (rx/of nil))))] (->> (query-side lt-side) (rx/combine-latest vector (query-side gt-side))))) @@ -193,25 +196,29 @@ distance-coincidences (concat (get-shapes-match show-candidate? lt-shapes) (get-shapes-match show-candidate? gt-shapes)) + ;; Stores the distance candidates to be shown + distance-candidates (d/concat + #{} + (map first distance-coincidences) + (filter #(check-in-set % lt-distances) gt-distances) + (filter #(check-in-set % gt-distances) lt-distances)) + + ;; Of these candidates we keep only the smaller to be displayed + min-distance (apply min distance-candidates) ;; Show the distances that either match one of the distances from the selrect ;; or are from the selrect and go to a shape on the left and to the right - show-distance? - (fn [dist] - (let [distances-to-show - (->> (d/concat #{} - (map first distance-coincidences) - (filter #(check-in-set % lt-distances) gt-distances) - (filter #(check-in-set % gt-distances) lt-distances)))] - (check-in-set dist distances-to-show))) + show-distance? #(check-in-set % #{min-distance}) ;; These are the segments whose distance will be displayed - ;; First segments from segments different that the selectio + ;; First segments from segments different that the selection other-shapes-segments (->> distance-coincidences + (filter #(show-distance? (first %))) (map second) ;; Retrieves list of [shape,shape] tuples (map #(mapv :selrect %))) ;; Changes [shape,shape] to [selrec,selrec] + ;; Segments from the selection to the other shapes selection-segments (->> (concat lt-shapes gt-shapes) (filter #(show-distance? (distance-to-selrect %))) diff --git a/frontend/src/app/worker.cljs b/frontend/src/app/worker.cljs index 952d5e184a..d26963dfd2 100644 --- a/frontend/src/app/worker.cljs +++ b/frontend/src/app/worker.cljs @@ -62,6 +62,7 @@ {:reply-to sender-id :payload result})))) (catch :default e + (.error js/console "error" e) (let [message {:reply-to sender-id :error {:data (ex-data e) :message (ex-message e)}}] From 6b9d91e2be79900680cce8d9f84ec38d48bfb0b4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 10:17:40 +0100 Subject: [PATCH 145/195] :lipstick: Update code style and add more coments to :mov-objects change impl. --- common/app/common/pages.cljc | 52 ++++++++++++++++--------- common/app/common/pages_migrations.cljc | 2 +- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 8d89806984..558470b541 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -945,36 +945,52 @@ (update objects id assoc :parent-id parent-id)) ;; Updates the frame-id references that might be outdated - (update-frame-ids [frame-id objects id] - (let [objects (assoc-in objects [id :frame-id] frame-id) + (assign-frame-id [frame-id objects id] + (let [objects (update objects id assoc :frame-id frame-id) obj (get objects id)] (cond-> objects + ;; If we moving frame, the parent frame is the root + ;; and we DO NOT NEED update children because the + ;; children will point correctly to the frame what we + ;; are currently moving (not= :frame (:type obj)) - (as-> $$ (reduce (partial update-frame-ids frame-id) $$ (:shapes obj)))))) + (as-> $$ (reduce (partial assign-frame-id frame-id) $$ (:shapes obj)))))) (move-objects [objects] - (let [valid? (every? (partial is-valid-move? objects) shapes) - cpindex (reduce (fn [index id] - (let [obj (get objects id)] - (assoc! index id (:parent-id obj)))) - (transient {}) - (keys objects)) - cpindex (persistent! cpindex) + (let [valid? (every? (partial is-valid-move? objects) shapes) - parent (get objects parent-id) - frame (if (= :frame (:type parent)) - parent - (get objects (:frame-id parent))) + ;; Create a index of shape ids pointing to the + ;; corresponding parents; used mainly for update old + ;; parents after move operation. + cpindex (reduce (fn [index id] + (let [obj (get objects id)] + (assoc! index id (:parent-id obj)))) + (transient {}) + (keys objects)) + cpindex (persistent! cpindex) - frm-id (:id frame)] + parent (get objects parent-id) + frame-id (if (= :frame (:type parent)) + (:id parent) + (:frame-id parent))] - (if valid? + (if (and valid? (seq shapes)) (as-> objects $ + ;; Add the new shapes to the parent object. (update $ parent-id #(add-to-parent % index shapes)) + + ;; Update each individual shapre link to the new parent (reduce update-parent-id $ shapes) + + ;; Analyze the old parents and clear the old links + ;; only if the new parrent is different form old + ;; parent. (reduce (partial remove-from-old-parent cpindex) $ shapes) - (reduce (partial update-frame-ids frm-id) $ (get-in $ [parent-id :shapes]))) - objects)))] + + ;; Ensure that all shapes of the new parent has a + ;; correct link to the topside frame. + (reduce (partial assign-frame-id frame-id) $ shapes)) + objects)))] (if page-id (d/update-in-when data [:pages-index page-id :objects] move-objects) diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages_migrations.cljc index d9af48c7cd..ef16a5e549 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages_migrations.cljc @@ -55,7 +55,7 @@ (if-not (contains? shape :content) (let [content (gsp/segments->content (:segments shape) (:close? shape)) selrect (gsh/content->selrect content) - points (gsh/rect->points selrect)] + points (gsh/rect->points selrect)] (-> shape (dissoc :segments) (dissoc :close?) From b92045f905fffab6d8d37ca7bc7fb77e1d49857d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 10:31:07 +0100 Subject: [PATCH 146/195] :bug: Properly disable asserts on production code. --- backend/scripts/build.sh | 2 +- frontend/shadow-cljs.edn | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/scripts/build.sh b/backend/scripts/build.sh index 2be3d8d2f1..a25d5bb82e 100755 --- a/backend/scripts/build.sh +++ b/backend/scripts/build.sh @@ -47,7 +47,7 @@ if [ -f ./environ ]; then fi set -x -exec \$JAVA_CMD \$JVM_OPTS -classpath \$CP -Dlog4j.configurationFile=./log4j2.xml "\$@" clojure.main -m app.main +exec \$JAVA_CMD \$JVM_OPTS -Dapp.enable-asserts=false -classpath \$CP -Dlog4j.configurationFile=./log4j2.xml "\$@" clojure.main -m app.main EOF chmod +x ./target/dist/run.sh diff --git a/frontend/shadow-cljs.edn b/frontend/shadow-cljs.edn index 408003d67c..88068a45dc 100644 --- a/frontend/shadow-cljs.edn +++ b/frontend/shadow-cljs.edn @@ -28,8 +28,7 @@ {:compiler-options {:fn-invoke-direct true :source-map true - ;; :pseudo-names true - ;; :pretty-print true + :elide-asserts true :anon-fn-naming-policy :off :source-map-detail-level :all}}} From c21dc7ea7fa34f563c2f6bfaa73e26a89361a0b6 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 12:59:23 +0100 Subject: [PATCH 147/195] :sparkles: Update default hasher to argon2id. --- backend/deps.edn | 6 +++--- backend/src/app/services/mutations/profile.clj | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/deps.edn b/backend/deps.edn index 8afc04fcd2..095b0e4fb7 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -38,9 +38,9 @@ funcool/promesa {:mvn/version "5.1.0"} funcool/cuerdas {:mvn/version "2020.03.26-3"} - buddy/buddy-core {:mvn/version "1.8.0"} - buddy/buddy-hashers {:mvn/version "1.6.0"} - buddy/buddy-sign {:mvn/version "3.2.0"} + buddy/buddy-core {:mvn/version "1.9.0"} + buddy/buddy-hashers {:mvn/version "1.7.0"} + buddy/buddy-sign {:mvn/version "3.3.0"} lambdaisland/uri {:mvn/version "1.4.54" :exclusions [org.clojure/data.json]} diff --git a/backend/src/app/services/mutations/profile.clj b/backend/src/app/services/mutations/profile.clj index 2585ba8111..a45ddcbca9 100644 --- a/backend/src/app/services/mutations/profile.clj +++ b/backend/src/app/services/mutations/profile.clj @@ -27,6 +27,7 @@ [app.util.time :as dt] [buddy.hashers :as hashers] [clojure.spec.alpha :as s] + [clojure.tools.logging :as log] [cuerdas.core :as str])) ;; --- Helpers & Specs @@ -138,11 +139,20 @@ (defn- derive-password [password] - (hashers/derive password {:alg :bcrypt+sha512})) + (hashers/derive password + {:alg :argon2id + :memory 16384 + :iterations 20 + :parallelism 2})) (defn- verify-password [attempt password] - (hashers/verify attempt password)) + (try + (hashers/verify attempt password) + (catch Exception e + (log/warnf e "Error on verify password (only informative, nothing affected to user).") + {:update false + :valid false}))) (defn- create-profile "Create the profile entry on the database with limited input From 2bd89c94d917c5152cf8cc633fa1aef8b42fdaa1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 14:16:07 +0100 Subject: [PATCH 148/195] :bug: Adapt trim-file task to page/file data model changes. --- backend/src/app/config.clj | 7 +++-- backend/src/app/tasks/trim_file.clj | 49 ++++++++++++++++------------- backend/src/app/util/time.clj | 3 +- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index a590eb5516..78159a6d73 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -48,7 +48,7 @@ ;; modification in order to make the file ellegible for ;; trimming. The value only supports s(econds) m(inutes) and ;; h(ours) as time unit. - :file-trimming-max-age "72h" + :file-trimming-threshold "72h" ;; LDAP auth disabled by default. Set ldap-auth-host to enable ;:ldap-auth-host "ldap.mysupercompany.com" @@ -92,7 +92,9 @@ (s/def ::debug-humanize-transit ::us/boolean) (s/def ::public-uri ::us/string) (s/def ::backend-uri ::us/string) + (s/def ::image-process-max-threads ::us/integer) +(s/def ::file-trimming-threshold ::dt/duration) (s/def ::google-client-id ::us/string) (s/def ::google-client-secret ::us/string) @@ -113,7 +115,6 @@ (s/def ::ldap-auth-email-attribute ::us/string) (s/def ::ldap-auth-fullname-attribute ::us/string) (s/def ::ldap-auth-avatar-attribute ::us/string) -(s/def ::file-trimming-threshold ::dt/duration) (s/def ::config (s/keys :opt-un [::http-server-cors @@ -143,7 +144,7 @@ ::smtp-password ::smtp-tls ::smtp-ssl - ::file-trimming-max-age + ::file-trimming-threshold ::debug-humanize-transit ::allow-demo-users ::registration-enabled diff --git a/backend/src/app/tasks/trim_file.clj b/backend/src/app/tasks/trim_file.clj index e135953a49..dd16f2fd00 100644 --- a/backend/src/app/tasks/trim_file.clj +++ b/backend/src/app/tasks/trim_file.clj @@ -9,6 +9,7 @@ (ns app.tasks.trim-file (:require + [app.common.pages-migrations :as pmg] [app.config :as cfg] [app.db :as db] [app.tasks :as tasks] @@ -29,7 +30,8 @@ (bytes? data) (assoc :data (blob/decode data)))) (def sql:retrieve-files-to-trim - "select id from file as f + "select f.id, f.data + from file as f where f.has_media_trimmed is false and f.modified_at < now() - ?::interval order by f.modified_at asc @@ -40,39 +42,42 @@ file is considered candidate when some time passes whith no modification." [conn] - (let [interval (:file-trimming-max-age cfg/config)] - (->> (db/exec! conn [sql:retrieve-files-to-trim interval]) - (map :id)))) - + (let [threshold (:file-trimming-threshold cfg/config) + interval (db/interval threshold)] + (db/exec! conn [sql:retrieve-files-to-trim interval]))) (def collect-media-xf - (comp (map :data) - (map :objects) - (mapcat vals) - (filter #(= :image (:type %))) - (map :metadata) - (map :id))) - + (comp + (map :objects) + (mapcat vals) + (filter #(= :image (:type %))) + (map :metadata) + (map :id))) (defn collect-used-media - [pages] - (into #{} collect-media-xf pages)) + [data] + (-> #{} + (into collect-media-xf (vals (:pages-index data))) + (into collect-media-xf (vals (:components data))) + (into (keys (:media data))))) (defn process-file - [file-id] - (log/debugf "Processing file: '%s'." file-id) + [{:keys [id data] :as file}] + (log/debugf "Processing file: '%s'." id) (db/with-atomic [conn db/pool] - (let [mobjs (db/query conn :media-object {:file-id file-id}) - pages (->> (db/query conn :page {:file-id file-id}) - (map decode-row)) - used (into #{} collect-media-xf pages) - unused (into #{} (comp (map :id) (remove #(contains? used %))) mobjs)] + (let [mobjs (map :id (db/query conn :media-object {:file-id id})) + data (-> (blob/decode data) + (pmg/migrate-data)) + + used (collect-used-media data) + unused (into #{} (remove #(contains? used %)) mobjs)] (log/debugf "Collected media ids: '%s'." (pr-str used)) (log/debugf "Unused media ids: '%s'." (pr-str unused)) + (db/update! conn :file {:has-media-trimmed true} - {:id file-id}) + {:id id}) (doseq [id unused] ;; TODO: add task batching diff --git a/backend/src/app/util/time.clj b/backend/src/app/util/time.clj index e8d62d8778..628835c331 100644 --- a/backend/src/app/util/time.clj +++ b/backend/src/app/util/time.clj @@ -103,9 +103,10 @@ (letfn [(conformer [v] (cond (duration? v) v + (string? v) (try - (parse-duration v) + (duration v) (catch java.time.format.DateTimeParseException _e ::s/invalid)) From 03639cb9ac5e96c73f9f098c4f45998ce2e27b12 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 15:49:12 +0100 Subject: [PATCH 149/195] :bug: Don't count draft as a project. --- frontend/src/app/main/ui/dashboard/team.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index 407a3d239c..fc3039e5f9 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -302,7 +302,7 @@ [:div.label (tr "dashboard.team-projects")] [:div.projects [:span.icon i/folder] - [:span.text (tr "labels.num-of-projects" (i18n/c (:projects stats)))]] + [:span.text (tr "labels.num-of-projects" (i18n/c (dec (:projects stats))))]] [:div.files [:span.icon i/file-html] [:span.text (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]])) From 6d2e2489bb7ac2a8e79a86afa52fddbddb89aa26 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 19:14:34 +0100 Subject: [PATCH 150/195] :arrow_up: Update deps on exporter. --- exporter/package.json | 8 +-- exporter/yarn.lock | 117 +++++++++++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 39 deletions(-) diff --git a/exporter/package.json b/exporter/package.json index 7f67fc45fb..bb3640b55c 100644 --- a/exporter/package.json +++ b/exporter/package.json @@ -12,15 +12,15 @@ "inflation": "^2.0.0", "jszip": "^3.5.0", "koa": "^2.13.0", - "puppeteer": "^4.0.1", - "puppeteer-cluster": "^0.21.0", + "puppeteer": "^5.5.0", + "puppeteer-cluster": "^0.22.0", "raw-body": "^2.4.1", "svgo": "^1.3.2", "xml-js": "^1.6.11", - "xregexp": "^4.3.0" + "xregexp": "^4.4.0" }, "devDependencies": { - "shadow-cljs": "^2.10.19", + "shadow-cljs": "^2.11.8", "source-map-support": "^0.5.19" } } diff --git a/exporter/yarn.lock b/exporter/yarn.lock index f60524e9ad..7e9c4c2af9 100644 --- a/exporter/yarn.lock +++ b/exporter/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/runtime-corejs3@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d" - integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw== +"@babel/runtime-corejs3@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.5.tgz#ffee91da0eb4c6dae080774e94ba606368e414f4" + integrity sha512-roGr54CsTmNPPzZoCP1AmDXuBoNao7tnSA83TXTwt+UK5QVyh1DIJnrgYRPWKCF2flqZQXwa7Yr8v7VmLzF0YQ== dependencies: core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" @@ -478,6 +478,11 @@ destroy@^1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +devtools-protocol@0.0.818844: + version "0.0.818844" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.818844.tgz#d1947278ec85b53e4c8ca598f607a28fa785ba9e" + integrity sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -625,6 +630,14 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + fresh@~0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -915,6 +928,13 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -959,11 +979,6 @@ mime-types@^2.1.18, mime-types@~2.1.24: dependencies: mime-db "1.44.0" -mime@^2.0.3: - version "2.4.6" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" - integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -986,11 +1001,6 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -mitt@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.0.1.tgz#9e8a075b4daae82dd91aac155a0ece40ca7cb393" - integrity sha512-FhuJY+tYHLnPcBHQhbUFzscD5512HumCPE4URXZUgPi3IvOJi4Xva5IIgy3xX56GqCmw++MAm5UURG6kDBYTdg== - mkdirp-classic@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" @@ -1018,7 +1028,12 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -node-libs-browser@^2.0.0: +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== @@ -1121,6 +1136,25 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -1147,6 +1181,11 @@ path-browserify@0.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1168,6 +1207,13 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -1218,23 +1264,24 @@ punycode@^1.2.4: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -puppeteer-cluster@^0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/puppeteer-cluster/-/puppeteer-cluster-0.21.0.tgz#79071aa9830312446b18ec9d99fe41f6d80ee103" - integrity sha512-/x5mei0vXxFPpJ7iUS+xJ3rOcxxYUa2YeEyuWI9m0M5e8ammPiCXjvOsTcni+4ZAop3L2gpZFkxafPvXWOoRfg== +puppeteer-cluster@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/puppeteer-cluster/-/puppeteer-cluster-0.22.0.tgz#4ab214671f414f15ad6a94a4b61ed0b4172e86e6" + integrity sha512-hmydtMwfVM+idFIDzS8OXetnujHGre7RY3BGL+3njy9+r8Dcu3VALkZHfuBEPf6byKssTCgzxU1BvLczifXd5w== dependencies: debug "^4.1.1" -puppeteer@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-4.0.1.tgz#ebc2ee61157ed1aa25be3843fda97807df1d51f5" - integrity sha512-LIiSWTRqpTnnm3R2yAoMBx1inSeKwVZy66RFSkgSTDINzheJZPd5z5mMbPM0FkvwWAZ27a+69j5nZf+Fpyhn3Q== +puppeteer@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.5.0.tgz#331a7edd212ca06b4a556156435f58cbae08af00" + integrity sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg== dependencies: debug "^4.1.0" + devtools-protocol "0.0.818844" extract-zip "^2.0.0" https-proxy-agent "^4.0.0" - mime "^2.0.3" - mitt "^2.0.1" + node-fetch "^2.6.1" + pkg-dir "^4.2.0" progress "^2.0.1" proxy-from-env "^1.0.0" rimraf "^3.0.2" @@ -1382,12 +1429,12 @@ shadow-cljs-jar@1.3.2: resolved "https://registry.yarnpkg.com/shadow-cljs-jar/-/shadow-cljs-jar-1.3.2.tgz#97273afe1747b6a2311917c1c88d9e243c81957b" integrity sha512-XmeffAZHv8z7451kzeq9oKh8fh278Ak+UIOGGrapyqrFBB773xN8vMQ3O7J7TYLnb9BUwcqadKkmgaq7q6fhZg== -shadow-cljs@^2.10.19: - version "2.11.1" - resolved "https://registry.yarnpkg.com/shadow-cljs/-/shadow-cljs-2.11.1.tgz#1658278e2fdc7e0239f9573c505d3fbcfd741a31" - integrity sha512-3V+mtrGQwFJcb7DIreKwmCtwLKi/a7r8++mdmSTq2z1HRmcQV9DqIY4y+TLS6HkF/GNSIH7+hyHSH8uLdvsPlQ== +shadow-cljs@^2.11.8: + version "2.11.8" + resolved "https://registry.yarnpkg.com/shadow-cljs/-/shadow-cljs-2.11.8.tgz#34f579a96f90f79f6fac46ff901d81695c2ea0c0" + integrity sha512-8k2t6lLHDseWTcqizkIyJNVInYTYcd7v8uEE3CWYrlqlNZ+U3TQ4FsUS2pRXUfosNgvdkM7hw61pvwRk+KB5TA== dependencies: - node-libs-browser "^2.0.0" + node-libs-browser "^2.2.1" readline-sync "^1.4.7" shadow-cljs-jar "1.3.2" source-map-support "^0.4.15" @@ -1673,12 +1720,12 @@ xml-js@^1.6.11: dependencies: sax "^1.2.4" -xregexp@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== +xregexp@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.4.0.tgz#29660f5d6567cd2ef981dd4a50cb05d22c10719d" + integrity sha512-83y4aa8o8o4NZe+L+46wpa+F1cWR/wCGOWI3tzqUso0w3/KAvXy0+Di7Oe/cbNMixDR4Jmi7NEybWU6ps25Wkg== dependencies: - "@babel/runtime-corejs3" "^7.8.3" + "@babel/runtime-corejs3" "^7.12.1" xtend@^4.0.0: version "4.0.2" From 43bd98151ac14cf471fe255dd41894fe6bf270bc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 19:15:19 +0100 Subject: [PATCH 151/195] :bug: Fix text exportation on svg. --- frontend/src/app/main/ui.cljs | 6 +++--- frontend/src/app/main/ui/shapes/text.cljs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 8a8ea4b9e2..8d194113c0 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -171,9 +171,9 @@ :render-object (do - (let [file-id (uuid (get-in route [:params :path :file-id])) - page-id (uuid (get-in route [:params :path :page-id])) - object-id (uuid (get-in route [:params :path :object-id]))] + (let [file-id (uuid (get-in route [:path-params :file-id])) + page-id (uuid (get-in route [:path-params :page-id])) + object-id (uuid (get-in route [:path-params :object-id]))] [:& render/render-object {:file-id file-id :page-id page-id :object-id object-id}])) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 266dc66015..bfffea0130 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -94,6 +94,7 @@ {:keys [id x y width height content]} shape] [:foreignObject {:x x :y y + :id (:id shape) :data-colors (retrieve-colors shape) :transform (geom/transform-matrix shape) :width (if (#{:auto-width} grow-type) 10000 width) From 9b8ec1ac02cde2ab868056e1b65e97dddf6382ab Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 3 Dec 2020 19:22:07 +0100 Subject: [PATCH 152/195] :bug: Fix text exportation on svg with colors. --- frontend/src/app/main/ui/shapes/text.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index bfffea0130..4578692b2b 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -78,7 +78,7 @@ [shape] (let [colors (->> shape :content (tree-seq map? :children) - (into #{} (comp (map :fill) (filter string?))))] + (into #{} (comp (map :fill-color) (filter string?))))] (if (empty? colors) "#000000" (apply str (interpose "," colors))))) From b4246c2869aa1a990f73b69345bcde9adee61e17 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Dec 2020 09:29:26 +0100 Subject: [PATCH 153/195] :bug: Fix wrong spec reference on messages. --- frontend/src/app/main/data/messages.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index 25aeae409c..7eb90707c2 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -33,7 +33,7 @@ (s/def ::label ::us/string) (s/def ::callback fn?) (s/def ::action (s/keys :req-un [::label ::callback])) -(s/def ::actions (s/every ::message-action :kind vector?)) +(s/def ::actions (s/every ::action :kind vector?)) (s/def ::timeout (s/nilable ::us/integer)) (s/def ::content ::us/string) From e9714c4fd06234acef126acae2ed7b582c931919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 3 Dec 2020 14:18:03 +0100 Subject: [PATCH 154/195] :bug: Fix synchronization when adding a subcomponent to a instance --- common/app/common/pages.cljc | 4 ++-- common/app/common/pages_helpers.cljc | 8 +++++--- .../app/main/data/workspace/libraries_helpers.cljs | 11 ++++++++--- frontend/src/app/main/store.cljs | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 558470b541..a93604229e 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -764,8 +764,8 @@ :frame-id frame-id :parent-id parent-id :id id)] - (if (and (contains? objects parent-id) - (contains? objects frame-id)) + (if (and (or (nil? parent-id) (contains? objects parent-id)) + (or (nil? frame-id) (contains? objects frame-id))) (-> data (update :objects assoc id obj) (update-in [:objects parent-id :shapes] diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages_helpers.cljc index 2fb13a2e27..7c5aaa5b0a 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages_helpers.cljc @@ -10,8 +10,9 @@ (ns app.common.pages-helpers (:require [app.common.data :as d] - [app.common.uuid :as uuid] - [app.common.geom.shapes :as gsh])) + [app.common.geom.shapes :as gsh] + [app.common.spec :as us] + [app.common.uuid :as uuid])) (defn walk-pages "Go through all pages of a file and apply a function to each one" @@ -48,7 +49,7 @@ (defn page? [container] - (assert (some? (:type container))) + (us/assert some? (:type container)) (= (:type container) :page)) (defn component? @@ -246,6 +247,7 @@ (let [child-id (first child-ids) child (get objects child-id) + _ (us/assert some? child) [new-child new-child-objects updated-child-objects] (clone-object child new-id objects update-new-object update-original-object)] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 0d539806e9..cdf122c05f 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -664,8 +664,13 @@ root-instance)] (cond-> new-shape true - (assoc :shape-ref (:id original-shape) - :frame-id (:frame-id parent-shape)) + (assoc :frame-id (:frame-id parent-shape)) + + (nil? (:shape-ref original-shape)) + (assoc :shape-ref (:id original-shape)) + + (some? (:shape-ref original-shape)) + (assoc :shape-ref (:shape-ref original-shape)) (:component-id original-shape) (assoc :component-id (:component-id original-shape)) @@ -685,7 +690,7 @@ [new-shape new-shapes _] (cph/clone-object component-shape (:id parent-shape) - (get container :objects) + (get component :objects) update-new-shape update-original-shape) diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index 8860679b3b..e182969f3e 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -148,7 +148,7 @@ (when component-file (str/format "<%s> " (:name component-file))) (:name component))))))))] - (println "[Workspace]") + (println "[Page]") (show-shape (:id root) 0 objects) (dorun (for [component (vals components)] From 976dab90c8ec32325a219e49a7066b7a58759e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 4 Dec 2020 10:39:35 +0100 Subject: [PATCH 155/195] :bug: Synchronize well al color and special attributes --- common/app/common/pages.cljc | 12 +++++-- .../data/workspace/libraries_helpers.cljs | 36 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index a93604229e..4a7f79772e 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -217,7 +217,7 @@ (s/def :internal.shape/fill-color string?) (s/def :internal.shape/fill-opacity ::safe-number) -(s/def :internal.shape/fill-gradient (s/nilable ::gradient)) +(s/def :internal.shape/fill-color-gradient (s/nilable ::gradient)) (s/def :internal.shape/fill-color-ref-file (s/nilable uuid?)) (s/def :internal.shape/fill-color-ref-id (s/nilable uuid?)) @@ -235,6 +235,7 @@ (s/def :internal.shape/rx ::safe-number) (s/def :internal.shape/ry ::safe-number) (s/def :internal.shape/stroke-color string?) +(s/def :internal.shape/stroke-color-gradient (s/nilable ::gradient)) (s/def :internal.shape/stroke-color-ref-file (s/nilable uuid?)) (s/def :internal.shape/stroke-color-ref-id (s/nilable uuid?)) (s/def :internal.shape/stroke-opacity ::safe-number) @@ -293,9 +294,10 @@ :internal.shape/collapsed :internal.shape/content :internal.shape/fill-color + :internal.shape/fill-opacity + :internal.shape/fill-color-gradient :internal.shape/fill-color-ref-file :internal.shape/fill-color-ref-id - :internal.shape/fill-opacity :internal.shape/font-family :internal.shape/font-size :internal.shape/font-style @@ -330,9 +332,10 @@ :internal.shape/blur])) (def component-sync-attrs {:fill-color :fill-group + :fill-opacity :fill-group + :fill-color-gradient :fill-group :fill-color-ref-file :fill-group :fill-color-ref-id :fill-group - :fill-opacity :fill-group :content :content-group :font-family :text-font-group :font-size :text-font-group @@ -342,6 +345,7 @@ :line-height :text-display-group :text-align :text-display-group :stroke-color :stroke-group + :stroke-color-gradient :stroke-group :stroke-color-ref-file :stroke-group :stroke-color-ref-id :stroke-group :stroke-opacity :stroke-group @@ -361,6 +365,8 @@ :height :geometry-group :transform :geometry-group :transform-inverse :geometry-group + :shadow :shadow-group + :blur :blur-group :masked-group? :mask-group}) ;; shapes-group is handled differently diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index cdf122c05f..8347e9bc17 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -1013,27 +1013,23 @@ (assoc $ :component-id (:id container))))]] [rchanges uchanges]) - (if-not (contains? dest-shape attr) - (recur (next attrs) - roperations - uoperations) - (let [roperation {:type :set - :attr attr - :val (get origin-shape attr) - :ignore-touched (not set-touched?)} - uoperation {:type :set - :attr attr - :val (get dest-shape attr) - :ignore-touched (not set-touched?)} + (let [roperation {:type :set + :attr attr + :val (get origin-shape attr) + :ignore-touched (not set-touched?)} + uoperation {:type :set + :attr attr + :val (get dest-shape attr) + :ignore-touched (not set-touched?)} - attr-group (get cp/component-sync-attrs attr)] - (if (and (touched attr-group) omit-touched?) - (recur (next attrs) - roperations - uoperations) - (recur (next attrs) - (conj roperations roperation) - (conj uoperations uoperation)))))))))) + attr-group (get cp/component-sync-attrs attr)] + (if (and (touched attr-group) omit-touched?) + (recur (next attrs) + roperations + uoperations) + (recur (next attrs) + (conj roperations roperation) + (conj uoperations uoperation))))))))) (defn- reposition-shape [shape origin-root dest-root] From 3ddf04fa31df3c131717caa876c2d3053d83d24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 4 Dec 2020 10:54:32 +0100 Subject: [PATCH 156/195] :bug: Disallow creating a component for an artboard --- frontend/src/app/main/ui/workspace/context_menu.cljs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 4e98368eeb..7f1a4bbf6b 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -140,8 +140,9 @@ [:& menu-entry {:title (t locale "workspace.shape.menu.lock") :on-click do-lock-shape}]) - (when (or (nil? (:shape-ref shape)) - (> (count selected) 1)) + (when (and (or (nil? (:shape-ref shape)) + (> (count selected) 1)) + (not= (:type shape) :frame)) [:* [:& menu-separator] [:& menu-entry {:title (t locale "workspace.shape.menu.create-component") From e375c1e7d83e3232b0a49a880b94fc2d953a477c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 4 Dec 2020 11:47:11 +0100 Subject: [PATCH 157/195] :sparkles: Synchronize border radius independently of other geometry --- common/app/common/pages.cljc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 4a7f79772e..a73d8d7f2b 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -352,13 +352,13 @@ :stroke-style :stroke-group :stroke-width :stroke-group :stroke-alignment :stroke-group + :rx :radius-group + :ry :radius-group :selrect :geometry-group :points :geometry-group :locked :geometry-group :proportion :geometry-group :proportion-lock :geometry-group - :rx :geometry-group - :ry :geometry-group :x :geometry-group :y :geometry-group :width :geometry-group From 4a5a5b10813884c4ef35c9dda95d8ad7aba76f3a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 3 Dec 2020 15:10:17 +0100 Subject: [PATCH 158/195] :bug: Fixes problem with layer visibility --- frontend/src/app/main/refs.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 124235bbbd..ec587dbdd1 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -152,8 +152,8 @@ [ids] (l/derived (fn [objects] (into [] (comp (map #(get objects %)) - (filter identity)) - (set ids))) + (remove nil?)) + ids)) workspace-page-objects =)) (defn is-child-selected? From a71a7d6951222c3251fa50d599013fd45edd1973 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 3 Dec 2020 22:29:47 +0100 Subject: [PATCH 159/195] :bug: Fixed problems with resize texts --- frontend/src/app/main/data/workspace.cljs | 20 +---- .../src/app/main/data/workspace/common.cljs | 6 +- .../main/data/workspace/drawing/common.cljs | 2 +- .../src/app/main/data/workspace/texts.cljs | 42 +++++++++ .../app/main/data/workspace/transforms.cljs | 23 ++++- frontend/src/app/main/ui/shapes/group.cljs | 11 +-- frontend/src/app/main/ui/shapes/shape.cljs | 2 +- frontend/src/app/main/ui/shapes/text.cljs | 3 +- .../app/main/ui/workspace/context_menu.cljs | 4 +- .../app/main/ui/workspace/shapes/group.cljs | 41 ++++++--- .../app/main/ui/workspace/shapes/text.cljs | 87 ++++++++----------- .../main/ui/workspace/shapes/text/editor.cljs | 4 +- .../workspace/sidebar/options/component.cljs | 4 +- .../ui/workspace/sidebar/options/fill.cljs | 4 +- .../ui/workspace/sidebar/options/page.cljs | 4 +- .../ui/workspace/sidebar/options/shadow.cljs | 4 +- .../ui/workspace/sidebar/options/stroke.cljs | 4 +- 17 files changed, 149 insertions(+), 116 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 817afccaa5..99fbecd7d9 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1003,21 +1003,6 @@ :operations ops2 :id (:id curr)}))))))))) -;; --- Update Dimensions - -;; Event mainly used for handling user modification of the size of the -;; object from workspace sidebar options inputs. - -(defn update-dimensions - [ids attr value] - (us/verify (s/coll-of ::us/uuid) ids) - (us/verify #{:width :height} attr) - (us/verify ::us/number value) - (ptk/reify ::update-dimensions - ptk/WatchEvent - (watch [_ state stream] - (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) - ;; --- Shape Proportions (defn set-shape-proportion-lock @@ -1348,10 +1333,10 @@ :height height :grow-type (if (> (count text) 100) :auto-height :auto-width) :content (as-content text)})] - (rx/of dwc/start-undo-transaction + (rx/of (dwc/start-undo-transaction) (dws/deselect-all) (dwc/add-shape shape) - dwc/commit-undo-transaction))))) + (dwc/commit-undo-transaction)))))) (defn- image-uploaded [image] @@ -1610,6 +1595,7 @@ (d/export dwt/set-rotation) (d/export dwt/set-modifiers) (d/export dwt/apply-modifiers) +(d/export dwt/update-dimensions) ;; Persistence diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 0cdd800186..663e037c79 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -288,7 +288,7 @@ (defonce empty-tx {:undo-changes [] :redo-changes []}) -(def start-undo-transaction +(defn start-undo-transaction [] (ptk/reify ::start-undo-transaction ptk/UpdateEvent (update [_ state] @@ -297,13 +297,13 @@ (cond-> state (nil? current-tx) (assoc-in [:workspace-undo :transaction] empty-tx)))))) -(def discard-undo-transaction +(defn discard-undo-transaction [] (ptk/reify ::discard-undo-transaction ptk/UpdateEvent (update [_ state] (update state :workspace-undo dissoc :transaction)))) -(def commit-undo-transaction +(defn commit-undo-transaction [] (ptk/reify ::commit-undo-transaction ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 424287b3f9..c5a19c32c3 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -55,7 +55,7 @@ ;; Add & select the created shape to the workspace (rx/concat (if (= :text (:type shape)) - (rx/of dwc/start-undo-transaction) + (rx/of (dwc/start-undo-transaction)) (rx/empty)) (rx/of (dws/deselect-all) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c13a6dda23..ed9b2dc821 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -19,6 +19,7 @@ [app.common.geom.shapes :as geom] [app.common.attrs :as attrs] [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.transforms :as dwt] [app.main.fonts :as fonts] [app.util.object :as obj] [app.util.text :as ut])) @@ -210,3 +211,44 @@ (and (= 1 (count selected)) (= (-> selected first :type) :text)) (assoc-in [:workspace-local :edition] (-> selected first :id))))))) + +(defn resize-text [id new-width new-height] + (ptk/reify ::resize-text + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + shape (get-in state [:workspace-data :pages-index page-id :objects id]) + {:keys [selrect grow-type overflow-text]} shape + {shape-width :width shape-height :height} selrect + undo-transaction (get-in state [:workspace-undo :transaction]) + + events (when (and (> new-width 0) (> new-height 0)) + (cond + (and overflow-text (not= :fixed grow-type)) + [(update-overflow-text id false)] + + (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) + [(update-overflow-text id true)] + + (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) + [(update-overflow-text id false)] + + (and (or (not= shape-width new-width) + (not= shape-height new-height)) + (= grow-type :auto-width)) + (when (and (pos? shape-width) + (pos? shape-height)) + [(dwt/update-dimensions [id] :width new-width) + (dwt/update-dimensions [id] :height new-height)]) + + (and (not= shape-height new-height) (= grow-type :auto-height)) + (when (pos? shape-height) + [(dwt/update-dimensions [id] :height new-height)])))] + + (if (not (empty? events)) + (rx/concat + (when (not undo-transaction) + (rx/of (dwc/start-undo-transaction))) + (rx/from events) + (when (not undo-transaction) + (rx/of (dwc/discard-undo-transaction))))))))) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index c74221e316..44d7658a04 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -18,7 +18,6 @@ [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.common :as dwc] - [app.main.data.workspace.texts :as dwt] [app.main.data.workspace.selection :as dws] [app.main.refs :as refs] [app.main.snap :as snap] @@ -266,7 +265,7 @@ (when-not (empty? rch) (rx/of dwc/pop-undo-into-transaction (dwc/commit-changes rch uch {:commit-local? true}) - dwc/commit-undo-transaction + (dwc/commit-undo-transaction) (dwc/expand-collapse frame-id))))))) (defn start-move @@ -472,6 +471,22 @@ rchanges (conj (dwc/generate-changes page-id objects1 objects2) regchg) uchanges (conj (dwc/generate-changes page-id objects2 objects0) regchg)] - (rx/of dwc/start-undo-transaction + (rx/of (dwc/start-undo-transaction) (dwc/commit-changes rchanges uchanges {:commit-local? true}) - dwc/commit-undo-transaction))))) + (dwc/commit-undo-transaction)))))) + +;; --- Update Dimensions + +;; Event mainly used for handling user modification of the size of the +;; object from workspace sidebar options inputs. + +(defn update-dimensions + [ids attr value] + (us/verify (s/coll-of ::us/uuid) ids) + (us/verify #{:width :height} attr) + (us/verify ::us/number value) + (ptk/reify ::update-dimensions + ptk/WatchEvent + (watch [_ state stream] + #_(prn "??? update-dimensions" ids attr value) + (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) diff --git a/frontend/src/app/main/ui/shapes/group.cljs b/frontend/src/app/main/ui/shapes/group.cljs index 03bea3db6d..98c36bd0a3 100644 --- a/frontend/src/app/main/ui/shapes/group.cljs +++ b/frontend/src/app/main/ui/shapes/group.cljs @@ -12,7 +12,6 @@ [rumext.alpha :as mf] [cuerdas.core :as str] [app.main.ui.shapes.attrs :as attrs] - [app.util.debug :refer [debug?]] [app.common.geom.shapes :as geom])) (def mask-id-ctx (mf/create-context nil)) @@ -32,7 +31,6 @@ childs (if (and (:masked-group? shape) (not expand-mask)) (rest childs) childs) - is-child-selected? (unchecked-get props "is-child-selected?") {:keys [id x y width height]} shape transform (geom/transform-matrix shape)] [:g @@ -48,13 +46,6 @@ [:& shape-wrapper {:frame frame :shape item :key (:id item)}])] - (when (not is-child-selected?) - [:rect {:transform transform - :x x - :y y - :fill (if (debug? :group) "red" "transparent") - :opacity 0.5 - :width width - :height height}])]))) + ]))) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 56af59aad2..cfe637c693 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -28,7 +28,7 @@ group-props (-> (obj/clone props) (obj/without ["shape" "children"]) (obj/set! "id" (str "shape-" (:id shape))) - (obj/set! "className" "shape") + (obj/set! "className" (str "shape " (:type shape))) (obj/set! "filter" (filters/filter-str filter-id shape)))] [:& (mf/provider muc/render-ctx) {:value render-id} [:> :g group-props diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 4578692b2b..c420f94216 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -100,6 +100,7 @@ :width (if (#{:auto-width} grow-type) 10000 width) :height (if (#{:auto-height :auto-width} grow-type) 10000 height) :mask mask-id - :ref ref} + :ref ref + :pointer-events "none"} [:& text-content {:shape shape :content (:content shape)}]])) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 7f1a4bbf6b..de51809668 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -71,10 +71,10 @@ do-detach-component #(st/emit! (dwl/detach-component id)) do-reset-component #(st/emit! (dwl/reset-component id)) do-update-component #(do - (st/emit! dwc/start-undo-transaction) + (st/emit! (dwc/start-undo-transaction)) (st/emit! (dwl/update-component id)) (st/emit! (dwl/sync-file nil)) - (st/emit! dwc/commit-undo-transaction)) + (st/emit! (dwc/commit-undo-transaction))) do-show-component #(st/emit! (dw/go-to-layout :assets)) do-navigate-component-file #(st/emit! (dwl/nav-to-component-file (:component-file shape)))] diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index 3e265d25cb..e9d502032b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -17,7 +17,9 @@ [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.effects :as we] [app.util.dom :as dom] - [rumext.alpha :as mf])) + [rumext.alpha :as mf] + [app.common.geom.shapes :as gsh] + [app.util.debug :refer [debug?]])) (defn- group-wrapper-factory-equals? [np op] @@ -46,6 +48,9 @@ (let [shape (unchecked-get props "shape") frame (unchecked-get props "frame") + {:keys [id x y width height]} shape + transform (gsh/transform-matrix shape) + childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) childs (mf/deref childs-ref) @@ -69,16 +74,26 @@ handle-pointer-leave (we/use-pointer-leave shape) handle-double-click (use-double-click shape)] - [:> shape-container {:shape shape - :on-mouse-down handle-mouse-down - :on-context-menu handle-context-menu - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave - :on-double-click handle-double-click} - [:& group-shape - {:frame frame - :shape shape - :childs childs - :is-child-selected? is-child-selected? - :expand-mask is-mask-selected?}]])))) + [:> shape-container {:shape shape} + [:g.group-shape + [:& group-shape + {:frame frame + :shape shape + :childs childs + :expand-mask is-mask-selected?}] + + (when-not is-child-selected? + [:rect.group-actions + {:x x + :y y + :fill (if (debug? :group) "red" "transparent") + :opacity 0.5 + :transform transform + :width width + :height height + :on-mouse-down handle-mouse-down + :on-context-menu handle-context-menu + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :on-double-click handle-double-click}])]])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index ea30d02821..46121983a3 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -41,52 +41,6 @@ ;; --- Text Wrapper for workspace -(defn handle-shape-resize - [{:keys [id selrect grow-type overflow-text]} new-width new-height] - (let [{shape-width :width shape-height :height} selrect - undo-transaction (get-in @st/state [:workspace-undo :transaction])] - (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) - (when (and (> new-width 0) (> new-height 0)) - (cond - (and overflow-text (not= :fixed grow-type)) - (st/emit! (dwt/update-overflow-text id false)) - - (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) - (st/emit! (dwt/update-overflow-text id true)) - - (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) - (st/emit! (dwt/update-overflow-text id false)) - - (and (or (not= shape-width new-width) - (not= shape-height new-height)) - (= grow-type :auto-width)) - (when (and (pos? shape-width) - (pos? shape-height)) - (st/emit! (dw/update-dimensions [id] :width new-width) - (dw/update-dimensions [id] :height new-height))) - - (and (not= shape-height new-height) (= grow-type :auto-height)) - (when (pos? shape-height) - (st/emit! (dw/update-dimensions [id] :height new-height))))) - (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))) - -(defn resize-observer [{:keys [id selrect grow-type overflow-text] :as shape} root query] - (mf/use-effect - (mf/deps id selrect grow-type overflow-text root query) - (fn [] - (let [on-change (fn [entries] - (when (seq entries) - ;; RequestAnimationFrame so the "loop limit error" error is not thrown - ;; https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded - (timers/raf - #(let [width (obj/get-in entries [0 "contentRect" "width"]) - height (obj/get-in entries [0 "contentRect" "height"])] - (handle-shape-resize shape (mth/ceil width) (mth/ceil height)))))) - observer (js/ResizeObserver. on-change) - node (when root (dom/query root query))] - (when node (.observe observer node)) - #(.disconnect observer))))) - (mf/defc text-wrapper {::mf/wrap-props false} [props] @@ -109,21 +63,50 @@ handle-pointer-leave (we/use-pointer-leave shape) handle-double-click (use-double-click shape selected?) - text-ref (mf/use-ref nil) - text-node (mf/ref-val text-ref)] + paragraph-ref (mf/use-var nil) - (resize-observer shape text-node ".paragraph-set") + handle-resize-text + (mf/use-callback + (mf/deps id) + (fn [entries] + (when (seq entries) + ;; RequestAnimationFrame so the "loop limit error" error is not thrown + ;; https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded + (timers/raf + #(let [width (obj/get-in entries [0 "contentRect" "width"]) + height (obj/get-in entries [0 "contentRect" "height"])] + (st/emit! (dwt/resize-text id (mth/ceil width) (mth/ceil height)))))))) + + text-ref-cb + (mf/use-callback + (mf/deps handle-resize-text) + (fn [node] + (when node + (let [obs-ref (atom nil)] + (timers/schedule + (fn [] + (when-let [ps-node (dom/query node ".paragraph-set")] + (reset! paragraph-ref ps-node))))))))] + + (mf/use-effect + (mf/deps @paragraph-ref handle-resize-text) + (fn [] + (when-let [paragraph-node @paragraph-ref] + (let [observer (js/ResizeObserver. handle-resize-text)] + (.observe observer paragraph-node) + #(.disconnect observer))) + )) [:> shape-container {:shape shape} ;; We keep hidden the shape when we're editing so it keeps track of the size ;; and updates the selrect acordingly [:g.text-shape {:opacity (when edition? 0)} - [:& text/text-shape {:key "text-shape" - :ref text-ref + [:& text/text-shape {:key (str "text-shape" (:id shape)) + :ref text-ref-cb :shape shape :selected? selected?}]] (when edition? - [:& editor/text-shape-edit {:key "editor" + [:& editor/text-shape-edit {:key (str "editor" (:id shape)) :shape shape}]) (when-not edition? diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 0e55d242c3..f54187a688 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -204,11 +204,11 @@ (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click-outside) lkey2 (events/listen (dom/get-root) EventType.KEYUP on-key-up)] (st/emit! (dwt/assign-editor id editor) - dwc/start-undo-transaction) + (dwc/start-undo-transaction)) #(do (st/emit! (dwt/assign-editor id nil) - dwc/commit-undo-transaction) + (dwc/commit-undo-transaction)) (events/unlistenByKey lkey1) (events/unlistenByKey lkey2)))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs index a88062f389..41fe6bd195 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs @@ -49,10 +49,10 @@ do-detach-component #(st/emit! (dwl/detach-component id)) do-reset-component #(st/emit! (dwl/reset-component id)) do-update-component #(do - (st/emit! dwc/start-undo-transaction) + (st/emit! (dwc/start-undo-transaction)) (st/emit! (dwl/update-component id)) (st/emit! (dwl/sync-file nil)) - (st/emit! dwc/commit-undo-transaction)) + (st/emit! (dwc/commit-undo-transaction))) do-show-component #(st/emit! (dw/go-to-layout :assets)) do-navigate-component-file #(st/emit! (dwl/nav-to-component-file (:component-file values)))] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs index d469acee20..016dc9652c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs @@ -81,13 +81,13 @@ (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/start-undo-transaction))) + (st/emit! (dwc/start-undo-transaction)))) on-close-picker (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/commit-undo-transaction)))] + (st/emit! (dwc/commit-undo-transaction))))] (if show? [:div.element-set diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs index 31381c3a08..e0a0289eff 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs @@ -34,12 +34,12 @@ on-open (mf/use-callback (mf/deps page-id) - #(st/emit! dwc/start-undo-transaction)) + #(st/emit! (dwc/start-undo-transaction))) on-close (mf/use-callback (mf/deps page-id) - #(st/emit! dwc/commit-undo-transaction))] + #(st/emit! (dwc/commit-undo-transaction)))] [:div.element-set [:div.element-set-title (t locale "workspace.options.canvas-background")] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index 0db47133ae..6bf6ae8994 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -172,8 +172,8 @@ (:color value)) :disable-gradient true :on-change (update-color index) - :on-open #(st/emit! dwc/start-undo-transaction) - :on-close #(st/emit! dwc/commit-undo-transaction)}]]]])) + :on-open #(st/emit! (dwc/start-undo-transaction)) + :on-close #(st/emit! (dwc/commit-undo-transaction))}]]]])) (mf/defc shadow-menu [{:keys [ids values] :as props}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs index 6419805d25..12903f28f0 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs @@ -116,13 +116,13 @@ (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/start-undo-transaction))) + (st/emit! (dwc/start-undo-transaction)))) on-close-picker (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/commit-undo-transaction)))] + (st/emit! (dwc/commit-undo-transaction))))] (if show-options [:div.element-set From e1ccde6533c603d56f9cbb2b684cf87f7b276f23 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 13:25:41 +0100 Subject: [PATCH 160/195] :bug: Fixed problem with texts inside groups --- frontend/src/app/main/ui/hooks.cljs | 7 +++++++ frontend/src/app/main/ui/workspace/effects.cljs | 5 ++--- .../ui/workspace/sidebar/options/rows/color_row.cljs | 10 +++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index ab9953317a..ba72e96c77 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -214,3 +214,10 @@ (mf/use-effect (fn [] (let [sub (->> stream (rx/subs on-subscribe))] #(rx/dispose! sub))))) + +;; https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state +(defn use-previous [value] + (let [ref (mf/use-ref)] + (mf/use-effect + #(mf/set-ref-val! ref value)) + (mf/ref-val ref))) diff --git a/frontend/src/app/main/ui/workspace/effects.cljs b/frontend/src/app/main/ui/workspace/effects.cljs index ab94350a56..8937e75132 100644 --- a/frontend/src/app/main/ui/workspace/effects.cljs +++ b/frontend/src/app/main/ui/workspace/effects.cljs @@ -60,11 +60,10 @@ nil (= type :frame) - (if selected? + (when selected? (do (dom/stop-propagation event) - (st/emit! (dw/start-move-selected))) - (st/emit! (dw/deselect-all))) + (st/emit! (dw/start-move-selected)))) :else (do diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index 45bb7e84dd..c9fbbce617 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -20,6 +20,7 @@ [app.util.color :as uc] [app.main.refs :as refs] [app.main.data.modal :as modal] + [app.main.ui.hooks :as h] [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.numeric-input :refer [numeric-input]])) @@ -120,12 +121,15 @@ disable-opacity handle-pick-color handle-open - handle-close)))] + handle-close))) + + prev-color (h/use-previous color)] (mf/use-effect - (mf/deps color) + (mf/deps color prev-color) (fn [] - (modal/update-props! :colorpicker {:data (parse-color color)}))) + (when (not= prev-color color) + (modal/update-props! :colorpicker {:data (parse-color color)})))) [:div.row-flex.color-data [:& cb/color-bullet {:color color From ab5323d8734084ce7f3c18e5a9d9dc2acf5a9771 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 13:58:48 +0100 Subject: [PATCH 161/195] :sparkles: Improves resize observer --- frontend/src/app/main/ui/workspace/shapes/text.cljs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 46121983a3..6561633082 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -23,11 +23,15 @@ [app.main.ui.workspace.shapes.common :as common] [app.main.ui.workspace.shapes.text.editor :as editor] [app.util.dom :as dom] + [app.util.logging :as log] [app.util.object :as obj] [app.util.timers :as timers] [beicon.core :as rx] [rumext.alpha :as mf])) +;; Change this to :info :debug or :trace to debug this module +(log/set-level! :warn) + ;; --- Events (defn use-double-click [{:keys [id]} selected?] @@ -44,7 +48,7 @@ (mf/defc text-wrapper {::mf/wrap-props false} [props] - (let [{:keys [id x y width height] :as shape} (unchecked-get props "shape") + (let [{:keys [id name x y width height] :as shape} (unchecked-get props "shape") selected-iref (mf/use-memo (mf/deps (:id shape)) #(refs/make-selected-ref (:id shape))) selected? (mf/deref selected-iref) @@ -63,7 +67,7 @@ handle-pointer-leave (we/use-pointer-leave shape) handle-double-click (use-double-click shape selected?) - paragraph-ref (mf/use-var nil) + paragraph-ref (mf/use-state nil) handle-resize-text (mf/use-callback @@ -93,9 +97,9 @@ (fn [] (when-let [paragraph-node @paragraph-ref] (let [observer (js/ResizeObserver. handle-resize-text)] + (log/debug :msg "Attach resize observer" :shape-id id :shape-name name) (.observe observer paragraph-node) - #(.disconnect observer))) - )) + #(.disconnect observer))))) [:> shape-container {:shape shape} ;; We keep hidden the shape when we're editing so it keeps track of the size From 28a2df96ff46f273439f493df23c75d50b8b2cd7 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Dec 2020 16:01:33 +0100 Subject: [PATCH 162/195] :tada: Add version string parsing. --- backend/src/app/config.clj | 4 +++ backend/src/app/main.clj | 10 ++++---- common/app/common/version.cljc | 18 +++++++++++++ frontend/resources/templates/index.mustache | 20 +++++++++------ frontend/src/app/config.cljs | 28 ++++++++++++++++----- manage.sh | 21 ++++++++-------- 6 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 common/app/common/version.cljc diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index 78159a6d73..41d1da2365 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -11,6 +11,7 @@ "A configuration management." (:require [app.common.spec :as us] + [app.common.version :as v] [app.util.time :as dt] [clojure.spec.alpha :as s] [cuerdas.core :as str] @@ -197,6 +198,9 @@ (def default-deletion-delay (dt/duration {:hours 48})) +(def version + (delay (v/parse "%version%"))) + (defn smtp [cfg] {:host (:smtp-host cfg "localhost") diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index a782b91187..431d3f266f 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -9,6 +9,8 @@ (ns app.main (:require + [app.config :as cfg] + [clojure.tools.logging :as log] [mount.core :as mount])) (defn- enable-asserts @@ -26,15 +28,13 @@ (defn run [_params] - (require 'app.config - 'app.srepl.server + (require 'app.srepl.server 'app.migrations 'app.worker 'app.media 'app.http) - (mount/start)) - - + (mount/start) + (log/infof "Welcome to penpot! Version: '%s'." (:full @cfg/version))) (defn -main [& _args] diff --git a/common/app/common/version.cljc b/common/app/common/version.cljc new file mode 100644 index 0000000000..5edb35d091 --- /dev/null +++ b/common/app/common/version.cljc @@ -0,0 +1,18 @@ +(ns app.common.version + "A version parsing helper." + (:require + [app.common.data :as d] + [cuerdas.core :as str])) + +(defn parse + [version] + (if (= version "%version%") + {:full "develop" + :base "develop" + :build 0 + :commit nil} + (let [[base build commit] (str/split version #"-" 3)] + {:full version + :base base + :build (d/parse-integer build) + :commit commit}))) diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache index 801633eb1f..7011dce991 100644 --- a/frontend/resources/templates/index.mustache +++ b/frontend/resources/templates/index.mustache @@ -6,21 +6,27 @@ PENPOT - The Open-Source prototyping tool + - - - {{>../public/images/sprites/symbol/svg/sprite.symbol.svg}} -
- + {{# manifest}} + {{/manifest}} + + + + {{>../public/images/sprites/symbol/svg/sprite.symbol.svg}} +
+ + {{# manifest}} {{/manifest}} diff --git a/frontend/src/app/config.cljs b/frontend/src/app/config.cljs index bff44964cb..0d06269958 100644 --- a/frontend/src/app/config.cljs +++ b/frontend/src/app/config.cljs @@ -10,15 +10,19 @@ (ns app.config (:require [clojure.spec.alpha :as s] + [app.common.data :as d] [app.common.spec :as us] + [app.common.version :as v] [app.util.object :as obj] [app.util.dom :as dom] [cuerdas.core :as str])) +;; --- Auxiliar Functions + (s/def ::platform #{:windows :linux :macos :other}) (s/def ::browser #{:chrome :mozilla :safari :edge :other}) -(defn parse-browser +(defn- parse-browser [] (let [user-agent (-> (dom/get-user-agent) str/lower) check-chrome? (fn [] (str/includes? user-agent "chrom")) @@ -32,7 +36,7 @@ (check-safari?) :safari :else :other))) -(defn parse-platform +(defn- parse-platform [] (let [user-agent (-> (dom/get-user-agent) str/lower) check-windows? (fn [] (str/includes? user-agent "windows")) @@ -44,6 +48,10 @@ (check-macos?) :macos :else :other))) +;; --- Globar Config Vars + +(def default-theme "default") + (this-as global (def default-language "en") (def demo-warning (obj/get global "appDemoWarning" false)) @@ -53,10 +61,18 @@ (def worker-uri (obj/get global "appWorkerURI" "/js/worker.js")) (def public-uri (or (obj/get global "appPublicURI") (.-origin ^js js/location))) - (def media-uri (str public-uri "/media")) - (def default-theme "default") - (def browser (parse-browser)) - (def platform (parse-platform))) + (def version (v/parse (obj/get global "appVersion")))) + + +(def media-uri (str public-uri "/media")) +(def browser (parse-browser)) +(def platform (parse-platform)) + +(js/console.log + (str/format "Welcome to pentpot! Version: '%s'" (:full version))) + +;; --- Helper Functions + (defn ^boolean check-browser? [candidate] (us/verify ::browser candidate) diff --git a/manage.sh b/manage.sh index 0bae480bc6..b628f83283 100755 --- a/manage.sh +++ b/manage.sh @@ -6,7 +6,7 @@ export DEVENV_IMGNAME="$ORGANIZATION/devenv"; export DEVENV_PNAME="penpotdev"; export CURRENT_USER_ID=$(id -u); -export CURRENT_GIT_TAG=$(git describe --tags); +export CURRENT_VERSION=$(git describe --tags); export CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD); function build-devenv { @@ -95,12 +95,11 @@ function build-bundle { mv ./backend/target/dist ./bundle/backend mv ./exporter/target ./bundle/exporter - local name="penpot-$CURRENT_GIT_TAG"; + local name="penpot-$CURRENT_VERSION"; + echo $CURRENT_VERSION > ./bundle/version.txt - echo $CURRENT_GIT_TAG > ./bundle/frontend/version.txt - echo $CURRENT_GIT_TAG > ./bundle/backend/main/version.txt - echo $CURRENT_GIT_TAG > ./bundle/exporter/version.txt - echo $CURRENT_GIT_TAG > ./bundle/version.txt + sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./bundle/frontend/index.html; + sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./bundle/backend/main/app/config.clj; local generate_tar=${PENPOT_BUILD_GENERATE_TAR:-"true"}; @@ -124,12 +123,12 @@ function build-image { pushd ./docker/images; local docker_image="$ORGANIZATION/$image"; - docker build -t $docker_image:$CURRENT_GIT_TAG -f Dockerfile.$image .; + docker build -t $docker_image:$CURRENT_VERSION -f Dockerfile.$image .; popd; } function build-images { - local bundle_file="penpot-$CURRENT_GIT_TAG.tar.xz"; + local bundle_file="penpot-$CURRENT_VERSION.tar.xz"; if [ ! -f $bundle_file ]; then echo "File '$bundle_file' does not exists."; @@ -153,9 +152,9 @@ function build-images { function publish-snapshot { set -x - docker tag $ORGANIZATION/frontend:$CURRENT_GIT_TAG $ORGANIZATION/frontend:$CURRENT_GIT_BRANCH - docker tag $ORGANIZATION/backend:$CURRENT_GIT_TAG $ORGANIZATION/backend:$CURRENT_GIT_BRANCH - docker tag $ORGANIZATION/exporter:$CURRENT_GIT_TAG $ORGANIZATION/exporter:$CURRENT_GIT_BRANCH + docker tag $ORGANIZATION/frontend:$CURRENT_VERSION $ORGANIZATION/frontend:$CURRENT_GIT_BRANCH + docker tag $ORGANIZATION/backend:$CURRENT_VERSION $ORGANIZATION/backend:$CURRENT_GIT_BRANCH + docker tag $ORGANIZATION/exporter:$CURRENT_VERSION $ORGANIZATION/exporter:$CURRENT_GIT_BRANCH docker push $ORGANIZATION/frontend:$CURRENT_GIT_BRANCH; docker push $ORGANIZATION/backend:$CURRENT_GIT_BRANCH; From 0da16c72198d39817122d55212a2864a594e7c18 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Dec 2020 16:01:55 +0100 Subject: [PATCH 163/195] :sparkles: Make all background task execute daily (instead of hourly). --- backend/src/app/worker.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/app/worker.clj b/backend/src/app/worker.clj index 5ee7d9d187..2b71beacd1 100644 --- a/backend/src/app/worker.clj +++ b/backend/src/app/worker.clj @@ -57,14 +57,14 @@ :fn #'app.tasks.trim-file/handler} {:id "maintenance/delete-executed-tasks" - :cron #app/cron "0 0 */1 * * ?" ;; hourly + :cron #app/cron "0 0 0 */1 * ?" ;; daily :fn #'app.tasks.maintenance/delete-executed-tasks - :props {:max-age #app/duration "48h"}} + :props {:max-age #app/duration "24h"}} {:id "maintenance/delete-old-files-xlog" - :cron #app/cron "0 0 */1 * * ?" ;; hourly + :cron #app/cron "0 0 0 */1 * ?" ;; daily :fn #'app.tasks.maintenance/delete-old-files-xlog - :props {:max-age #app/duration "8h"}} + :props {:max-age #app/duration "12h"}} ]) (defstate executor From 62d98ad265ae1a36069bb2e7b1ecebe23e3f648e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 15:22:59 +0100 Subject: [PATCH 164/195] :bug: Fixed styles for typography advanced options --- .../main/partials/sidebar-element-options.scss | 12 +++--------- frontend/resources/styles/main/partials/sidebar.scss | 2 +- .../main/ui/workspace/sidebar/options/common.cljs | 12 ++++++++++-- .../ui/workspace/sidebar/options/typography.cljs | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss index 4465ef2c35..ed324a469b 100644 --- a/frontend/resources/styles/main/partials/sidebar-element-options.scss +++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss @@ -760,30 +760,23 @@ left: 0; position: absolute; top: 0; - width: 100%; + width: calc(100% - 8px); opacity: 0.4; z-index: 10; } .advanced-options-wrapper { - position: absolute; width: 100%; - padding-right: 1.5rem; padding-left: 0.25rem; } -.element-options .advanced-options-wrapper { - padding-right: 1rem; -} - .advanced-options { background-color: #303236; border-radius: 4px; - left: -8px; padding: 0.5rem; position: relative; top: 2px; - width: calc(100% + 16px); + width: 100%; z-index: 20; } @@ -918,6 +911,7 @@ flex-grow: 1; font-size: 11px; margin-top: 4px; + white-space: nowrap; } .element-set-actions-button svg { diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index e03353aec6..3c11fe1059 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -171,7 +171,7 @@ $width-settings-bar: 16rem; .tool-window-content { display: flex; flex-direction: column; - overflow-y: auto; + // overflow-y: auto; height: 100%; width: 100%; } diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs index a37caa0095..91f0eb4383 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/common.cljs @@ -13,13 +13,21 @@ [app.util.dom :as dom])) (mf/defc advanced-options [{:keys [visible? on-close children]}] - (let [handle-click (fn [event] (when on-close + (let [ref (mf/use-ref nil) + handle-click (fn [event] (when on-close (do (dom/stop-propagation event) (on-close))))] + (mf/use-effect + (mf/deps visible?) + (fn [] + (when-let [node (mf/ref-val ref)] + (when visible? + (.scrollIntoViewIfNeeded ^js node))))) + (when visible? [:* [:div.focus-overlay {:on-click handle-click}] - [:div.advanced-options-wrapper + [:div.advanced-options-wrapper {:ref ref} [:div.advanced-options {} children]]]))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs index b7a9b8200b..5af24e2539 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/typography.cljs @@ -270,7 +270,7 @@ (if read-only? [:div.element-set-content.typography-read-only-data [:div.row-flex.typography-name - [:spang (:name typography)]] + [:span (:name typography)]] [:div.row-flex [:span.label (t locale "workspace.assets.typography.font-id")] From d0306ac92cfbc0fb7919426df5344e0f096947d7 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 17:35:13 +0100 Subject: [PATCH 165/195] :bug: Fixes some issues with text shape --- .../src/app/main/data/workspace/drawing.cljs | 2 -- .../src/app/main/data/workspace/texts.cljs | 36 +++++++++---------- .../app/main/data/workspace/transforms.cljs | 1 - frontend/src/app/main/store.cljs | 5 +-- .../app/main/ui/workspace/shapes/text.cljs | 6 ++-- .../main/ui/workspace/shapes/text/editor.cljs | 4 +-- frontend/src/app/util/debug.cljs | 5 +++ 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index d83d2b79c6..ece9fffba6 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -39,8 +39,6 @@ (watch [_ state stream] (let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)] (rx/merge - (rx/of (dws/deselect-all)) - (when (= tool :path) (rx/of (start-drawing :path))) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index ed9b2dc821..3f8a34596a 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -16,7 +16,7 @@ [clojure.walk :as walk] [goog.object :as gobj] [potok.core :as ptk] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] [app.common.attrs :as attrs] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.transforms :as dwt] @@ -218,32 +218,28 @@ (watch [_ state stream] (let [page-id (:current-page-id state) shape (get-in state [:workspace-data :pages-index page-id :objects id]) - {:keys [selrect grow-type overflow-text]} shape + {:keys [selrect grow-type overflow-text]} (gsh/transform-shape shape) {shape-width :width shape-height :height} selrect undo-transaction (get-in state [:workspace-undo :transaction]) - events (when (and (> new-width 0) (> new-height 0)) - (cond - (and overflow-text (not= :fixed grow-type)) - [(update-overflow-text id false)] + events + (cond-> [] + (and overflow-text (not= :fixed grow-type)) + (conj (update-overflow-text id false)) - (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) - [(update-overflow-text id true)] + (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) + (conj (update-overflow-text id true)) - (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) - [(update-overflow-text id false)] + (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) + (conj (update-overflow-text id false)) - (and (or (not= shape-width new-width) - (not= shape-height new-height)) - (= grow-type :auto-width)) - (when (and (pos? shape-width) - (pos? shape-height)) - [(dwt/update-dimensions [id] :width new-width) - (dwt/update-dimensions [id] :height new-height)]) + (and (or (not= shape-width new-width) (not= shape-height new-height)) + (= grow-type :auto-width)) + (conj (dwt/update-dimensions [id] :width new-width) + (dwt/update-dimensions [id] :height new-height)) - (and (not= shape-height new-height) (= grow-type :auto-height)) - (when (pos? shape-height) - [(dwt/update-dimensions [id] :height new-height)])))] + (and (not= shape-height new-height) (= grow-type :auto-height)) + (conj (dwt/update-dimensions [id] :height new-height)))] (if (not (empty? events)) (rx/concat diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 44d7658a04..514b59b50c 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -488,5 +488,4 @@ (ptk/reify ::update-dimensions ptk/WatchEvent (watch [_ state stream] - #_(prn "??? update-dimensions" ids attr value) (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index e182969f3e..4b06ecce08 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -15,7 +15,7 @@ [app.common.pages-helpers :as cph] [app.common.uuid :as uuid] [app.util.storage :refer [storage]] - [app.util.debug :refer [debug? logjs]])) + [app.util.debug :refer [debug? debug-exclude-events logjs]])) (enable-console-print!) @@ -43,7 +43,8 @@ (defonce debug-subscription (->> stream (rx/filter ptk/event?) - (rx/filter (fn [s] (debug? :events))) + (rx/filter (fn [s] (and (debug? :events) + (not (debug-exclude-events (ptk/type s)))))) (rx/subs #(println "[stream]: " (repr-event %)))))) (defn emit! ([] nil) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 6561633082..8d612bb421 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -48,7 +48,7 @@ (mf/defc text-wrapper {::mf/wrap-props false} [props] - (let [{:keys [id name x y width height] :as shape} (unchecked-get props "shape") + (let [{:keys [id name x y width height grow-type] :as shape} (unchecked-get props "shape") selected-iref (mf/use-memo (mf/deps (:id shape)) #(refs/make-selected-ref (:id shape))) selected? (mf/deref selected-iref) @@ -79,6 +79,7 @@ (timers/raf #(let [width (obj/get-in entries [0 "contentRect" "width"]) height (obj/get-in entries [0 "contentRect" "height"])] + (log/debug :msg "Resize detected" :shape-id id :width width :height height) (st/emit! (dwt/resize-text id (mth/ceil width) (mth/ceil height)))))))) text-ref-cb @@ -93,7 +94,7 @@ (reset! paragraph-ref ps-node))))))))] (mf/use-effect - (mf/deps @paragraph-ref handle-resize-text) + (mf/deps @paragraph-ref handle-resize-text grow-type) (fn [] (when-let [paragraph-node @paragraph-ref] (let [observer (js/ResizeObserver. handle-resize-text)] @@ -101,6 +102,7 @@ (.observe observer paragraph-node) #(.disconnect observer))))) + [:> shape-container {:shape shape} ;; We keep hidden the shape when we're editing so it keeps track of the size ;; and updates the selrect acordingly diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index f54187a688..8776173587 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -165,13 +165,13 @@ on-click-outside (fn [event] - (let [sidebar (dom/get-element "settings-bar") + (let [options (dom/get-element-by-class "element-options") assets (dom/get-element-by-class "assets-bar") cpicker (dom/get-element-by-class "colorpicker-tooltip") self (mf/ref-val self-ref) target (dom/get-target event) selecting? (mf/ref-val selecting-ref)] - (when-not (or (and sidebar (.contains sidebar target)) + (when-not (or (and options (.contains options target)) (and assets (.contains assets target)) (and self (.contains self target)) (and cpicker (.contains cpicker target))) diff --git a/frontend/src/app/util/debug.cljs b/frontend/src/app/util/debug.cljs index c562b1b3f7..b1787add2e 100644 --- a/frontend/src/app/util/debug.cljs +++ b/frontend/src/app/util/debug.cljs @@ -4,6 +4,11 @@ (def debug-options #{:bounding-boxes :group :events :rotation-handler :resize-handler :selection-center #_:simple-selection}) +;; These events are excluded when we activate the :events flag +(def debug-exclude-events + #{:app.main.data.workspace.notifications/handle-pointer-update + :app.main.data.workspace.selection/change-hover-state}) + (defonce ^:dynamic *debug* (atom #{})) (defn debug-all! [] (reset! *debug* debug-options)) From c30aa7346bf018a91dc60ba1914e2f221366298b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 22:16:51 +0100 Subject: [PATCH 166/195] :sparkles: Removed slider for shapes rotation --- .../src/app/main/ui/workspace/sidebar/options/measures.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index eabf072939..6a46ea5317 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -173,7 +173,7 @@ :on-click select-all :on-change on-rotation-change :value (attr->string :rotation values)}]] - [:input.slidebar + #_[:input.slidebar {:type "range" :min "0" :max "359" From 2aaa82a5c422a364eaeb7143431235c3406b846c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 22:58:53 +0100 Subject: [PATCH 167/195] :bug: Fixed thumbnail to change color --- frontend/src/app/main/ui/workspace/sidebar/assets.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 4094eeee12..d3072e1a8b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -313,7 +313,8 @@ nil)) [:div.group-list-item {:on-context-menu on-context-menu} - [:& bc/color-bullet {:color color}] + [:& bc/color-bullet {:color color + :on-click click-color}] (if (:editing @state) [:input.element-name From 4d4e7c75dae896989a72404825d84b1c59eb8fc2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 4 Dec 2020 23:11:26 +0100 Subject: [PATCH 168/195] :sparkles: Changes image shortcut to K --- frontend/resources/locales.json | 8 ++++---- frontend/src/app/main/data/workspace.cljs | 4 ++++ frontend/src/app/main/ui/workspace/left_toolbar.cljs | 9 +++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index ceddb5b7b7..99362eba22 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -3689,10 +3689,10 @@ "workspace.toolbar.image" : { "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:79" ], "translations" : { - "en" : "Image (I)", - "fr" : "Image (I)", - "ru" : "Изображение (I)", - "es" : "Imagen (I)" + "en" : "Image (K)", + "fr" : "Image (K)", + "ru" : "Изображение (K)", + "es" : "Imagen (K)" } }, "workspace.toolbar.libraries" : { diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 99fbecd7d9..724c987bd4 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -44,6 +44,7 @@ [app.util.transit :as t] [app.util.webapi :as wapi] [app.util.i18n :refer [tr] :as i18n] + [app.util.dom :as dom] [beicon.core :as rx] [cljs.spec.alpha :as s] [clojure.set :as set] @@ -1674,6 +1675,9 @@ "t" #(st/emit! dwtxt/start-edit-if-selected (dwd/select-for-drawing :text)) "p" #(st/emit! (dwd/select-for-drawing :path)) + "k" (fn [event] + (let [image-upload (dom/get-element "image-upload")] + (dom/click image-upload))) (c-mod "c") #(st/emit! copy-selected) (c-mod "x") #(st/emit! copy-selected delete-selected) "escape" #(st/emit! (esc-pressed)) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index 5137d3fdee..fc96f2f7c2 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -80,10 +80,11 @@ :on-click on-image} [:* i/image - [:& file-uploader {:accept cm/str-media-types - :multi true - :input-ref file-input - :on-selected on-files-selected}]]] + [:& file-uploader {:input-id "image-upload" + :accept cm/str-media-types + :multi true + :input-ref file-input + :on-selected on-files-selected}]]] [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.curve") :class (when (= selected-drawtool :curve) "selected") From 489dc521e3025ee44d5140333d2f85f9a5767cdf Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Mon, 7 Dec 2020 12:10:05 +0100 Subject: [PATCH 169/195] :tada: Fix project name edit field --- frontend/resources/styles/main/partials/dashboard.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/resources/styles/main/partials/dashboard.scss b/frontend/resources/styles/main/partials/dashboard.scss index 2aed67220e..38b467b49a 100644 --- a/frontend/resources/styles/main/partials/dashboard.scss +++ b/frontend/resources/styles/main/partials/dashboard.scss @@ -135,6 +135,7 @@ border: 1px solid $color-gray-10; border-radius: $br-small; display: flex; + padding-right: $big; position: relative; input.element-title { From 1b5efa6ba25f94d4a26a786dcc6fb15481a315dc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 08:55:54 +0100 Subject: [PATCH 170/195] :bug: Fixed issue with shared token for logged users --- backend/src/app/services/queries/viewer.clj | 2 +- backend/tests/app/tests/test_services_viewer.clj | 2 +- frontend/src/app/main/data/viewer.cljs | 8 ++++---- frontend/src/app/main/ui/viewer/header.cljs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/app/services/queries/viewer.clj b/backend/src/app/services/queries/viewer.clj index 27d52a88ab..000f383620 100644 --- a/backend/src/app/services/queries/viewer.clj +++ b/backend/src/app/services/queries/viewer.clj @@ -65,7 +65,7 @@ (assoc bundle :token token)) (let [stoken (retrieve-shared-token conn file-id page-id)] (files/check-read-permissions! conn profile-id file-id) - (assoc bundle :share-token (:token stoken))))))) + (assoc bundle :token (:token stoken))))))) (defn check-shared-token! [conn file-id page-id token] diff --git a/backend/tests/app/tests/test_services_viewer.clj b/backend/tests/app/tests/test_services_viewer.clj index c4544475ed..4b582eda1d 100644 --- a/backend/tests/app/tests/test_services_viewer.clj +++ b/backend/tests/app/tests/test_services_viewer.clj @@ -43,7 +43,7 @@ (t/is (nil? (:error out))) (let [result (:result out)] - (t/is (contains? result :share-token)) + (t/is (contains? result :token)) (t/is (contains? result :page)) (t/is (contains? result :file)) (t/is (contains? result :project))))) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 739cc0cefe..8e7e7a40da 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -138,7 +138,7 @@ (d/index-by :id) (assoc state :comment-threads))) (on-error [err] - (if (= :authorization (:type err)) + (if (= :not-authorized (:code err)) (rx/empty) (rx/throw err)))] @@ -180,7 +180,7 @@ (->> (rp/mutation! :create-file-share-token {:file-id file-id :page-id page-id}) (rx/map (fn [{:keys [token]}] - #(assoc-in % [:viewer-data :share-token] token)))))))) + #(assoc-in % [:viewer-data :token] token)))))))) (defn delete-share-link [] @@ -189,12 +189,12 @@ (watch [_ state stream] (let [file-id (:current-file-id state) page-id (:current-page-id state) - token (get-in state [:viewer-data :share-token]) + token (get-in state [:viewer-data :token]) params {:file-id file-id :page-id page-id :token token}] (->> (rp/mutation :delete-file-share-token params) - (rx/map (fn [_] #(update % :viewer-data dissoc :share-token)))))))) + (rx/map (fn [_] #(update % :viewer-data dissoc :token)))))))) ;; --- Zoom Management diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index fc1df4b094..21e15787d1 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -257,7 +257,7 @@ nil) (when-not anonymous? - [:& share-link {:token (:share-token data) + [:& share-link {:token (:token data) :page (:page data)}]) (when-not anonymous? From 86dc2379a309323dd35ea1ee5a5770c08e39ce1c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 14:08:24 +0100 Subject: [PATCH 171/195] :bug: Fixed problems with groups selrect --- common/app/common/geom/shapes.cljc | 1 + common/app/common/geom/shapes/common.cljc | 2 +- common/app/common/geom/shapes/transforms.cljc | 23 +++++++++ common/app/common/pages.cljc | 29 +++-------- .../ui/workspace/shapes/bounding_box.cljs | 49 +++++++++++++------ 5 files changed, 67 insertions(+), 37 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 5dbb6260e7..628dc43222 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -266,6 +266,7 @@ (d/export gtr/transform-matrix) (d/export gtr/transform-point-center) (d/export gtr/transform-rect) +(d/export gtr/update-group-selrect) ;; PATHS (d/export gsp/content->points) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index 49abc5943d..98dcf12574 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -42,7 +42,7 @@ (defn center-shape "Calculate the center of the shape." [shape] - (center-rect (:selrect shape))) + (center-points (:points shape))) (defn make-centered-rect "Creates a rect given a center and a width and height" diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 6248131a72..2def83afa2 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -262,3 +262,26 @@ (apply-transform transform) (dissoc :modifiers))) shape))) + +(defn update-group-selrect [group children] + (let [shape-center (gco/center-shape group) + + ;; Points for every shape inside the group + points (->> children (mapcat :points)) + + ;; Invert to get the points minus the transforms applied to the group + base-points (transform-points points shape-center (:transform-inverse group)) + + ;; Defines the new selection rect with its transformations + new-points (-> (gpr/points->selrect base-points) + (gpr/rect->points) + (transform-points shape-center (:transform group))) + + ;; Calculte the new selrect + new-selrect (gpr/points->selrect base-points)] + + ;; Updates the shape and the applytransform-rect will update the other properties + (-> group + (assoc :selrect new-selrect) + (assoc :points new-points) + (apply-transform-rect (gmt/matrix))))) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index a73d8d7f2b..51720fab6e 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -14,7 +14,7 @@ [app.common.data :as d] [app.common.pages-helpers :as cph] [app.common.exceptions :as ex] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.spec :as us] @@ -840,7 +840,7 @@ (defn rotation-modifiers [center shape angle] - (let [displacement (let [shape-center (geom/center-shape shape)] + (let [displacement (let [shape-center (gsh/center-shape shape)] (-> (gmt/matrix) (gmt/rotate angle center) (gmt/rotate (- angle) shape-center)))] @@ -860,26 +860,11 @@ (distinct)) shapes))) (update-group [group objects] - (let [gcenter (geom/center-shape group) - gxfm (comp - (map #(get objects %)) - (map #(-> % - (assoc :modifiers - (rotation-modifiers gcenter % (- (:rotation group 0)))) - (geom/transform-shape)))) - inner-shapes (if (:masked-group? group) - [(first (:shapes group))] - (:shapes group)) - selrect (-> (into [] gxfm inner-shapes) - (geom/selection-rect))] - - ;; Rotate the group shape change the data and rotate back again - (-> group - (assoc :selrect selrect) - (assoc :points (geom/rect->points selrect)) - (merge (select-keys selrect [:x :y :width :height])) - (assoc-in [:modifiers :rotation] (:rotation group 0)) - (geom/transform-shape))))] + (let [children (->> (if (:masked-group? group) + [(first (:shapes group))] + (:shapes group)) + (map #(get objects %)))] + (gsh/update-group-selrect group children)))] (if page-id (d/update-in-when data [:pages-index page-id :objects] reg-objects) diff --git a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs index 2a442bb258..10edd1b2bd 100644 --- a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs @@ -9,7 +9,7 @@ [cuerdas.core :as str] [rumext.alpha :as mf] [app.util.debug :as debug] - [app.common.geom.shapes :as geom] + [app.common.geom.shapes :as gsh] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.util.debug :refer [debug?]] @@ -35,16 +35,41 @@ :stroke-width "1px" :stroke-opacity 0.5}]])) +(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color]}] + [:rect {:x x + :y y + :width width + :height height + :style {:stroke color + :fill "transparent" + :stroke-width "1px" + :stroke-opacity 0.5 + :stroke-dasharray 4 + :pointer-events "none"}}]) + +(mf/defc render-rect-points [{:keys [points color]}] + (for [[p1 p2] (map vector points (concat (rest points) [(first points)]))] + [:line {:x1 (:x p1) + :y1 (:y p1) + :x2 (:x p2) + :y2 (:y p2) + :style {:stroke color + :stroke-width "1px"}}])) + (mf/defc bounding-box {::mf/wrap-props false} [props] (when (debug? :bounding-boxes) - (let [shape (unchecked-get props "shape") + (let [shape (-> (unchecked-get props "shape")) frame (unchecked-get props "frame") - selrect (-> shape :selrect) - shape-center (geom/center-shape shape) + selrect (gsh/points->selrect (-> shape :points)) + shape-center (gsh/center-shape shape) line-color (rdcolor #js {:seed (str (:id shape))}) - zoom (mf/deref refs/selected-zoom)] + zoom (mf/deref refs/selected-zoom) + childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) + childs (->> (mf/deref childs-ref) + (map gsh/transform-shape))] + [:g.bounding-box [:text {:x (:x selrect) :y (- (:y selrect) 5) @@ -63,12 +88,8 @@ :zoom zoom :color line-color}]) - [:rect {:x (:x selrect) - :y (:y selrect) - :width (:width selrect) - :height (:height selrect) - :style {:stroke line-color - :fill "transparent" - :stroke-width "1px" - :stroke-opacity 0.5 - :pointer-events "none"}}]]))) + [:& render-rect-points {:rect selrect + :color line-color}] + + [:& render-rect {:rect selrect + :color line-color}]]))) From 1b9aae3bbd7204dae78749ded68b2a9c342b5e56 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 14:13:39 +0100 Subject: [PATCH 172/195] :arrow_up: Upgrades highlight.js --- frontend/package.json | 2 +- frontend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 2bffc5c7ab..4c52e371cc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "date-fns": "^2.15.0", - "highlight.js": "^10.3.1", + "highlight.js": "^10.4.1", "js-beautify": "^1.13.0", "mousetrap": "^1.6.5", "randomcolor": "^0.6.2", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 0225cfb407..fd6f4a6d59 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2247,10 +2247,10 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -highlight.js@^10.3.1: - version "10.3.2" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.3.2.tgz#135fd3619a00c3cbb8b4cd6dbc78d56bfcbc46f1" - integrity sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw== +highlight.js@^10.4.1: + version "10.4.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" + integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== hmac-drbg@^1.0.0: version "1.0.1" From 24e998ca2e8cd8a0842c680590a13cf55fb86c9d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 15:05:51 +0100 Subject: [PATCH 173/195] :bug: Fixed problem with center shapes --- common/app/common/geom/shapes/common.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/app/common/geom/shapes/common.cljc b/common/app/common/geom/shapes/common.cljc index 98dcf12574..49abc5943d 100644 --- a/common/app/common/geom/shapes/common.cljc +++ b/common/app/common/geom/shapes/common.cljc @@ -42,7 +42,7 @@ (defn center-shape "Calculate the center of the shape." [shape] - (center-points (:points shape))) + (center-rect (:selrect shape))) (defn make-centered-rect "Creates a rect given a center and a width and height" From 266d4c837c7ef4f5aa31cbc403fdf1c1b86c0077 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 15:51:00 +0100 Subject: [PATCH 174/195] :bug: Fixes problem with create shape on a snap point --- .../app/main/data/workspace/drawing/box.cljs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index bdcdb1aeaf..1519cd3652 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -18,13 +18,14 @@ [app.main.data.workspace.common :as dwc] [app.main.snap :as snap] [app.main.streams :as ms] - [app.main.data.workspace.drawing.common :as common])) + [app.main.data.workspace.drawing.common :as common] + [app.common.math :as mth])) -(defn resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] +(defn resize-shape [{:keys [x y width height transform transform-inverse] :as shape} point lock?] (let [;; The new shape behaves like a resize on the bottom-right corner initial (gpt/point (+ x width) (+ y height)) shapev (gpt/point width height) - deltav (gpt/to-vec initial point-snap) + deltav (gpt/to-vec initial point) scalev (gpt/divide (gpt/add shapev deltav) shapev) scalev (if lock? (let [v (max (:x scalev) (:y scalev))] @@ -36,8 +37,15 @@ (assoc-in [:modifiers :resize-origin] (gpt/point x y)) (assoc-in [:modifiers :resize-rotation] 0)))) -(defn update-drawing [state point lock? point-snap] - (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap)) +(defn update-drawing [state point lock?] + (update-in state [:workspace-drawing :object] resize-shape point lock?)) + +(defn move-drawing + [{:keys [x y]}] + (fn [state] + (let [x (mth/precision x 0) + y (mth/precision y 0)] + (update-in state [:workspace-drawing :object] gsh/absolute-move (gpt/point x y))))) (defn handle-drawing-box [] (ptk/reify ::handle-drawing-box @@ -73,9 +81,7 @@ ;; Initial SNAP (->> (snap/closest-snap-point page-id [shape] layout initial) - (rx/map (fn [{:keys [x y]}] - #(update-in % [:workspace-drawing :object] gsh/absolute-move (gpt/point x y)) - ))) + (rx/map move-drawing)) (->> ms/mouse-position (rx/filter #(> (gpt/distance % initial) 2)) @@ -85,8 +91,8 @@ (->> (snap/closest-snap-point page-id [shape] layout point) (rx/map #(conj current %))))) (rx/map - (fn [[pt ctrl? point-snap]] - #(update-drawing % pt ctrl? point-snap))) + (fn [[_ ctrl? point]] + #(update-drawing % point ctrl?))) (rx/take-until stoper)) (rx/of common/handle-finish-drawing)))))) From 2f1b72e105b9dbc03a60c6d71f932933183eef88 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 15:56:21 +0100 Subject: [PATCH 175/195] :bug: Disallowing negative border radius --- frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index 6a46ea5317..c26a11a8c2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -189,6 +189,7 @@ [:div.input-element.pixels [:> numeric-input {:placeholder "--" + :min "0" :on-click select-all :on-change on-radius-change :value (attr->string :rx values)}]] From 621545cc749425f5d53d1ff673b8e1b493b488fe Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 16:17:44 +0100 Subject: [PATCH 176/195] :bug: Allows remove fill in text shapes --- frontend/src/app/main/ui/shapes/text/styles.cljs | 6 ++++++ frontend/src/app/main/ui/workspace/shapes/text/editor.cljs | 4 +++- frontend/src/app/util/text.cljs | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 02926dc781..fa230f1af5 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -83,7 +83,13 @@ fill-color-ref-id (obj/get data "fill-color-ref-id") fill-color-ref-file (obj/get data "fill-color-ref-file") + ;; Uncomment this to allow to remove text colors. This could break the texts that already exist + ;;[r g b a] (if (nil? fill-color) + ;; [0 0 0 0] ;; Transparent color + ;; (uc/hex->rgba fill-color fill-opacity)) + [r g b a] (uc/hex->rgba fill-color fill-opacity) + text-color (if fill-color-gradient (uc/gradient->css (js->clj fill-color-gradient)) (str/format "rgba(%s, %s, %s, %s)" r g b a)) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 8776173587..499b72b88f 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -37,7 +37,9 @@ [{:type "root" :children [{:type "paragraph-set" :children [{:type "paragraph" - :children [{:text (or text "")}]}]}]}])) + :children [{:fill-color "#000000" + :fill-opacity 1 + :text (or text "")}]}]}]}])) (defn- parse-content [content] (cond diff --git a/frontend/src/app/util/text.cljs b/frontend/src/app/util/text.cljs index 4e1ad7136a..c00547c9f7 100644 --- a/frontend/src/app/util/text.cljs +++ b/frontend/src/app/util/text.cljs @@ -16,7 +16,7 @@ :text-transform "none" :text-align "left" :text-decoration "none" - :fill-color "#000000" + :fill-color nil :fill-opacity 1}) (def typography-fields From 60e6dd7822246bc8e1c902e6d825f71a14d39493 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 16:45:18 +0100 Subject: [PATCH 177/195] :bug: Fixed count projects in dashboard when deleting file --- frontend/src/app/main/data/dashboard.cljs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 395503836f..10eba755d0 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -419,6 +419,8 @@ ;; --- Delete File (by id) +(declare delete-file-result) + (defn delete-file [{:keys [id project-id] :as params}] (us/assert ::file params) @@ -431,8 +433,18 @@ ptk/WatchEvent (watch [_ state s] - (->> (rp/mutation :delete-file {:id id}) - (rx/ignore))))) + (let [team-id (uuid/uuid (get-in state [:route :path-params :team-id]))] + (->> (rp/mutation :delete-file {:id id}) + (rx/map #(delete-file-result team-id project-id))))))) + +(defn delete-file-result + [team-id project-id] + + (ptk/reify ::delete-file + ptk/UpdateEvent + (update [_ state] + (-> state + (update-in [:projects team-id project-id :count] dec))))) ;; --- Rename File From 34af5e456322f0d09fd07c4bac14f30d9cb79c6e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 7 Dec 2020 17:14:16 +0100 Subject: [PATCH 178/195] :bug: Fixed right click context menu --- frontend/src/app/main/data/workspace.cljs | 3 ++- frontend/src/app/main/ui/components/dropdown.cljs | 10 +++++----- frontend/src/app/main/ui/modal.cljs | 7 ++++--- .../src/app/main/ui/workspace/shapes/path/editor.cljs | 2 +- .../src/app/main/ui/workspace/shapes/text/editor.cljs | 4 ++-- frontend/src/app/main/ui/workspace/viewport.cljs | 2 -- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 724c987bd4..26b60f9f7e 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1146,7 +1146,8 @@ ptk/WatchEvent (watch [_ state stream] - (rx/of (dws/select-shape (:id shape)))))) + (rx/of (dws/deselect-all) + (dws/select-shape (:id shape)))))) (def hide-context-menu (ptk/reify ::hide-context-menu diff --git a/frontend/src/app/main/ui/components/dropdown.cljs b/frontend/src/app/main/ui/components/dropdown.cljs index 9903c528e7..db9013df32 100644 --- a/frontend/src/app/main/ui/components/dropdown.cljs +++ b/frontend/src/app/main/ui/components/dropdown.cljs @@ -31,11 +31,11 @@ on-mount (fn [] - (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click) - lkey2 (events/listen (dom/get-root) EventType.KEYUP on-keyup)] - #(do - (events/unlistenByKey lkey1) - (events/unlistenByKey lkey2))))] + (let [keys [(events/listen js/document EventType.CLICK on-click) + (events/listen js/document EventType.CONTEXTMENU on-click) + (events/listen js/document EventType.KEYUP on-keyup)]] + #(doseq [key keys] + (events/unlistenByKey key))))] (mf/use-effect on-mount) children)) diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs index 07d3849a6f..544c0d55c1 100644 --- a/frontend/src/app/main/ui/modal.cljs +++ b/frontend/src/app/main/ui/modal.cljs @@ -75,9 +75,10 @@ (mf/use-layout-effect (mf/deps allow-click-outside) (fn [] - (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) - (events/listen js/document EventType.KEYDOWN handle-keydown) - (events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] + (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) + (events/listen js/document EventType.KEYDOWN handle-keydown) + (events/listen js/document EventType.CLICK handle-click-outside) + (events/listen js/document EventType.CONTEXTMENU handle-click-outside)]] #(doseq [key keys] (events/unlistenByKey key))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs index 1cefba76aa..e8367bcd02 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs @@ -186,7 +186,7 @@ (mf/use-layout-effect (fn [] - (let [keys [(events/listen (dom/get-root) EventType.CLICK handle-click-outside)]] + (let [keys [(events/listen js/document EventType.CLICK handle-click-outside)]] #(doseq [key keys] (events/unlistenByKey key))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 499b72b88f..79b27658f3 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -203,8 +203,8 @@ on-mount (fn [] - (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click-outside) - lkey2 (events/listen (dom/get-root) EventType.KEYUP on-key-up)] + (let [lkey1 (events/listen js/document EventType.CLICK on-click-outside) + lkey2 (events/listen js/document EventType.KEYUP on-key-up)] (st/emit! (dwt/assign-editor id editor) (dwc/start-undo-transaction)) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index d90da22a83..fdafadd018 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -248,7 +248,6 @@ (mf/use-callback (fn [event] (dom/prevent-default event) - (dom/stop-propagation event) (let [position (dom/get-client-position event)] (st/emit! (dw/show-context-menu {:position position}))))) @@ -287,7 +286,6 @@ on-click (mf/use-callback (fn [event] - (dom/stop-propagation event) (let [ctrl? (kbd/ctrl? event) shift? (kbd/shift? event) alt? (kbd/alt? event)] From 3a8a212432c254fb82af68689fba3331854c22ae Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 11:35:14 +0100 Subject: [PATCH 179/195] :bug: Fixes problems with masks rotation and some clipping problems --- common/app/common/pages.cljc | 15 ++-- frontend/src/app/main/data/workspace.cljs | 17 +++- frontend/src/app/main/ui/modal.cljs | 5 +- .../src/app/main/ui/shapes/custom_stroke.cljs | 38 +++------ .../src/app/main/ui/shapes/gradients.cljs | 82 +++++++++---------- frontend/src/app/main/ui/shapes/group.cljs | 26 +++--- frontend/src/app/main/ui/shapes/image.cljs | 5 +- frontend/src/app/main/ui/shapes/path.cljs | 5 +- frontend/src/app/main/ui/shapes/text.cljs | 3 - .../app/main/ui/workspace/shapes/group.cljs | 3 +- 10 files changed, 95 insertions(+), 104 deletions(-) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 51720fab6e..696c5e9d23 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -860,11 +860,16 @@ (distinct)) shapes))) (update-group [group objects] - (let [children (->> (if (:masked-group? group) - [(first (:shapes group))] - (:shapes group)) - (map #(get objects %)))] - (gsh/update-group-selrect group children)))] + (let [children (->> group :shapes (map #(get objects %)))] + (if (:masked-group? group) + (let [mask (first children)] + (-> group + (merge (select-keys mask [:selrect :points])) + (assoc :x (-> mask :selrect :x) + :y (-> mask :selrect :y) + :width (-> mask :selrect :width) + :height (-> mask :selrect :height)))) + (gsh/update-group-selrect group children))))] (if page-id (d/update-in-when data [:pages-index page-id :objects] reg-objects) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 26b60f9f7e..481a6eff49 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1146,8 +1146,11 @@ ptk/WatchEvent (watch [_ state stream] - (rx/of (dws/deselect-all) - (dws/select-shape (:id shape)))))) + (let [selected (get-in state [:workspace-local :selected])] + (if (selected (:id shape)) + (rx/empty) + (rx/of (dws/deselect-all) + (dws/select-shape (:id shape)))))))) (def hide-context-menu (ptk/reify ::hide-context-menu @@ -1478,14 +1481,20 @@ :id (:id group) :operations [{:type :set :attr :masked-group? - :val nil}]}] + :val nil}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]}] uchanges [{:type :mod-obj :page-id page-id :id (:id group) :operations [{:type :set :attr :masked-group? - :val (:masked-group? group)}]}]] + :val (:masked-group? group)}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]}]] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (dwc/select-shapes (d/ordered-set (:id group)))))))))) diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs index 544c0d55c1..87d7ad5982 100644 --- a/frontend/src/app/main/ui/modal.cljs +++ b/frontend/src/app/main/ui/modal.cljs @@ -77,7 +77,10 @@ (fn [] (let [keys [(events/listen js/window EventType.POPSTATE on-pop-state) (events/listen js/document EventType.KEYDOWN handle-keydown) - (events/listen js/document EventType.CLICK handle-click-outside) + + ;; Changing to js/document breaks the color picker + (events/listen (dom/get-root) EventType.CLICK handle-click-outside) + (events/listen js/document EventType.CONTEXTMENU handle-click-outside)]] #(doseq [key keys] (events/unlistenByKey key))))) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index d9705dd7bf..bd6c4df4f4 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -9,7 +9,6 @@ [rumext.alpha :as mf] [app.common.uuid :as uuid] [app.common.geom.shapes :as geom] - [app.main.ui.shapes.group :refer [mask-id-ctx]] [app.util.object :as obj])) ; The SVG standard does not implement yet the 'stroke-alignment' @@ -25,16 +24,13 @@ elem-name (unchecked-get props "elem-name") ;; {:keys [x y width height]} (geom/shape->rect-shape shape) {:keys [x y width height]} (:selrect shape) - mask-id (mf/use-ctx mask-id-ctx) stroke-id (mf/use-var (uuid/next)) stroke-style (:stroke-style shape :none) stroke-position (:stroke-alignment shape :center)] (cond ;; Center alignment (or no stroke): the default in SVG (or (= stroke-style :none) (= stroke-position :center)) - [:> elem-name (cond-> (obj/merge! #js {} base-props) - (some? mask-id) - (obj/merge! #js {:mask mask-id}))] + [:> elem-name (obj/merge! #js {} base-props)] ;; Inner alignment: display the shape with double width stroke, ;; and clip the result with the original shape without stroke. @@ -54,15 +50,10 @@ shape-props (-> (obj/merge! #js {} base-props) (obj/merge! #js {:strokeWidth (* stroke-width 2) :clipPath (str "url('#" clip-id "')")}))] - (if (nil? mask-id) - [:* - [:> "clipPath" #js {:id clip-id} - [:> elem-name clip-props]] - [:> elem-name shape-props]] - [:g {:mask mask-id} - [:> "clipPath" #js {:id clip-id} - [:> elem-name clip-props]] - [:> elem-name shape-props]])) + [:* + [:> "clipPath" #js {:id clip-id} + [:> elem-name clip-props]] + [:> elem-name shape-props]]) ;; Outer alingmnent: display the shape in two layers. One ;; without stroke (only fill), and another one only with stroke @@ -100,17 +91,10 @@ :fill "none" :fillOpacity 0 :mask (str "url('#" stroke-mask-id "')")}))] - (if (nil? mask-id) - [:* - [:mask {:id mask-id} - [:> elem-name mask-props1] - [:> elem-name mask-props2]] - [:> elem-name shape-props1] - [:> elem-name shape-props2]] - [:g {:mask mask-id} - [:mask {:id stroke-mask-id} - [:> elem-name mask-props1] - [:> elem-name mask-props2]] - [:> elem-name shape-props1] - [:> elem-name shape-props2]]))))) + [:* + [:mask {:id stroke-mask-id} + [:> elem-name mask-props1] + [:> elem-name mask-props2]] + [:> elem-name shape-props1] + [:> elem-name shape-props2]])))) diff --git a/frontend/src/app/main/ui/shapes/gradients.cljs b/frontend/src/app/main/ui/shapes/gradients.cljs index 120e623dd7..7d60bb88d5 100644 --- a/frontend/src/app/main/ui/shapes/gradients.cljs +++ b/frontend/src/app/main/ui/shapes/gradients.cljs @@ -18,56 +18,54 @@ (mf/defc linear-gradient [{:keys [id gradient shape]}] (let [{:keys [x y width height]} shape] - [:defs - [:linearGradient {:id id - :x1 (:start-x gradient) - :y1 (:start-y gradient) - :x2 (:end-x gradient) - :y2 (:end-y gradient)} - (for [{:keys [offset color opacity]} (:stops gradient)] - [:stop {:key (str id "-stop-" offset) - :offset (or offset 0) - :stop-color color - :stop-opacity opacity}])]])) + [:linearGradient {:id id + :x1 (:start-x gradient) + :y1 (:start-y gradient) + :x2 (:end-x gradient) + :y2 (:end-y gradient)} + (for [{:keys [offset color opacity]} (:stops gradient)] + [:stop {:key (str id "-stop-" offset) + :offset (or offset 0) + :stop-color color + :stop-opacity opacity}])])) (mf/defc radial-gradient [{:keys [id gradient shape]}] (let [{:keys [x y width height]} shape] - [:defs - (let [[x y] (if (= (:type shape) :frame) [0 0] [x y]) - translate-vec (gpt/point (+ x (* width (:start-x gradient))) - (+ y (* height (:start-y gradient)))) - - gradient-vec (gpt/to-vec (gpt/point (* width (:start-x gradient)) - (* height (:start-y gradient))) - (gpt/point (* width (:end-x gradient)) - (* height (:end-y gradient)))) + (let [[x y] (if (= (:type shape) :frame) [0 0] [x y]) + translate-vec (gpt/point (+ x (* width (:start-x gradient))) + (+ y (* height (:start-y gradient)))) - angle (gpt/angle gradient-vec - (gpt/point 1 0)) + gradient-vec (gpt/to-vec (gpt/point (* width (:start-x gradient)) + (* height (:start-y gradient))) + (gpt/point (* width (:end-x gradient)) + (* height (:end-y gradient)))) - shape-height-vec (gpt/point 0 (/ height 2)) + angle (gpt/angle gradient-vec + (gpt/point 1 0)) - scale-factor-y (/ (gpt/length gradient-vec) (/ height 2)) - scale-factor-x (* scale-factor-y (:width gradient)) + shape-height-vec (gpt/point 0 (/ height 2)) - scale-vec (gpt/point (* scale-factor-y (/ height 2)) - (* scale-factor-x (/ width 2))) + scale-factor-y (/ (gpt/length gradient-vec) (/ height 2)) + scale-factor-x (* scale-factor-y (:width gradient)) - tr-translate (str/fmt "translate(%s, %s)" (:x translate-vec) (:y translate-vec)) - tr-rotate (str/fmt "rotate(%s)" angle) - tr-scale (str/fmt "scale(%s, %s)" (:x scale-vec) (:y scale-vec)) - transform (str/fmt "%s %s %s" tr-translate tr-rotate tr-scale)] - [:radialGradient {:id id - :cx 0 - :cy 0 - :r 1 - :gradientUnits "userSpaceOnUse" - :gradientTransform transform} - (for [{:keys [offset color opacity]} (:stops gradient)] - [:stop {:key (str id "-stop-" offset) - :offset (or offset 0) - :stop-color color - :stop-opacity opacity}])])])) + scale-vec (gpt/point (* scale-factor-y (/ height 2)) + (* scale-factor-x (/ width 2))) + + tr-translate (str/fmt "translate(%s, %s)" (:x translate-vec) (:y translate-vec)) + tr-rotate (str/fmt "rotate(%s)" angle) + tr-scale (str/fmt "scale(%s, %s)" (:x scale-vec) (:y scale-vec)) + transform (str/fmt "%s %s %s" tr-translate tr-rotate tr-scale)] + [:radialGradient {:id id + :cx 0 + :cy 0 + :r 1 + :gradientUnits "userSpaceOnUse" + :gradientTransform transform} + (for [{:keys [offset color opacity]} (:stops gradient)] + [:stop {:key (str id "-stop-" offset) + :offset (or offset 0) + :stop-color color + :stop-opacity opacity}])]))) (mf/defc gradient {::mf/wrap-props false} diff --git a/frontend/src/app/main/ui/shapes/group.cljs b/frontend/src/app/main/ui/shapes/group.cljs index 98c36bd0a3..f9b039b6ca 100644 --- a/frontend/src/app/main/ui/shapes/group.cljs +++ b/frontend/src/app/main/ui/shapes/group.cljs @@ -14,17 +14,16 @@ [app.main.ui.shapes.attrs :as attrs] [app.common.geom.shapes :as geom])) -(def mask-id-ctx (mf/create-context nil)) - (defn group-shape [shape-wrapper] (mf/fnc group-shape {::mf/wrap-props false} [props] - (let [frame (unchecked-get props "frame") - shape (unchecked-get props "shape") - childs (unchecked-get props "childs") - expand-mask (unchecked-get props "expand-mask") + (let [frame (unchecked-get props "frame") + shape (unchecked-get props "shape") + childs (unchecked-get props "childs") + expand-mask (unchecked-get props "expand-mask") + pointer-events (unchecked-get props "pointer-events") mask (if (and (:masked-group? shape) (not expand-mask)) (first childs) nil) @@ -33,7 +32,9 @@ childs) {:keys [id x y width height]} shape transform (geom/transform-matrix shape)] - [:g + [:g.group {:pointer-events pointer-events + :mask (when (and mask (not expand-mask)) + (str/fmt "url(#%s)" (:id mask)))} (when mask [:defs [:mask {:id (:id mask) @@ -41,11 +42,10 @@ :height height} [:& shape-wrapper {:frame frame :shape mask}]]]) - [:& (mf/provider mask-id-ctx) {:value (str/fmt "url(#%s)" (:id mask))} - (for [item childs] - [:& shape-wrapper {:frame frame - :shape item - :key (:id item)}])] - ]))) + (for [item childs] + [:& shape-wrapper {:frame frame + :shape item + :key (:id item)}])]))) + diff --git a/frontend/src/app/main/ui/shapes/image.cljs b/frontend/src/app/main/ui/shapes/image.cljs index 61ef85c791..c7640bbc37 100644 --- a/frontend/src/app/main/ui/shapes/image.cljs +++ b/frontend/src/app/main/ui/shapes/image.cljs @@ -13,7 +13,6 @@ [app.config :as cfg] [app.common.geom.shapes :as geom] [app.main.ui.shapes.attrs :as attrs] - [app.main.ui.shapes.group :refer [mask-id-ctx]] [app.util.object :as obj] [app.main.ui.context :as muc] [app.main.data.fetch :as df] @@ -27,7 +26,6 @@ {:keys [id x y width height rotation metadata]} shape uri (cfg/resolve-media-path (:path metadata)) embed-resources? (mf/use-ctx muc/embed-ctx) - mask-id (mf/use-ctx mask-id-ctx) data-uri (mf/use-state (when (not embed-resources?) uri))] (mf/use-effect @@ -45,8 +43,7 @@ :transform transform :width width :height height - :preserveAspectRatio "none" - :mask mask-id}))] + :preserveAspectRatio "none"}))] (if (nil? @data-uri) [:> "rect" (obj/merge! props diff --git a/frontend/src/app/main/ui/shapes/path.cljs b/frontend/src/app/main/ui/shapes/path.cljs index 85a0e0cd28..90f485a0a1 100644 --- a/frontend/src/app/main/ui/shapes/path.cljs +++ b/frontend/src/app/main/ui/shapes/path.cljs @@ -13,7 +13,6 @@ [rumext.alpha :as mf] [app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]] - [app.main.ui.shapes.group :refer [mask-id-ctx]] [app.common.geom.shapes :as geom] [app.util.object :as obj] [app.util.geom.path :as ugp])) @@ -27,7 +26,6 @@ background? (unchecked-get props "background?") ;; {:keys [id x y width height]} (geom/shape->rect-shape shape) {:keys [id x y width height]} (:selrect shape) - mask-id (mf/use-ctx mask-id-ctx) transform (geom/transform-matrix shape) pdata (ugp/content->path (:content shape)) props (-> (attrs/extract-style-attrs shape) @@ -35,7 +33,7 @@ #js {:transform transform :d pdata}))] (if background? - [:g {:mask mask-id} + [:g [:path {:stroke "transparent" :fill "transparent" :stroke-width "20px" @@ -45,6 +43,5 @@ :elem-name "path"}]] [:& shape-custom-stroke {:shape shape :base-props props - :mask mask-id :elem-name "path"}]))) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index c420f94216..05c0afda49 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -12,7 +12,6 @@ [cuerdas.core :as str] [rumext.alpha :as mf] [app.main.ui.context :as muc] - [app.main.ui.shapes.group :refer [mask-id-ctx]] [app.common.data :as d] [app.common.geom.shapes :as geom] [app.common.geom.matrix :as gmt] @@ -90,7 +89,6 @@ (let [shape (unchecked-get props "shape") selected? (unchecked-get props "selected?") grow-type (:grow-type shape) - mask-id (mf/use-ctx mask-id-ctx) {:keys [id x y width height content]} shape] [:foreignObject {:x x :y y @@ -99,7 +97,6 @@ :transform (geom/transform-matrix shape) :width (if (#{:auto-width} grow-type) 10000 width) :height (if (#{:auto-height :auto-width} grow-type) 10000 height) - :mask mask-id :ref ref :pointer-events "none"} [:& text-content {:shape shape diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index e9d502032b..619a9e1581 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -80,7 +80,8 @@ {:frame frame :shape shape :childs childs - :expand-mask is-mask-selected?}] + :expand-mask is-mask-selected? + :pointer-events (when (not is-child-selected?) "none")}] (when-not is-child-selected? [:rect.group-actions From c7e33929dbbc04cfb84e932837acc6e5ecaae525 Mon Sep 17 00:00:00 2001 From: elhombretecla Date: Mon, 7 Dec 2020 09:05:20 +0100 Subject: [PATCH 180/195] :tada: Add move icon --- frontend/resources/locales.json | 23 +++++++++++++------ .../app/main/ui/workspace/left_toolbar.cljs | 5 ++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index 99362eba22..9176932b85 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -3644,7 +3644,7 @@ } }, "workspace.toolbar.ellipse" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:69" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:74" ], "translations" : { "en" : "Ellipse (E)", "fr" : "", @@ -3662,7 +3662,7 @@ } }, "workspace.toolbar.comments" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:99" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:104" ], "translations" : { "en" : "Comments", "es" : "Comentarios" @@ -3677,8 +3677,17 @@ "es" : "Curva" } }, - "workspace.toolbar.frame" : { + "workspace.toolbar.move" : { "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:59" ], + "translations" : { + "en" : "Move", + "fr" : "Déplacer", + "ru" : "Вытеснить", + "es" : "Mover" + } + }, + "workspace.toolbar.frame" : { + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:64" ], "translations" : { "en" : "Artboard (A)", "fr" : "Plan de travail (A)", @@ -3687,7 +3696,7 @@ } }, "workspace.toolbar.image" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:79" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:93" ], "translations" : { "en" : "Image (K)", "fr" : "Image (K)", @@ -3705,7 +3714,7 @@ "unused" : true }, "workspace.toolbar.path" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:93" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:98" ], "translations" : { "en" : "Path", "fr" : "Chemin", @@ -3714,7 +3723,7 @@ } }, "workspace.toolbar.rect" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:64" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:69" ], "translations" : { "en" : "Rectangle (R)", "fr" : "", @@ -3723,7 +3732,7 @@ } }, "workspace.toolbar.text" : { - "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:74" ], + "used-in" : [ "src/app/main/ui/workspace/left_toolbar.cljs:79" ], "translations" : { "en" : "Text (T)", "fr" : "Texte (T)", diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index fc96f2f7c2..192882c719 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -55,6 +55,11 @@ [:aside.left-toolbar [:div.left-toolbar-inside [:ul.left-toolbar-options + [:li.tooltip.tooltip-right + {:alt (t locale "workspace.toolbar.move") + :class (when (nil? selected-drawtool) "selected") + :on-click #(st/emit! :interrupt)} + i/pointer-inner] [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.frame") :class (when (= selected-drawtool :frame) "selected") From 07e0c02d11c24e631b563af3fe6cf2a83e6c9284 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 11:46:46 +0100 Subject: [PATCH 181/195] :bug: Fixed arrow style when mask with only one element --- frontend/resources/styles/main/partials/sidebar-layers.scss | 2 +- frontend/resources/styles/main/partials/sidebar.scss | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar-layers.scss b/frontend/resources/styles/main/partials/sidebar-layers.scss index 25e42fe072..a0df8eaf2f 100644 --- a/frontend/resources/styles/main/partials/sidebar-layers.scss +++ b/frontend/resources/styles/main/partials/sidebar-layers.scss @@ -166,7 +166,7 @@ border-left: none; position: relative; - &::before { + &::after { content: " "; border-left: 1px solid $color-gray-40; border-bottom: 1px solid $color-gray-40; diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index 3c11fe1059..676219e9af 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -194,9 +194,8 @@ $width-settings-bar: 16rem; display: flex; flex-direction: column; width: 100%; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - + padding-top: 1px; + padding-bottom: 1px; &.open { From 07d77c13205b7116e09409dd41a63080bfe53d10 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 12:16:17 +0100 Subject: [PATCH 182/195] :bug: Fixed dashboard edition on new project --- frontend/src/app/main/data/dashboard.cljs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 10eba755d0..395d03563a 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -394,7 +394,9 @@ (ptk/reify ::rename-project ptk/UpdateEvent (update [_ state] - (assoc-in state [:projects team-id id :name] name)) + (-> state + (assoc-in [:projects team-id id :name] name) + (update :dashboard-local dissoc :project-for-edit))) ptk/WatchEvent (watch [_ state stream] From 4b22615f9729f950d14839bb09b4c9b25643ca96 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 15:33:53 +0100 Subject: [PATCH 183/195] :bug: Fixed issues with masks when coloring --- .../styles/main/partials/sidebar-layers.scss | 54 +++-- frontend/src/app/main/data/workspace.cljs | 148 ++----------- .../src/app/main/data/workspace/groups.cljs | 199 ++++++++++++++++++ .../app/main/data/workspace/libraries.cljs | 6 +- .../app/main/data/workspace/selection.cljs | 85 -------- frontend/src/app/main/ui/shapes/group.cljs | 59 +++--- frontend/src/app/main/ui/shapes/mask.cljs | 35 +++ 7 files changed, 304 insertions(+), 282 deletions(-) create mode 100644 frontend/src/app/main/data/workspace/groups.cljs create mode 100644 frontend/src/app/main/ui/shapes/mask.cljs diff --git a/frontend/resources/styles/main/partials/sidebar-layers.scss b/frontend/resources/styles/main/partials/sidebar-layers.scss index a0df8eaf2f..d31e5c7b76 100644 --- a/frontend/resources/styles/main/partials/sidebar-layers.scss +++ b/frontend/resources/styles/main/partials/sidebar-layers.scss @@ -144,38 +144,36 @@ } } -.element-list li.masked { - .element-children { - li:first-child { - position: relative; +.element-list li.masked > .element-children > li { + &:first-child { + position: relative; - &::before { - content: " "; - border-right: 1px solid $color-gray-40; - border-top: 1px solid $color-gray-40; - position: absolute; - width: 6px; - height: 6px; - transform: rotate(-45deg); - top: -1px; - left: -4px; - } + &::before { + content: " "; + border-right: 1px solid $color-gray-40; + border-top: 1px solid $color-gray-40; + position: absolute; + width: 6px; + height: 6px; + transform: rotate(-45deg); + top: -1px; + left: -4px; } + } - li:last-child { - border-left: none; - position: relative; + &:last-child { + border-left: none; + position: relative; - &::after { - content: " "; - border-left: 1px solid $color-gray-40; - border-bottom: 1px solid $color-gray-40; - height: 1rem; - width: 0.3rem; - position: absolute; - top: 0; - left: 0; - } + &::after { + content: " "; + border-left: 1px solid $color-gray-40; + border-bottom: 1px solid $color-gray-40; + height: 1rem; + width: 0.3rem; + position: absolute; + top: 0; + left: 0; } } } diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 481a6eff49..126ed925bf 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -32,6 +32,7 @@ [app.main.data.workspace.selection :as dws] [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] + [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.drawing :as dwd] [app.main.data.workspace.drawing.path :as dwdp] [app.main.repo :as rp] @@ -1011,11 +1012,12 @@ (ptk/reify ::set-shape-proportion-lock ptk/WatchEvent (watch [_ state stream] - (rx/of (dwc/update-shapes [id] (fn [shape] - (if-not lock - (assoc shape :proportion-lock false) - (-> (assoc shape :proportion-lock true) - (gpr/assign-proportions))))))))) + (letfn [(assign-proportions [shape] + (if-not lock + (assoc shape :proportion-lock false) + (-> (assoc shape :proportion-lock true) + (gpr/assign-proportions))))] + (rx/of (dwc/update-shapes [id] assign-proportions)))))) ;; --- Update Shape Position @@ -1371,135 +1373,6 @@ (with-meta params {:on-success image-uploaded}))))))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; GROUPS -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def group-selected - (ptk/reify ::group-selected - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - selected (get-in state [:workspace-local :selected]) - shapes (dws/shapes-for-grouping objects selected)] - (when-not (empty? shapes) - (let [[group rchanges uchanges] (dws/prepare-create-group page-id shapes "Group-" false)] - (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dwc/select-shapes (d/ordered-set (:id group)))))))))) - -(def ungroup-selected - (ptk/reify ::ungroup-selected - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - selected (get-in state [:workspace-local :selected]) - group-id (first selected) - group (get objects group-id)] - (when (and (= 1 (count selected)) - (= (:type group) :group)) - (let [[rchanges uchanges] - (dws/prepare-remove-group page-id group objects)] - (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))))) - -(def mask-group - (ptk/reify ::mask-group - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - selected (get-in state [:workspace-local :selected]) - shapes (dws/shapes-for-grouping objects selected)] - (when-not (empty? shapes) - (let [;; If the selected shape is a group, we can use it. If not, - ;; create a new group and set it as masked. - [group rchanges uchanges] - (if (and (= (count shapes) 1) - (= (:type (first shapes)) :group)) - [(first shapes) [] []] - (dws/prepare-create-group page-id shapes "Group-" true)) - - rchanges (d/concat rchanges - [{:type :mod-obj - :page-id page-id - :id (:id group) - :operations [{:type :set - :attr :masked-group? - :val true}]} - {:type :reg-objects - :page-id page-id - :shapes [(:id group)]}]) - - uchanges (conj uchanges - {:type :mod-obj - :page-id page-id - :id (:id group) - :operations [{:type :set - :attr :masked-group? - :val nil}]}) - - ;; If the mask has the default color, change it automatically - ;; to white, to have an opaque mask by default (user may change - ;; it later to have different degrees of transparency). - mask (first shapes) - rchanges (if (not= (:fill-color mask) cp/default-color) - rchanges - (conj rchanges - {:type :mod-obj - :page-id page-id - :id (:id mask) - :operations [{:type :set - :attr :fill-color - :val "#ffffff"}]})) - - uchanges (if (not= (:fill-color mask) cp/default-color) - uchanges - (conj uchanges - {:type :mod-obj - :page-id page-id - :id (:id mask) - :operations [{:type :set - :attr :fill-color - :val (:fill-color mask)}]}))] - - (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dwc/select-shapes (d/ordered-set (:id group)))))))))) - -(def unmask-group - (ptk/reify ::unmask-group - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - selected (get-in state [:workspace-local :selected])] - (when (= (count selected) 1) - (let [group (get objects (first selected)) - - rchanges [{:type :mod-obj - :page-id page-id - :id (:id group) - :operations [{:type :set - :attr :masked-group? - :val nil}]} - {:type :reg-objects - :page-id page-id - :shapes [(:id group)]}] - - uchanges [{:type :mod-obj - :page-id page-id - :id (:id group) - :operations [{:type :set - :attr :masked-group? - :val (:masked-group? group)}]} - {:type :reg-objects - :page-id page-id - :shapes [(:id group)]}]] - - (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) - (dwc/select-shapes (d/ordered-set (:id group)))))))))) - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interactions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1631,6 +1504,13 @@ (d/export dwc/start-edition-mode) (d/export dwdp/start-path-edit) +;; Groups + +(d/export dwg/mask-group) +(d/export dwg/unmask-group) +(d/export dwg/group-selected) +(d/export dwg/ungroup-selected) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs new file mode 100644 index 0000000000..41cf994a6d --- /dev/null +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -0,0 +1,199 @@ +(ns app.main.data.workspace.groups + (:require + [app.common.data :as d] + [app.common.geom.shapes :as gsh] + [app.common.pages :as cp] + [app.common.pages-helpers :as cph] + [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.selection :as dws] + [beicon.core :as rx] + [potok.core :as ptk])) + +(defn shapes-for-grouping + [objects selected] + (->> selected + (map #(get objects %)) + (filter #(not= :frame (:type %))) + (map #(assoc % ::index (cph/position-on-parent (:id %) objects))) + (sort-by ::index))) + +(defn- make-group + [shapes prefix keep-name] + (let [selrect (gsh/selection-rect shapes) + frame-id (-> shapes first :frame-id) + parent-id (-> shapes first :parent-id) + group-name (if (and keep-name + (= (count shapes) 1) + (= (:type (first shapes)) :group)) + (:name (first shapes)) + (name (gensym prefix)))] + (-> (cp/make-minimal-group frame-id selrect group-name) + (gsh/setup selrect) + (assoc :shapes (mapv :id shapes))))) + +(defn prepare-create-group + [page-id shapes prefix keep-name] + (let [group (make-group shapes prefix keep-name) + rchanges [{:type :add-obj + :id (:id group) + :page-id page-id + :frame-id (:frame-id (first shapes)) + :parent-id (:parent-id (first shapes)) + :obj group + :index (::index (first shapes))} + {:type :mov-objects + :page-id page-id + :parent-id (:id group) + :shapes (mapv :id shapes)}] + + uchanges (conj + (mapv (fn [obj] {:type :mov-objects + :page-id page-id + :parent-id (:parent-id obj) + :index (::index obj) + :shapes [(:id obj)]}) + shapes) + {:type :del-obj + :id (:id group) + :page-id page-id})] + [group rchanges uchanges])) + +(defn prepare-remove-group + [page-id group objects] + (let [shapes (:shapes group) + parent-id (cph/get-parent (:id group) objects) + parent (get objects parent-id) + index-in-parent (->> (:shapes parent) + (map-indexed vector) + (filter #(#{(:id group)} (second %))) + (ffirst)) + rchanges [{:type :mov-objects + :page-id page-id + :parent-id parent-id + :shapes shapes + :index index-in-parent} + {:type :del-obj + :page-id page-id + :id (:id group)}] + uchanges [{:type :add-obj + :page-id page-id + :id (:id group) + :frame-id (:frame-id group) + :obj (assoc group :shapes [])} + {:type :mov-objects + :page-id page-id + :parent-id (:id group) + :shapes shapes} + {:type :mov-objects + :page-id page-id + :parent-id parent-id + :shapes [(:id group)] + :index index-in-parent}]] + [rchanges uchanges])) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; GROUPS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(def group-selected + (ptk/reify ::group-selected + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + selected (get-in state [:workspace-local :selected]) + shapes (shapes-for-grouping objects selected)] + (when-not (empty? shapes) + (let [[group rchanges uchanges] (prepare-create-group page-id shapes "Group-" false)] + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) + +(def ungroup-selected + (ptk/reify ::ungroup-selected + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + selected (get-in state [:workspace-local :selected]) + group-id (first selected) + group (get objects group-id)] + (when (and (= 1 (count selected)) + (= (:type group) :group)) + (let [[rchanges uchanges] + (prepare-remove-group page-id group objects)] + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))))) + +(def mask-group + (ptk/reify ::mask-group + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + selected (get-in state [:workspace-local :selected]) + shapes (shapes-for-grouping objects selected)] + (when-not (empty? shapes) + (let [;; If the selected shape is a group, we can use it. If not, + ;; create a new group and set it as masked. + [group rchanges uchanges] + (if (and (= (count shapes) 1) + (= (:type (first shapes)) :group)) + [(first shapes) [] []] + (prepare-create-group page-id shapes "Group-" true)) + + rchanges (d/concat rchanges + [{:type :mod-obj + :page-id page-id + :id (:id group) + :operations [{:type :set + :attr :masked-group? + :val true}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]}]) + + uchanges (conj uchanges + {:type :mod-obj + :page-id page-id + :id (:id group) + :operations [{:type :set + :attr :masked-group? + :val nil}]})] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) + +(def unmask-group + (ptk/reify ::unmask-group + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + selected (get-in state [:workspace-local :selected])] + (when (= (count selected) 1) + (let [group (get objects (first selected)) + + rchanges [{:type :mod-obj + :page-id page-id + :id (:id group) + :operations [{:type :set + :attr :masked-group? + :val nil}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]}] + + uchanges [{:type :mod-obj + :page-id page-id + :id (:id group) + :operations [{:type :set + :attr :masked-group? + :val (:masked-group? group)}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]}]] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) + (dwc/select-shapes (d/ordered-set (:id group)))))))))) + + diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 3eb8f60db7..381b8f5e31 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -17,7 +17,7 @@ [app.common.geom.shapes :as geom] [app.main.data.messages :as dm] [app.main.data.workspace.common :as dwc] - [app.main.data.workspace.selection :as dws] + [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.libraries-helpers :as dwlh] [app.common.pages :as cp] [app.main.repo :as rp] @@ -182,7 +182,7 @@ (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) selected (get-in state [:workspace-local :selected]) - shapes (dws/shapes-for-grouping objects selected)] + shapes (dwg/shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [;; If the selected shape is a group, we can use it. If not, ;; we need to create a group before creating the component. @@ -190,7 +190,7 @@ (if (and (= (count shapes) 1) (= (:type (first shapes)) :group)) [(first shapes) [] []] - (dws/prepare-create-group page-id shapes "Component-" true)) + (dwg/prepare-create-group page-id shapes "Component-" true)) [new-shape new-shapes updated-shapes] (dwlh/make-component-shape group objects) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index d01e9c8b4c..fe9ea3d6f0 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -197,91 +197,6 @@ (rx/of (deselect-all) (select-shape (:id selected)))))))) -;; --- Group shapes - -(defn shapes-for-grouping - [objects selected] - (->> selected - (map #(get objects %)) - (filter #(not= :frame (:type %))) - (map #(assoc % ::index (cph/position-on-parent (:id %) objects))) - (sort-by ::index))) - -(defn- make-group - [shapes prefix keep-name] - (let [selrect (geom/selection-rect shapes) - frame-id (-> shapes first :frame-id) - parent-id (-> shapes first :parent-id) - group-name (if (and keep-name - (= (count shapes) 1) - (= (:type (first shapes)) :group)) - (:name (first shapes)) - (name (gensym prefix)))] - (-> (cp/make-minimal-group frame-id selrect group-name) - (geom/setup selrect) - (assoc :shapes (mapv :id shapes))))) - -(defn prepare-create-group - [page-id shapes prefix keep-name] - (let [group (make-group shapes prefix keep-name) - rchanges [{:type :add-obj - :id (:id group) - :page-id page-id - :frame-id (:frame-id (first shapes)) - :parent-id (:parent-id (first shapes)) - :obj group - :index (::index (first shapes))} - {:type :mov-objects - :page-id page-id - :parent-id (:id group) - :shapes (mapv :id shapes)}] - - uchanges (conj - (mapv (fn [obj] {:type :mov-objects - :page-id page-id - :parent-id (:parent-id obj) - :index (::index obj) - :shapes [(:id obj)]}) - shapes) - {:type :del-obj - :id (:id group) - :page-id page-id})] - [group rchanges uchanges])) - -(defn prepare-remove-group - [page-id group objects] - (let [shapes (:shapes group) - parent-id (cph/get-parent (:id group) objects) - parent (get objects parent-id) - index-in-parent (->> (:shapes parent) - (map-indexed vector) - (filter #(#{(:id group)} (second %))) - (ffirst)) - rchanges [{:type :mov-objects - :page-id page-id - :parent-id parent-id - :shapes shapes - :index index-in-parent} - {:type :del-obj - :page-id page-id - :id (:id group)}] - uchanges [{:type :add-obj - :page-id page-id - :id (:id group) - :frame-id (:frame-id group) - :obj (assoc group :shapes [])} - {:type :mov-objects - :page-id page-id - :parent-id (:id group) - :shapes shapes} - {:type :mov-objects - :page-id page-id - :parent-id parent-id - :shapes [(:id group)] - :index index-in-parent}]] - [rchanges uchanges])) - - ;; --- Duplicate Shapes (declare prepare-duplicate-change) (declare prepare-duplicate-frame-change) diff --git a/frontend/src/app/main/ui/shapes/group.cljs b/frontend/src/app/main/ui/shapes/group.cljs index f9b039b6ca..5e00ea9e38 100644 --- a/frontend/src/app/main/ui/shapes/group.cljs +++ b/frontend/src/app/main/ui/shapes/group.cljs @@ -10,42 +10,37 @@ (ns app.main.ui.shapes.group (:require [rumext.alpha :as mf] - [cuerdas.core :as str] - [app.main.ui.shapes.attrs :as attrs] - [app.common.geom.shapes :as geom])) + [app.main.ui.shapes.mask :refer [mask-str mask-factory]])) (defn group-shape [shape-wrapper] - (mf/fnc group-shape - {::mf/wrap-props false} - [props] - (let [frame (unchecked-get props "frame") - shape (unchecked-get props "shape") - childs (unchecked-get props "childs") - expand-mask (unchecked-get props "expand-mask") - pointer-events (unchecked-get props "pointer-events") - mask (if (and (:masked-group? shape) (not expand-mask)) - (first childs) - nil) - childs (if (and (:masked-group? shape) (not expand-mask)) - (rest childs) - childs) - {:keys [id x y width height]} shape - transform (geom/transform-matrix shape)] - [:g.group {:pointer-events pointer-events - :mask (when (and mask (not expand-mask)) - (str/fmt "url(#%s)" (:id mask)))} - (when mask - [:defs - [:mask {:id (:id mask) - :width width - :height height} + (let [render-mask (mask-factory shape-wrapper)] + (mf/fnc group-shape + {::mf/wrap-props false} + [props] + (let [frame (unchecked-get props "frame") + shape (unchecked-get props "shape") + childs (unchecked-get props "childs") + expand-mask (unchecked-get props "expand-mask") + pointer-events (unchecked-get props "pointer-events") + + {:keys [id x y width height]} shape + + show-mask? (and (:masked-group? shape) (not expand-mask)) + mask (when show-mask? (first childs)) + childs (if show-mask? (rest childs) childs)] + + [:g.group + {:pointer-events pointer-events + :mask (when (and mask (not expand-mask)) (mask-str mask))} + + (when mask + [:> render-mask #js {:frame frame :mask mask}]) + + (for [item childs] [:& shape-wrapper {:frame frame - :shape mask}]]]) - (for [item childs] - [:& shape-wrapper {:frame frame - :shape item - :key (:id item)}])]))) + :shape item + :key (:id item)}])])))) diff --git a/frontend/src/app/main/ui/shapes/mask.cljs b/frontend/src/app/main/ui/shapes/mask.cljs new file mode 100644 index 0000000000..be96847938 --- /dev/null +++ b/frontend/src/app/main/ui/shapes/mask.cljs @@ -0,0 +1,35 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.shapes.mask + (:require + [rumext.alpha :as mf] + [cuerdas.core :as str])) + +(defn mask-str [mask] + (str/fmt "url(#%s)" (str (:id mask) "-mask"))) + +(defn mask-factory + [shape-wrapper] + (mf/fnc mask-shape + {::mf/wrap-props false} + [props] + (let [frame (unchecked-get props "frame") + mask (unchecked-get props "mask")] + [:defs + [:filter {:id (str (:id mask) "-filter")} + [:feFlood {:flood-color "white"}] + [:feComposite {:in "BackgroundImage" + :in2 "SourceGraphic" + :operator "in" + :result "comp"}]] + [:mask {:id (str (:id mask) "-mask")} + [:g {:filter (str/fmt "url(#%s)" (str (:id mask) "-filter"))} + [:& shape-wrapper {:frame frame :shape mask}]]]]))) + From 20a7366432fa497da4aaa337d425f7e1d0c6b776 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 16:05:11 +0100 Subject: [PATCH 184/195] :bug: Fixes problems with hover on elements --- frontend/src/app/main/data/workspace/groups.cljs | 14 +++++++++++++- .../src/app/main/data/workspace/selection.cljs | 13 +++++-------- .../src/app/main/ui/workspace/shapes/common.cljs | 4 ++-- .../src/app/main/ui/workspace/shapes/frame.cljs | 4 ++-- .../src/app/main/ui/workspace/shapes/group.cljs | 4 ++-- .../src/app/main/ui/workspace/shapes/path.cljs | 4 ++-- .../src/app/main/ui/workspace/shapes/text.cljs | 4 ++-- 7 files changed, 28 insertions(+), 19 deletions(-) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index 41cf994a6d..e5e6b78e1f 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -147,7 +147,19 @@ :id (:id group) :operations [{:type :set :attr :masked-group? - :val true}]} + :val true} + {:type :set + :attr :selrect + :val (-> shapes first :selrect)} + {:type :set + :attr :points + :val (-> shapes first :points)} + {:type :set + :attr :transform + :val (-> shapes first :transform)} + {:type :set + :attr :transform-inverse + :val (-> shapes first :transform-inverse)}]} {:type :reg-objects :page-id page-id :shapes [(:id group)]}]) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index fe9ea3d6f0..28a5aa5ff1 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -314,11 +314,8 @@ (defn change-hover-state [id value] - (letfn [(update-hover [items] - (if value - (conj items id) - (disj items id)))] - (ptk/reify ::change-hover-state - ptk/UpdateEvent - (update [_ state] - (update-in state [:workspace-local :hover] (fnil update-hover #{})))))) + (ptk/reify ::change-hover-state + ptk/UpdateEvent + (update [_ state] + (let [hover-value (if value #{id} #{})] + (assoc-in state [:workspace-local :hover] hover-value))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/common.cljs b/frontend/src/app/main/ui/workspace/shapes/common.cljs index 168bd0dd64..af49860356 100644 --- a/frontend/src/app/main/ui/workspace/shapes/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/common.cljs @@ -22,6 +22,6 @@ [:> shape-container {:shape shape :on-mouse-down (we/use-mouse-down shape) :on-context-menu (we/use-context-menu shape) - :on-pointer-enter (we/use-pointer-enter shape) - :on-pointer-leave (we/use-pointer-leave shape)} + :on-pointer-over (we/use-pointer-enter shape) + :on-pointer-out (we/use-pointer-leave shape)} [:& component {:shape shape}]]))) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index d092b48d98..1b6bef2cf9 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -73,8 +73,8 @@ :class "workspace-frame-label" :transform (text-transform label-pos zoom) :on-click handle-click - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave} + :on-pointer-over handle-pointer-enter + :on-pointer-out handle-pointer-leave} (:name frame)])) (defn make-is-moving-ref diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index 619a9e1581..7c6f464cde 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -94,7 +94,7 @@ :height height :on-mouse-down handle-mouse-down :on-context-menu handle-context-menu - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave + :on-pointer-over handle-pointer-enter + :on-pointer-out handle-pointer-leave :on-double-click handle-double-click}])]])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index 4205101787..fd9fbe1734 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -49,8 +49,8 @@ :pointer-events (when editing? "none") :on-mouse-down handle-mouse-down :on-context-menu handle-context-menu - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave + :on-pointer-over handle-pointer-enter + :on-pointer-out handle-pointer-leave :on-double-click handle-double-click} [:& path/path-shape {:shape shape :background? true}]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 8d612bb421..d122c694d9 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -124,8 +124,8 @@ :style {:fill "transparent"} :on-mouse-down handle-mouse-down :on-context-menu handle-context-menu - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave + :on-pointer-over handle-pointer-enter + :on-pointer-out handle-pointer-leave :on-double-click handle-double-click :transform (gsh/transform-matrix shape)}])])) From a881d86637b952fc6eebfbe4cfe665480e70c360 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 8 Dec 2020 16:47:26 +0100 Subject: [PATCH 185/195] :sparkles: Rename graphic assets --- backend/src/app/services/mutations/media.clj | 6 +-- common/app/common/pages.cljc | 13 +++++- .../app/main/data/workspace/libraries.cljs | 18 ++++++++ .../app/main/data/workspace/persistence.cljs | 5 ++- .../app/main/ui/workspace/sidebar/assets.cljs | 41 +++++++++++++++++-- .../src/app/main/ui/workspace/viewport.cljs | 4 +- 6 files changed, 76 insertions(+), 11 deletions(-) diff --git a/backend/src/app/services/mutations/media.clj b/backend/src/app/services/mutations/media.clj index e50e7a500d..f1812b7fec 100644 --- a/backend/src/app/services/mutations/media.clj +++ b/backend/src/app/services/mutations/media.clj @@ -47,20 +47,20 @@ (s/def ::add-media-object-from-url (s/keys :req-un [::profile-id ::file-id ::is-local ::url] - :opt-un [::id])) + :opt-un [::id ::name])) (s/def ::upload-media-object (s/keys :req-un [::profile-id ::file-id ::is-local ::name ::content] :opt-un [::id])) (sm/defmutation ::add-media-object-from-url - [{:keys [profile-id file-id url] :as params}] + [{:keys [profile-id file-id url name] :as params}] (db/with-atomic [conn db/pool] (let [file (select-file-for-update conn file-id)] (teams/check-edition-permissions! conn profile-id (:team-id file)) (let [content (media/download-media-object url) params' (merge params {:content content - :name (:filename content)})] + :name (or name (:filename content))})] (create-media-object conn params'))))) (sm/defmutation ::upload-media-object diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 696c5e9d23..cdec3e8df3 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -416,6 +416,15 @@ :internal.media-object/mtype :internal.media-object/thumb-path])) +(s/def ::media-object-update + (s/keys :req-un [::id] + :req-opt [::name + :internal.media-object/name + :internal.media-object/path + :internal.media-object/width + :internal.media-object/height + :internal.media-object/mtype + :internal.media-object/thumb-path])) (s/def :internal.file/colors (s/map-of ::uuid ::color)) @@ -576,8 +585,10 @@ (defmethod change-spec :add-media [_] (s/keys :req-un [:internal.changes.media/object])) +(s/def :internal.changes.media.mod/object ::media-object-update) + (defmethod change-spec :mod-media [_] - (s/keys :req-un [:internal.changes.media/object])) + (s/keys :req-un [:internal.changes.media.mod/object])) (defmethod change-spec :del-media [_] (s/keys :req-un [::id])) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 381b8f5e31..32cf296a84 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -115,6 +115,24 @@ :id id}] (rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})))))) +(defn rename-media + [id new-name] + (us/assert ::us/uuid id) + (us/assert ::us/string new-name) + (ptk/reify ::rename-media + ptk/WatchEvent + (watch [_ state stream] + (let [object (get-in state [:workspace-data :media id]) + + rchanges [{:type :mod-media + :object {:id id + :name new-name}}] + + uchanges [{:type :mod-media + :object {:id id + :name (:name object)}}]] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (defn delete-media [{:keys [id] :as params}] diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 57ee632b11..fe4efc91db 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -350,7 +350,7 @@ :opt-un [::uri ::di/js-files])) (defn upload-media-objects - [{:keys [file-id local? js-files uri] :as params}] + [{:keys [file-id local? js-files uri name] :as params}] (us/assert ::upload-media-objects-params params) (ptk/reify ::upload-media-objects ptk/WatchEvent @@ -370,7 +370,8 @@ (fn [uri] {:file-id file-id :is-local local? - :url uri})] + :url uri + :name name})] (rx/concat (rx/of (dm/show {:content (tr "media.loading") diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index d3072e1a8b..8758831484 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -143,6 +143,7 @@ [{:keys [file-id local? objects open? on-open on-close] :as props}] (let [input-ref (mf/use-ref nil) state (mf/use-state {:menu-open false + :renaming nil :top nil :left nil :object-id nil}) @@ -176,6 +177,25 @@ (let [params {:id (:object-id @state)}] (st/emit! (dwl/delete-media params))))) + on-rename + (mf/use-callback + (mf/deps state) + (fn [] + (swap! state assoc :renaming (:object-id @state)))) + + cancel-rename + (mf/use-callback + (mf/deps state) + (fn [] + (swap! state assoc :renaming nil))) + + do-rename + (mf/use-callback + (mf/deps state) + (fn [new-name] + (st/emit! (dwl/rename-media (:renaming @state) new-name)) + (swap! state assoc :renaming nil))) + on-context-menu (mf/use-callback (fn [object-id] @@ -192,8 +212,9 @@ on-drag-start (mf/use-callback - (fn [path event] + (fn [path name event] (dnd/set-data! event "text/uri-list" (cfg/resolve-media-path path)) + (dnd/set-data! event "text/asset-name" name) (dnd/set-allowed-effect! event "move")))] [:div.asset-group @@ -213,10 +234,21 @@ [:div.grid-cell {:key (:id object) :draggable true :on-context-menu (on-context-menu (:id object)) - :on-drag-start (partial on-drag-start (:path object))} + :on-drag-start (partial on-drag-start (:path object) (:name object))} [:img {:src (cfg/resolve-media-path (:thumb-path object)) :draggable false}] ;; Also need to add css pointer-events: none - [:div.cell-name (:name object)]]) + + #_[:div.cell-name (:name object)] + (let [renaming? (= (:renaming @state) (:id object))] + [:& editable-label + {:class-name (dom/classnames + :cell-name true + :editing renaming?) + :value (:name object) + :editing? renaming? + :disable-dbl-click? true + :on-change do-rename + :on-cancel cancel-rename}])]) (when local? [:& context-menu @@ -225,7 +257,8 @@ :on-close #(swap! state assoc :menu-open false) :top (:top @state) :left (:left @state) - :options [[(tr "workspace.assets.delete") on-delete]]}])])])) + :options [[(tr "workspace.assets.rename") on-rename] + [(tr "workspace.assets.delete") on-delete]]}])])])) (mf/defc color-item [{:keys [color local? locale] :as props}] diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index fdafadd018..0a3b821952 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -452,6 +452,7 @@ (dnd/has-type? event "text/uri-list") (let [data (dnd/get-data event "text/uri-list") + name (dnd/get-data event "text/asset-name") lines (str/lines data) urls (filter #(and (not (str/blank? %)) (not (str/starts-with? % "#"))) @@ -460,7 +461,8 @@ (map (fn [uri] (with-meta {:file-id (:id file) :local? true - :uri uri} + :uri uri + :name name} {:on-success #(on-uploaded % viewport-coord)}))) (map dw/upload-media-objects) (apply st/emit!))) From 4d7a34a998a9fca8b9e45d2fdad8369854b16d05 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Dec 2020 20:38:38 +0100 Subject: [PATCH 186/195] :tada: Add better error reporting. --- backend/deps.edn | 1 + backend/resources/log4j2.xml | 10 +++- backend/src/app/config.clj | 7 +++ backend/src/app/error_reporter.clj | 83 +++++++++++++++++++++++++++++ backend/src/app/http.clj | 2 +- backend/src/app/http/errors.clj | 56 ++++++++++++++----- backend/src/app/http/handlers.clj | 48 ++++++++++------- backend/src/app/services.clj | 43 +++++++++++++++ backend/src/app/services/init.clj | 31 +---------- backend/src/app/worker.clj | 2 +- backend/tests/app/tests/helpers.clj | 6 +-- common/app/common/data.cljc | 13 ++++- common/app/common/exceptions.cljc | 4 ++ common/app/common/spec.cljc | 4 +- 14 files changed, 238 insertions(+), 72 deletions(-) create mode 100644 backend/src/app/error_reporter.clj create mode 100644 backend/src/app/services.clj diff --git a/backend/deps.edn b/backend/deps.edn index 095b0e4fb7..782997986b 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -34,6 +34,7 @@ org.postgresql/postgresql {:mvn/version "42.2.16"} com.zaxxer/HikariCP {:mvn/version "3.4.5"} + funcool/log4j2-clojure {:mvn/version "2020.11.23-1"} funcool/datoteka {:mvn/version "1.2.0"} funcool/promesa {:mvn/version "5.1.0"} funcool/cuerdas {:mvn/version "2020.03.26-3"} diff --git a/backend/resources/log4j2.xml b/backend/resources/log4j2.xml index df7bc897eb..26a71e7bc3 100644 --- a/backend/resources/log4j2.xml +++ b/backend/resources/log4j2.xml @@ -12,6 +12,10 @@ + + + + @@ -23,13 +27,17 @@ + + + + + - diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index 41d1da2365..9a6f3a3c66 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -40,6 +40,8 @@ :smtp-default-reply-to "no-reply@example.com" :smtp-default-from "no-reply@example.com" + :host "devenv" + :allow-demo-users true :registration-enabled true :registration-domain-whitelist "" @@ -78,6 +80,9 @@ (s/def ::media-uri ::us/string) (s/def ::media-directory ::us/string) (s/def ::secret-key ::us/string) + +(s/def ::host ::us/string) +(s/def ::error-report-webhook ::us/string) (s/def ::smtp-enabled ::us/boolean) (s/def ::smtp-default-reply-to ::us/email) (s/def ::smtp-default-from ::us/email) @@ -135,6 +140,7 @@ ::assets-uri ::media-directory ::media-uri + ::error-report-webhook ::secret-key ::smtp-default-from ::smtp-default-reply-to @@ -145,6 +151,7 @@ ::smtp-password ::smtp-tls ::smtp-ssl + ::host ::file-trimming-threshold ::debug-humanize-transit ::allow-demo-users diff --git a/backend/src/app/error_reporter.clj b/backend/src/app/error_reporter.clj new file mode 100644 index 0000000000..a567c17ab2 --- /dev/null +++ b/backend/src/app/error_reporter.clj @@ -0,0 +1,83 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 Andrey Antukh + +(ns app.error-reporter + "A mattermost integration for error reporting." + (:require + [app.common.exceptions :as ex] + [app.common.spec :as us] + [app.config :as cfg] + [app.db :as db] + [app.tasks :as tasks] + [app.util.async :as aa] + [app.worker :as wrk] + [app.util.http :as http] + [clojure.core.async :as a] + [clojure.data.json :as json] + [clojure.spec.alpha :as s] + [clojure.tools.logging :as log] + [cuerdas.core :as str] + [mount.core :as mount :refer [defstate]] + [promesa.exec :as px])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Public API +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defonce enqueue identity) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Implementation +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn- send-to-mattermost! + [log-event] + (try + (let [text (str/fmt "Unhandled exception: `host='%s'`, `version=%s`.\n@channel ⇊\n```%s\n```" + (:host cfg/config) + (:full @cfg/version) + (str log-event)) + rsp (http/send! {:uri (:error-reporter-webhook cfg/config) + :method :post + :headers {"content-type" "application/json"} + :body (json/write-str {:text text})})] + (when (not= (:status rsp) 200) + (log/warnf "Error reporting webhook replying with unexpected status: %s\n%s" + (:status rsp) + (pr-str rsp)))) + (catch Exception e + (log/warnf e "Unexpected exception on error reporter.")))) + +(defn- send! + [val] + (aa/thread-call wrk/executor (partial send-to-mattermost! val))) + +(defn- start + [] + (let [qch (a/chan (a/sliding-buffer 128))] + (log/info "Starting error reporter loop.") + + ;; Only enable when a valid URL is provided. + (when (:error-reporter-webhook cfg/config) + (alter-var-root #'enqueue (constantly #(a/>!! qch %))) + (a/go-loop [] + (let [val (a/" (:explain response) "\n")} - + :body (str "
"
+                  (with-out-str
+                    (:data edata))
+                  "
\n")} :else {:status 400 - :body response}))) + :body edata}))) (defmethod handle-exception :ratelimit [_ _] @@ -60,11 +65,38 @@ :body {:type :parse :message (ex-message err)}}) +(defn get-context-string + [err request] + (str + "=| uri: " (pr-str (:uri request)) "\n" + "=| method: " (pr-str (:request-method request)) "\n" + "=| path-params: " (pr-str (:path-params request)) "\n" + "=| query-params: " (pr-str (:query-params request)) "\n" + + (when-let [bparams (:body-params request)] + (str "=| body-params: " (pr-str bparams) "\n")) + + (when (ex/ex-info? err) + (str "=| ex-data: " (pr-str (ex-data err)) "\n")) + + "\n")) + + +(defmethod handle-exception :assertion + [err request] + (let [{:keys [data] :as edata} (ex-data err)] + (log/errorf err + (str "Assertion error\n" + (get-context-string err request) + (with-out-str (expound/printer data)))) + {:status 500 + :body {:type :internal-error + :message "Assertion error" + :data (ex-data err)}})) + (defmethod handle-exception :default - [err req] - (log/error "Unhandled exception on request:" (:path req) "\n" - (with-out-str - (.printStackTrace ^Throwable err (java.io.PrintWriter. *out*)))) + [err request] + (log/errorf err (str "Internal Error\n" (get-context-string err request))) {:status 500 :body {:type :internal-error :message (ex-message err) diff --git a/backend/src/app/http/handlers.clj b/backend/src/app/http/handlers.clj index 3d38551756..1265a97e10 100644 --- a/backend/src/app/http/handlers.clj +++ b/backend/src/app/http/handlers.clj @@ -9,6 +9,10 @@ (ns app.http.handlers (:require + [app.common.data :as d] + [app.common.exceptions :as ex] + [app.emails :as emails] + [app.http.session :as session] [app.services.init] [app.services.mutations :as sm] [app.services.queries :as sq])) @@ -25,36 +29,40 @@ :login}) (defn query-handler - [req] - (let [type (keyword (get-in req [:path-params :type])) - data (merge (:params req) - {::sq/type type}) - data (cond-> data - (:profile-id req) (assoc :profile-id (:profile-id req)))] - (if (or (:profile-id req) (contains? unauthorized-services type)) + [{:keys [profile-id] :as request}] + (let [type (keyword (get-in request [:path-params :type])) + data (assoc (:params request) ::sq/type type) + data (if profile-id + (assoc data :profile-id profile-id) + (dissoc data :profile-id))] + + (if (or (uuid? profile-id) + (contains? unauthorized-services type)) {:status 200 - :body (sq/handle (with-meta data {:req req}))} + :body (sq/handle (with-meta data {:req request}))} {:status 403 :body {:type :authentication :code :unauthorized}}))) (defn mutation-handler - [req] - (let [type (keyword (get-in req [:path-params :type])) - data (merge (:params req) - (:body-params req) - (:uploads req) - {::sm/type type}) - data (cond-> data - (:profile-id req) (assoc :profile-id (:profile-id req)))] - (if (or (:profile-id req) (contains? unauthorized-services type)) - (let [result (sm/handle (with-meta data {:req req})) + [{:keys [profile-id] :as request}] + (let [type (keyword (get-in request [:path-params :type])) + data (d/merge (:params request) + (:body-params request) + (:uploads request) + {::sm/type type}) + data (if profile-id + (assoc data :profile-id profile-id) + (dissoc data :profile-id))] + + (if (or (uuid? profile-id) + (contains? unauthorized-services type)) + (let [result (sm/handle (with-meta data {:req request})) mdata (meta result) resp {:status (if (nil? (seq result)) 204 200) :body result}] (cond->> resp - (:transform-response mdata) ((:transform-response mdata) req))) - + (:transform-response mdata) ((:transform-response mdata) request))) {:status 403 :body {:type :authentication :code :unauthorized}}))) diff --git a/backend/src/app/services.clj b/backend/src/app/services.clj new file mode 100644 index 0000000000..2268ed7916 --- /dev/null +++ b/backend/src/app/services.clj @@ -0,0 +1,43 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.services + "A initialization of services." + (:require + [app.services.middleware :as middleware] + [app.util.dispatcher :as uds] + [mount.core :as mount :refer [defstate]])) + +;; --- Initialization + +(defn- load-query-services + [] + (require 'app.services.queries.projects) + (require 'app.services.queries.files) + (require 'app.services.queries.comments) + (require 'app.services.queries.profile) + (require 'app.services.queries.recent-files) + (require 'app.services.queries.viewer)) + +(defn- load-mutation-services + [] + (require 'app.services.mutations.demo) + (require 'app.services.mutations.media) + (require 'app.services.mutations.projects) + (require 'app.services.mutations.files) + (require 'app.services.mutations.comments) + (require 'app.services.mutations.profile) + (require 'app.services.mutations.viewer) + (require 'app.services.mutations.verify-token)) + +(defstate query-services + :start (load-query-services)) + +(defstate mutation-services + :start (load-mutation-services)) diff --git a/backend/src/app/services/init.clj b/backend/src/app/services/init.clj index d0b69fa73c..6223b121b7 100644 --- a/backend/src/app/services/init.clj +++ b/backend/src/app/services/init.clj @@ -7,33 +7,4 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.services.init - "A initialization of services." - (:require - [mount.core :as mount :refer [defstate]])) - -(defn- load-query-services - [] - (require 'app.services.queries.projects) - (require 'app.services.queries.files) - (require 'app.services.queries.comments) - (require 'app.services.queries.profile) - (require 'app.services.queries.recent-files) - (require 'app.services.queries.viewer)) - -(defn- load-mutation-services - [] - (require 'app.services.mutations.demo) - (require 'app.services.mutations.media) - (require 'app.services.mutations.projects) - (require 'app.services.mutations.files) - (require 'app.services.mutations.comments) - (require 'app.services.mutations.profile) - (require 'app.services.mutations.viewer) - (require 'app.services.mutations.verify-token)) - -(defstate query-services - :start (load-query-services)) - -(defstate mutation-services - :start (load-mutation-services)) +(ns app.services.init) diff --git a/backend/src/app/worker.clj b/backend/src/app/worker.clj index 2b71beacd1..f7de49abf1 100644 --- a/backend/src/app/worker.clj +++ b/backend/src/app/worker.clj @@ -380,7 +380,7 @@ (defn thread-pool ([] (thread-pool {})) ([{:keys [min-threads max-threads name] - :or {min-threads 0 max-threads 128}}] + :or {min-threads 0 max-threads 256}}] (let [executor (QueuedThreadPool. max-threads min-threads)] (.setName executor (or name "default-tp")) (.start executor) diff --git a/backend/tests/app/tests/helpers.clj b/backend/tests/app/tests/helpers.clj index 2ae597a029..4ff4232dfb 100644 --- a/backend/tests/app/tests/helpers.clj +++ b/backend/tests/app/tests/helpers.clj @@ -17,7 +17,7 @@ [mount.core :as mount] [environ.core :refer [env]] [app.common.pages :as cp] - [app.services.init] + [app.services] [app.services.mutations.profile :as profile] [app.services.mutations.projects :as projects] [app.services.mutations.teams :as teams] @@ -50,8 +50,8 @@ #'app.redis/client #'app.redis/conn #'app.media/semaphore - #'app.services.init/query-services - #'app.services.init/mutation-services + #'app.services/query-services + #'app.services/mutation-services #'app.migrations/migrations #'app.media-storage/assets-storage #'app.media-storage/media-storage}) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index 5cde2320a2..a52991a687 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -6,7 +6,7 @@ (ns app.common.data "Data manipulation and query helper functions." - (:refer-clojure :exclude [concat read-string hash-map]) + (:refer-clojure :exclude [concat read-string hash-map merge]) #?(:cljs (:require-macros [app.common.data])) (:require @@ -210,6 +210,17 @@ (assoc m key v) m))) +(defn merge + "A faster merge." + [& maps] + (loop [res (transient (first maps)) + maps (next maps)] + (if (nil? maps) + (persistent! res) + (recur (reduce-kv assoc! res (first maps)) + (next maps))))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data Parsing / Conversion ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/common/app/common/exceptions.cljc b/common/app/common/exceptions.cljc index 69885361bb..3891782557 100644 --- a/common/app/common/exceptions.cljc +++ b/common/app/common/exceptions.cljc @@ -48,3 +48,7 @@ (defmacro try [& exprs] `(try* (^:once fn* [] ~@exprs) identity)) + +(defn ex-info? + [v] + (instance? #?(:clj clojure.lang.ExceptionInfo :cljs cljs.core.ExceptionInfo) v)) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index 1292e1bf96..929396e916 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -189,9 +189,7 @@ (let [edata (s/explain-data spec data)] (throw (ex/error :type :validation :code :spec-validation - :explain (with-out-str - (expound/printer edata)) - :data (::s/problems edata))))) + :data data)))) result)) (defmacro instrument! From a674b3ab940ed2c79ad5bcf3b0d339607e00bb8d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 14:12:38 +0100 Subject: [PATCH 187/195] :bug: Fix unexpected exception on faster merge function. --- common/app/common/data.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index a52991a687..99a643129d 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -213,7 +213,7 @@ (defn merge "A faster merge." [& maps] - (loop [res (transient (first maps)) + (loop [res (transient (or (first maps) {})) maps (next maps)] (if (nil? maps) (persistent! res) From 1c8de910a6be8a301c2006451e78f79328e2d5a9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 14:13:04 +0100 Subject: [PATCH 188/195] :bug: Add missing license header on version ns. --- common/app/common/version.cljc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/common/app/common/version.cljc b/common/app/common/version.cljc index 5edb35d091..d02fe513e5 100644 --- a/common/app/common/version.cljc +++ b/common/app/common/version.cljc @@ -1,3 +1,12 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 Andrey Antukh + (ns app.common.version "A version parsing helper." (:require From 419eecbe72024d5df1f74056191641380fa9a882 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 14:13:25 +0100 Subject: [PATCH 189/195] :bug: Fix wrong volume name on devenv and build scripts. --- docker/devenv/files/bashrc | 2 +- manage.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/devenv/files/bashrc b/docker/devenv/files/bashrc index 8b623d9029..3f1ddd20ba 100644 --- a/docker/devenv/files/bashrc +++ b/docker/devenv/files/bashrc @@ -1,6 +1,6 @@ #!/usr/bin/env bash -export PATH=$HOME/.local/bin:/usr/local/nodejs/bin:$PATH +export PATH=/usr/local/nodejs/bin:$PATH alias l='ls --color -GFlh' alias rm='rm -r' diff --git a/manage.sh b/manage.sh index b628f83283..480b8f8009 100755 --- a/manage.sh +++ b/manage.sh @@ -62,7 +62,7 @@ function run-devenv { function build { pull-devenv-if-not-exists; - docker volume create $DEVENV_PNAME_user_data; + docker volume create ${DEVENV_PNAME}_user_data; docker run -t --rm \ --mount source=${DEVENV_PNAME}_user_data,type=volume,target=/home/penpot/ \ --mount source=`pwd`,type=bind,target=/home/penpot/penpot \ From 2907dd1a50830ecce3c6233ca220b379f8d92b9d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 16:48:26 +0100 Subject: [PATCH 190/195] :bug: Add missing require. --- backend/src/app/main.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 431d3f266f..d223de175e 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -29,6 +29,7 @@ (defn run [_params] (require 'app.srepl.server + 'app.services 'app.migrations 'app.worker 'app.media From 05563168c3abeaa4761e02f61aca090d35c2e0e1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 17:25:49 +0100 Subject: [PATCH 191/195] :tada: Add onboarding modal. --- backend/src/app/migrations.clj | 3 + ...0034-mod-profile-table-add-props-field.sql | 1 + .../src/app/services/mutations/profile.clj | 25 +- backend/src/app/services/queries/profile.clj | 11 +- frontend/resources/images/dashboard-img.svg | 119 --------- frontend/resources/images/deco-left.png | Bin 0 -> 4124 bytes frontend/resources/images/deco-right.png | Bin 0 -> 3616 bytes frontend/resources/images/login-bg.jpg | Bin 150020 -> 0 bytes frontend/resources/images/on-design.gif | Bin 0 -> 376471 bytes frontend/resources/images/on-feed.gif | Bin 0 -> 389308 bytes frontend/resources/images/on-handoff.gif | Bin 0 -> 647073 bytes frontend/resources/images/on-proto.gif | Bin 0 -> 496554 bytes .../resources/images/onboarding-start.jpg | Bin 0 -> 32513 bytes frontend/resources/images/onboarding-team.jpg | Bin 0 -> 20760 bytes frontend/resources/images/open-source.svg | 38 +++ frontend/resources/images/penpot-login2.jpg | Bin 195319 -> 0 bytes frontend/resources/images/pot.png | Bin 0 -> 117830 bytes .../resources/styles/main/partials/modal.scss | 187 ++++++++++++++ frontend/src/app/main/data/users.cljs | 11 +- frontend/src/app/main/ui.cljs | 1 + frontend/src/app/main/ui/dashboard.cljs | 7 + frontend/src/app/main/ui/modal.cljs | 10 +- frontend/src/app/main/ui/onboarding.cljs | 230 ++++++++++++++++++ frontend/src/app/util/dom.cljs | 2 + frontend/src/app/util/timers.cljs | 4 + 25 files changed, 520 insertions(+), 129 deletions(-) create mode 100644 backend/src/app/migrations/sql/0034-mod-profile-table-add-props-field.sql delete mode 100644 frontend/resources/images/dashboard-img.svg create mode 100644 frontend/resources/images/deco-left.png create mode 100644 frontend/resources/images/deco-right.png delete mode 100644 frontend/resources/images/login-bg.jpg create mode 100644 frontend/resources/images/on-design.gif create mode 100644 frontend/resources/images/on-feed.gif create mode 100644 frontend/resources/images/on-handoff.gif create mode 100644 frontend/resources/images/on-proto.gif create mode 100644 frontend/resources/images/onboarding-start.jpg create mode 100644 frontend/resources/images/onboarding-team.jpg create mode 100644 frontend/resources/images/open-source.svg delete mode 100644 frontend/resources/images/penpot-login2.jpg create mode 100644 frontend/resources/images/pot.png create mode 100644 frontend/src/app/main/ui/onboarding.cljs diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index 94d3aaa3ac..c1ec7bd664 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -115,6 +115,9 @@ {:name "0033-mod-comment-thread-table" :fn (mg/resource "app/migrations/sql/0033-mod-comment-thread-table.sql")} + + {:name "0034-mod-profile-table-add-props-field" + :fn (mg/resource "app/migrations/sql/0034-mod-profile-table-add-props-field.sql")} ]}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/backend/src/app/migrations/sql/0034-mod-profile-table-add-props-field.sql b/backend/src/app/migrations/sql/0034-mod-profile-table-add-props-field.sql new file mode 100644 index 0000000000..11f80ec320 --- /dev/null +++ b/backend/src/app/migrations/sql/0034-mod-profile-table-add-props-field.sql @@ -0,0 +1 @@ +ALTER TABLE profile ADD COLUMN props jsonb NULL DEFAULT NULL; diff --git a/backend/src/app/services/mutations/profile.clj b/backend/src/app/services/mutations/profile.clj index a45ddcbca9..01f11d69c7 100644 --- a/backend/src/app/services/mutations/profile.clj +++ b/backend/src/app/services/mutations/profile.clj @@ -280,7 +280,7 @@ (defn- validate-password! [conn {:keys [profile-id old-password] :as params}] - (let [profile (profile/retrieve-profile-data conn profile-id)] + (let [profile (db/get-by-id conn :profile profile-id)] (when-not (:valid (verify-password old-password (:password profile))) (ex/raise :type :validation :code :old-password-not-match)))) @@ -310,7 +310,7 @@ [{:keys [profile-id file] :as params}] (media/validate-media-type (:content-type file)) (db/with-atomic [conn db/pool] - (let [profile (profile/retrieve-profile conn profile-id) + (let [profile (db/get-by-id conn :profile profile-id) _ (media/run {:cmd :info :input {:path (:tempfile file) :mtype (:content-type file)}}) photo (teams/upload-photo conn params)] @@ -409,6 +409,27 @@ (update-password conn)) nil))) +;; --- Mutation: Update Profile Props + +(s/def ::props map?) +(s/def ::update-profile-props + (s/keys :req-un [::profile-id ::props])) + +(sm/defmutation ::update-profile-props + [{:keys [profile-id props]}] + (db/with-atomic [conn db/pool] + (let [profile (profile/retrieve-profile-data conn profile-id) + props (reduce-kv (fn [props k v] + (if (nil? v) + (dissoc props k) + (assoc props k v))) + (:props profile) + props)] + (db/update! conn :profile + {:props (db/tjson props)} + {:id profile-id}) + nil))) + ;; --- Mutation: Delete Profile diff --git a/backend/src/app/services/queries/profile.clj b/backend/src/app/services/queries/profile.clj index 14da3b4535..db954905d7 100644 --- a/backend/src/app/services/queries/profile.clj +++ b/backend/src/app/services/queries/profile.clj @@ -73,9 +73,15 @@ {:default-team-id (:id team) :default-project-id (:id project)})) +(defn decode-profile-row + [{:keys [props] :as row}] + (cond-> row + (db/pgobject? props) (assoc :props (db/decode-transit-pgobject props)))) + (defn retrieve-profile-data [conn id] - (db/get-by-id conn :profile id)) + (-> (db/get-by-id conn :profile id) + (decode-profile-row))) (defn retrieve-profile [conn id] @@ -97,7 +103,8 @@ (defn retrieve-profile-data-by-email [conn email] (let [email (str/lower email)] - (db/exec-one! conn [sql:profile-by-email email]))) + (-> (db/exec-one! conn [sql:profile-by-email email]) + (decode-profile-row)))) ;; --- Attrs Helpers diff --git a/frontend/resources/images/dashboard-img.svg b/frontend/resources/images/dashboard-img.svg deleted file mode 100644 index 00544e925d..0000000000 --- a/frontend/resources/images/dashboard-img.svg +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - Octoface - - - - Mark Github - - - - Twitter - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/frontend/resources/images/deco-left.png b/frontend/resources/images/deco-left.png new file mode 100644 index 0000000000000000000000000000000000000000..bd14661c7a9515ccb4d2236cda284190bd528be0 GIT binary patch literal 4124 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 literal 0 HcmV?d00001 diff --git a/frontend/resources/images/deco-right.png b/frontend/resources/images/deco-right.png new file mode 100644 index 0000000000000000000000000000000000000000..cc108924e5fe9150e0e0aa73c1873531724f2e79 GIT binary patch literal 3616 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 MH2f!^;aK(m19K59g#Z8m diff --git a/frontend/resources/images/on-design.gif b/frontend/resources/images/on-design.gif new file mode 100644 index 0000000000000000000000000000000000000000..94a3925b54adb6e4ba1e4c53f16f145c1f46ea2f GIT binary patch literal 376471 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

u`DJgf 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μ6}H}@G~gA3(Cdi1AM!69hjFB|yeVOF1>p-;? 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 n68sBZ~|O-k-vX{BnP&n z+xAT*(PgPXu#9$lkz8Oi<}{Bma-6dFH>Q7E#0%^S^S>c{izF8XD6bHuW@v&1yEUnG zykdWJ`hJNe%@0L`3c8^UbPEu()dq#Rf`U;&^{?@KcQ%Z~w;D=j;OY<(qsWP_upJW+ zS^wZ0|AfSs3q@ao1|2_$?Z-pxWFj8cJV3wt#}W6nmv4Ig<_-mWOaKwx^Oefq^Czio z!M@PGi?kdP-jAo3D1kj1y`Kz2lAQuCpqvR2ZQ_<~y2U4cEEx*kudeFR2Q0f}=nO1B z)_+dHerrydrVMnq=#o{K4Cc4L?{O}V=qrUFvz)WqewZSAG&!)rbSs}S1BfAX&9@6I zS=@bG!YmnI{(AIH+-C_22=5tYetQTj4W1PD%VT@s*5n$|1fwYp{AL-7%mYt|U5O-y z$Xn3wSF?;qfX!hKl47rZt45aV26K}M9g*y6{F65@^Kqu2c)bB zmC@X)4~(r`SoqDrcRK`WWP=%m5Hal5V4SVj@7ToeQIOB*HUBtnp~&`TIN$fUWy;Kh zXuZ3@bq`g!a3mq#n8UyQvyQoof*3SRIpW%Ns|S2I#`4&N^?O|L({ZU*DA-eUfEgB11afCo=3O+6yMy@1tkPk4A%RV0fBAfUOb*N$H41;!@wl-@LPr z{z@|1TKC`-pzSBJ#N%mPR+Bp3ppHi|-#FOJ!QQCPNsK5+FLyxtqnk(6mx_1F%IJylI&qOu@H7*`WHQB>XD3|qLM7Hl*EsVWyWQO z_ydeY5VrtGj5e!CPd<)J9koNlP( z!`PJ~O;EWZ30b10Aiv|>T`U4Vtyzg@*az6<%p&j5#%1Yo*flerTe;Ui1E7y{X>f?@ zQB)iD!u-MGN)l3;_-%5jL_< zXDKdjKAl|?j3SRc9^?d^r(NfokS(sZB!|38(1l3~_2#*f!t6uHuS*)C`I8CjT^ZL`jTZBle7H=6|;;az>!0WncDzGQ>Vu7Mj9lL zepZs$gIJzP=9d6aMF5=5iG~WCSG0$g2o!OIl(#$-jE`X(=kcwPo%9{?worNmR z6+|6GCIM!Sf+#eBMfX5+T9BIpuoNPL!FVO-CQ2@`sLdx|o(Q52@m*3aX-kmwTC9FJ zUg5J@0Zj*8qc0m2D5%e_^tR!CL|Lp+Q$_jOpaK%Bg&vnjb=0(ft_kO286`167VBu6iCqR9 z-KVuNr}fH@>j!MuhwADA$Ls!9mfLhSAZHp_gBormR*oms&MjgF@x>XZ4KGib3Tu&R zA`Kth*k23OWF$5Y3b0h}$wWEn;nyEK9W0Q)Lk2wyN5-F2P+Y zxPhJ-bgt=A^OLra>fdJa^h;cfTTM!6M%r^IdBP3;@u#4@r(oY^j+-o8RHU! zn=wUeml)4#P2s0*}nZx(ob0##Bn}njpf^G_8u9>mwrehwSV+{#~ zIhV1zmZ4+Mq4!Z>cpso`#(FoBHE)8|r5Sa1hWe>x_w1wbMza*0(+aRcITwg+?4ujc z*fNq(L8a{4vs~B%ff()=h<&7x3M$_j6MZI(19J?VL&cYJJi1eY?GqYI3Xplu&n(ch z*U$F$CLfd%!HK-sQ*ppabO?LT;1gvjyt>rG=g?b2=%qDd#4$s6&d^UCFl)^(|17=y zclHwCA%oS)kXvME82PUuC}{~?-^V4N{xT4dpth4cd|!Ov2I7=3T-|;D73=@>3Gnm_ zsrQTA>K6;^=T;YE-6r$*ai8DgE-ICNeiL>6PlrUXVLg+x6sl~2)bK&@5L{*(db*Fv073s+Ka6zuXz`yh63=*DBq!*vUczf7HN8!XCGphyl*UYlq%Mfd8;1dWI4+djO4aG2}6O+r6uewLo z)5SrgKJ1J*#w@<#0G;$dHIkraC{alANVRS0508Z$?FA6~ygK)BusC}{nLJ0~xKU=~ zxTss*|9D2&8D}cYyLrP?k!Y%hCwKy(r3XNO^hNMPkSb^u1i&c(4V>ry3blN0i$w_= z6zVmX4JC2NyDg74m+PpDFc~SM01yPNre1ez>{;bRuB@XHf{nzEO9zRKE|0ZTQ=x+L zCg$gv#Y2TmmI zb==dcN|4YQbhvrf?TJ7wphV5!ZA7dPdg58m1&lEXE|kUiYfWP|*?aQ+O^t@T{BtjX^(Zl9b+Pfy=4W?k+jz4)iGe>pkxLWlNzxtrtDzeyZn??D zSWU2~g2)PY=g}5#E~~a!BHzW3Eg~mH#25u018C|TZ@(`7()I0grkrI}xyRYrZ(G%y zmdSiI=gJqJ-+TyRt05{3b?c_d&qC}$I=P$@r4fz$>{z)DIn3v1o^RhLsq@PmCoVFSBW)k$DiXt(-~JeB|V6E z2v|b^A3ewV086jqoWL#vzH60iRgS5+PXC<|144sYV?G+AJ!-xd*ri*c&NJ&fpg@qq zT=BxN09I}E-E}lplm;DAttBH8O(+Og+RQ?L-zrLQ-*CBK{5aKl^9@wUrD_3dn}ws} z7SfBx=F`a4ZPdv%1CcNxC(2$q_7Vh3%gV#E2F^m4j&DAdEh0uhX_}{R;_A4fC7UMy zwMyf(s;u#_I3@Q+!}LBWJPk_Jow53R3!GS`&^S2J-n5SJu*?526xg|cmq7~q2yw;!k^b<4sjg-#!4J^TWe}%s1g1=b@L)ky2OV`YaRI_A+Rk+cwx^H7m!JQI6M>PS z9BB}OF5n8MRHSO06{`PQ0l9!CB|ALrzsnM+bVuA3d13tJG|S#eC7PpE)2|9i7Ky_4 z02@m{oqQ7OIUXg^!mUW_cY2YOF$fNOCtR(Z0NDR6Xv?{qH? zizq`;;`9cExc1}qjLMjEM+e1J_Y?5RWteKcAt{^vM61a%w&$ZmG9mj(_K0$h5xwDy zkN1;ZjLNy*j}9w!?Wg!8m-Bqr8&O@{PYs$Z=leA}qItTXMnF^u!1PD8xDJT%MioNr zW20A957LRr6(ZvLV+J+{8F`ZxVwc9oOhOJaNr*}bUHx(M#|K$8MwL>QW8*iv4zin) zE2Z!0PuMITYxDNA1jjAr@j!inNwuGP649nF;&{Jpj zxIplEt$%$}UVidG_rzzpyyjTRJbBDW9)u0rW8J=tDzl1A2In;K(4Y@4nJ+~AqJtB zfDg!pab1fJ@{bL~x^aMEGmoObAjE0cm0nnDV@O$bAdO*8Jb}JRQ&G@3=Ck@so9oRX z4=PN)ZXT1!G$1$$fJzYT4sC!*2B1IaJc=>}t;V@>kiC#>vN8^-rLXQq1)S)kZ(%5M?$$YxHfUj3gPZEm929IOJu? zz+(T+H}?lYxcIAXp=HQ|GN2k3tjiEYwx}v@Yi|#?%PY!eLC9_d97{u z+(;4~B9}9&L-Z}j7O#Y#!&h`v*R>~lP))2eyIvoilbHNnrGp5+KY0{U>tm^0P;&Pb zM8|WMF)WIC-+_%q7>OIjUS*oT2YD*;>SnQCZkjl)p!OgjkJVANLf{|$Dd!0u{Sg|P z4Kw6k6pkGsV)^ zSj)-`VT-bvD6?zZ^YgTgofP0LRyw#^*5{#q&IvkPrTENK!)^7t+Au61r1)eReJ9L* zfZkWDUD4b$9X=lk$;+)vNF zq@UbElyA5AASNgpg*%_*=#-NgwbmaThA!>&Dt?dm-E|fgp^2gV+b}gSJ8U-_9c zI>62BJCa@A^G;I_YX8KKq(d`F&klz_)+x6;psY0JFQxOvz9y?e22fZGTD^nACoKJ$V-0zPvU3kH>VES`%yG`0*|CQ=N9 z2R|-6XV(zS5A=KYwaWK3OZ4Z0M@cMt-j9VGd5+@aI==MWNL3Rb{Q2V3c)dP90a>%S z-B}&H*Z3~P$J>3jG;LxrfggC5%lpd`8N3a9e-b_a@XR+~gR&p-C^V{qudDvo;^2}d zYE_s20wXCLz#^&O$Cv#px;OvWUPhf>_;fB=H#8(3WvQ9S7sj& z4}g*Vzv`l(^S3E51swSy4K89soE@YW;_4H|;2ZHTE8_B-@XyB&;{_jZ=YVGdLTDT! z*N0TfM;?K30kzE!D`4Remx!^r`$#Lrw*jafOaBlvrt>hzBy8k-uFK-D2!obKRIF#~ zXK?Fx@NQGgt@#+c4wM%w6f+Z(O+%Ym9W24Y-i8f@t;Bf!j-mT}Baq0%0*Z@{0xNR> zlH|yw=0|sa!M!=+>Cv%{qcPdqpkSAnwuqRDYT5{jL_A!O3P42%C@X`Baheh_@gTVM z?|5&HI7iXg2QKkx{t0wufqFF@OW4rPFA3Q-<~B+R=>0@L3*ePFYA7c*SP*pZJ+V~+ z6|J0j(@Lc(9wl6p6x0`g=N^LVYtldvDnlaqwVpC9NeFD_G+YX4g~6xRlhZj8W0X^( zg@NEp(FObP)@sOy^`uYh*Pp@BFN2icu7^R1i3JXb4GGjMiBuYNa+Y3Vs&*>eH~Mi0 z$4N)(6L?CqL<;7ca=0RKw1yqlnZ`($q|chls-mvz!rM@jc2+~&86^(2#C;p(l(Dk4 zI!uRtPHTY^2jmIw`al)A86P_`7*5h;D4goD2|O1i0~D+?A$=Kpd6|8y58uyZ${uHK zyQKR|WDGiH@u+0d;L??X(`Q}O@d-TE%Gpw!S(g?vbQaXCgLz;H#A2)LviM9+6?M^0 zPItYK&CzVbjcmc%9CuE2FDUDYJyInb30lczi%3n;L)k8*t>mFXT~SoF_(Qt9_ZfMx zzPv{X=o(tqPJ868GHQd!kZO%y)C&m~&ZQg6%GXEb=I7t+$S-m|Umc99%SQ{ZV@`++ zT>$+tIhQ6Kc|@XKBRZ_n<8a4GiO2U`(_O7mE!G9k^-*181-&PEt*!+xPjX)@6ui+# z&mUvHkPF)Lk(n;YL=wXorKymu8930*i{S)jf>2Afg&!qRE0V=)uIGO&6n)|>UJWi{ z@deRtFrT1`yL<}r#)=O0(e-*Ek+H@8u6Z}|EdVLf29|U>CQTVDKuMJ{?i1lS#t>`d z7^!eSzl4PzU8on5P(~`(&o$1s;G-}5ElJubE8v$Zx?n?s&44jYsNg2n4LmZ6T)@vo z0;^W&*i>9Gpn=KC!R!Hpx{5OU3OrY3*aqB!KyNNZA^{a_A(gilEA37z?YXM%a8+4L z6^~mZQ4!!z{j4X7kjl6`fgYR!Ec`a1$p z3nC(#9^pgbs=zMRByrVdsMcoL)aHcL<{4D`Y*uNhmO&$E7(l>RDv)oZhWNPFkDfkk zvAVvi4vVU;F{r*nrb*zcO&qVS=Bn@Ns_$N`&+4l6ax16zg$m^6R(+`6cJ0Y!zG?%8nhlQAbvMI?$q z(X)8?O#}2pxTAPtnP7ccs6xgzjP`DLk!H0#zw>rw-?1`448KEpQHggKc;Y^atz zKPi1AkM_Za0;tCVXYm3m&ma+PDi zn7>dyMP%CLM1Ru{SvE(34Ik6ZARZKO)&{Av#m0$^!xx+#?D&S?e!hHWl1 zE31HYzbhz9JcmBChx?GAZUQK8dF79o7TUg>@)Mjr4DG%N9aW)Sj9ln<)6jixs+$nk za#Qi6NH28erU{u-PcmThMK8{hy?W~7&CY%Znr*%nAs*ZaVP@qz}`!2Xy5!f z^ai=dZ3X_Q^M&nziTm?TPn=7_ew+OgkmuOvw3G^+K#edATvX3b9WX(w_j)=2`%UbT zbnVOVLENo&7OF)}g!;?E(TxaD>$+e3PE zUzRC$Z#aJ0L`WLN{SA1q%&MN;FG?KFOwL*0Mt}Hfr2?v)O6qoiH4S2$8AS>G%ZMrGvHlxj*?ldq0;B_= z$1Db@S3f6ju765bbN4h<<(mW;)5dM51L+nK|m7K{XenC?H1uM(F(D%sc|Wy=^TK2FTzU`1av4 z0@Jd*Z)VlwYZ%aT)6~CHIYRHc{rJoT`Q_?gGm4eHV9CS6N!KE|r>*roBqn6Hw z{inP7Gi?Te;o?7Uc~-y%d+_iuRGTcF!3vm}IC0zfHAIlg^+ahcP(|uKo`y6LMlNTzOdBy| zd=b8A?&)BH&%;msd3EStIpt2en=2NS%v4i%=5e zc>6=BEfo(*XWsPbk1c&Cd6{*8nbG%SPq|yAY|H-Nw@@}!>egE+<DjafsM4mybFa)3p^x< z0ScBWFvr?FBfP`FV}eMLMf&%C?YjG2zG%%$<{Py#UNFU6^)aRs&%pB#)L8X3ZRe|# z?O6Oj_4Zf2Jn36r@U>KSWFy};YwE|~VpQlybp@F>?4{e@OiwxYw(fr3v^CiR^Q~qV ztJhWiP)*sXdbQ2DvTY680hh+4KPi4@vUB+AJ6qKb6)Jdx@7>3p^`}qdIW>2NG&N3o zcj0M2xQ2FiQaSfz_5vS%4zb&LXLp_M(f(-fp6JIPDgX8kWHwB!HBd48B9A@_zxu&w z`W-~sA5KVLV8M&>A4XD^cT<1u?lA!eJ24O{kr1iz19QlMOhZt%J>m|%B=+Y%9?q^B zV@vk3^bUED+r+9blO&{V$D#hypN15q@zdQ(&7Zp_2w^MwK{CSf_O1h;rtQ-o9CBZ{ zy$?UFf!bEUeSes&c2|F;YPgrovH2d{&pqI01NiKl4^n?>dTEB?)#W4yzr5$NnBeAW|vO0^MXe9lza=uFDW+%`VxxgZM}vWHjV5uy%K zQ1M+7auQDunAK;IZAzl|RwBx-yRMXSt1`K(u!0 zVu4ljNE-;M_nX1u$z3qe|dGagl^zA8W-R5*_$nl<#5JVOWf{8Ryp@KTHI9hfm*|I0| zNwt^%+;`lTIhEONnUO+4+ zWIHh}lLI>)<)TN&5lubvK5!bnl%N9tI-y-74}NE-H{MlAc>iZDg&87q4FG)`oHC=$ zc)iu^D!(yi_KNV-Sjn`LJIl0V&a&y4$v%X&u~%p-vxzN8S^C;_`Pq>R7$B`W zKC8N({e-Q~OsUrMMT+~gq%zv)AJUKYtE-wh{NS*OWct|;YQH3P?UcDg);~IaJTdrS zesqPSq7aWeFND^PK71ej>qDGF9Dl0BoxFEP#19FV+kbL6R!zGxPD=mfm?P@SoUGkl zDjZwQ5+7#EcFPi;n$F*CIB_m;2495m!LX|3vFbLLX=5#u+SW}68Sa7R8IzlCjY~H|Jr`F33O+pDIR4?8$~dg%-Fx<@ zb@yG~t99=_4f#Ul8l>g68*%MUVcQ_u+FpWQpy`oT9E~ z@b{89uG0;cmJg>}7VIC(SD(K==REKd_NnfL_XYm5-7(Xb0X<8f+&zBJWIX!!ySlyP zVf*3BN00v1#__!Wm&-Q7xF-!(um`iSq5f~{qXDc6D*6A9eS&{oSG&Q;TIco_yzTh= zY57Ph=pXL?^m+fM^)c=^`OYYxb925oh2iohX5-m^)<+aQZw`B4bA=%p^yh@-x5@UK0*k=dwS|Bup9kVu z(ryjVjPR0a(*%diJU8u&Xlc)VoLsPf^UC%YuVEdVLvLj%o^CD-CBObY;aALO&=tk) z(zE1JQlXsSf6>s!fRw$}AFF5wRB@U+^?fo;bnxjD{}8~!2pU-i5QjFsRsrQ8eM zM$lhdO?a;Kucs&UyZ(^H1^!;2{U5uB-o?hHghw?0SgCytF#R=w2q;7VpjEGMo{2&+ zvwkq1vyQV3plh!F6nlPOVOA~JMHT==GL-N9x3P355!@VKmMB4gKZ0}j=Kvf26w$(M z*9&^iIBfGYYKl&$7L9t z&SCjXx>}K#6b-TKxSED$Zl~N@OYw(x-!{x8nTT{`Jd;9(m|?~OYxdp!NsQfHh=X!r zQAmLGJKj>v9Jlsh*vj`C{CIg6gR=_ZcU}%z4{k67P-CPvCVrf?#p)ash_kl2$7VLB zv91*<^-^-^nz^!Gplf*}{YhPJxRDw0Ec+*##t3V3I2c}&6V&}Y}=dm{?M z*Iu>gNh#3CiJiHle8PQPquSL#b`wr`n65E!hlvY!juRm{u>NWn_;RyY4xNB!8@CQp^fBJTx_MZK- zl_{z-_S05%|Mb(Kc1X|srfPG~*AFZ*mwuDe__0Se0oPN1r1O*h9OSg8ot*705v!Oj zQ8c5k!tChm)&Q)^2Xu5G56B+)^d^3T4s!n}G--4tqp zuilMF{M$_@UNhpDR3@5VyOAwtOyr7v6g@%<>I4OhxFS^3L=m}+HnWnqY)v)xNgPQlg zo8AE_ki62r53Q7t2Sy|5o z58olCrf0NPB&64$|usF=$awLiq|3c*R9aeLL_^p_wD9 zUVANMVd`3zywQ=g5ssm-3EbWqukyp$yxwM(B6XwgY0QsXLC3|}SD!$j`O@xxRTq~x zZ^#&jAO&Q(ZuLG?Y)v}a^!;Ae`%A(h!q>&iGH%Oe*yO#e_23qmztnb6^H<}{-zN@C z_BZBanhahwN_$n-+coMS5_YV;)-D2{eiY|cZ8Un{u#q(y>KvhEXuv(1I``>ih$UG^ zkX>tTv6x00g<|-({piXPYE~;qqFe_K+~45+d%Dr>c3rFex3t+ZK>46vpcDP3>vNfLHIK z-H_WgoN4|vETTp8JA!~5{W^(dmCs0yKz)A3Mn0UnSfOF`)>wE^z~^5ajN?O}E`ucl z&$dU_`Ea{0V4Lx%V{d!$g1hGfD=Z_-hx{&6f;-f?1$I_u0Y`LtdT-vkgFMKClcWxN%{{Hbe6{aXrbYGUAbB(t%e=Rfm z5*a4IJtW%iz}>RsQsfU?sFA6eQ5Oyk0`7ed7fE?t~1db-o*m;F&KEW+$? zOn6V__auMOVffqAgO=Gp1(ug-AL-Ijc;at|i@5$ZJX07_s*>}H<+^`aHg7#;T z6ruq0y7+%m1`t{BHbTD)vLq11g8^jhgBId~IDWI3Ff;zS5~*PIkdsUR`PlA?qRz$N zhn7ABMju`nWp4Ze>9`i9XGMKv{LFn>UQ?w4JUx@Jy2kGZtn)T9%F!BT(yp1&c5pxj z8^UEqZz4c@H;>k2kFE`Ccs)MwvP;BZRSc(K>mhQ0~%o=adSpVoGH~>Y((lsN) z=DjI^0>UgNciqXlBY|dK{woo7?q`fB07Ez=B6NiQenYOeqZDQ1U8=&GI50)={3$3% zK+PjgJPpS;RF@S!_ni0HUJ^YT7WMm4eoewq9`nd=#WWO*DhUb38~z7=CP8dg;!&kZ zC40#At10jDP(A|Dc^vm0-lr7)PWe%JuCht~6i5RLrZGmOJg!OkotJjHp7LitO}rFo zT!Y-7M(*n&-p-?rtlWQf1TzH3GfF0l&RoZ+5ZP4H;0{E~b+;{82Cp?Ue=Tw5$U>MC zfQ+FyHy-&=Bm&QGq>t1%*yy^;TW2yvWQ@ke#B@++DpRDbZZ5E8i6*3t)B#CdAKH< z9OOh^P4^8>56cxfQof(_AlHACEhNDutTx-vmEd%TXqWF0t&fQf&V#4t9gK>YyFdx^ zLPs?@t*{(kNpubB+}}Zovl^C=PE?L-y1E5bV9@Ec6rx$7EhSv2Y2q1#K0bxB+@Tf~ zo6d8glPK66rsl^2a&EfOBFs%-!_xDm_I|!Wxzx3g-ZD&|IVX5EV_?iz#Gw#a0X0dg z02DlcAz`LAFnwl>$+<*n$+$BVo1-tRDw3`CqO^3nk3{q1Pn^OA{lLpvaOEAgp9|m- zAH>#JdZ0CXpc&)v47>Us`=x!BpH<8#y0q@!MN50)BIbaj1Ivb7;X^d^3#oX!wjg$t zBNfE)8!fJuQ6$sssgcg7um(EYgF|J7Fal6hGfp)#i7ecG-I1I!99K`N;4TqU>nnY> zN9UwfUVn!=U{K-V%OwF6igM+2HVa=-m4BJe6^fQTBTDYf%HT*y?zb=*Qsvw}cbhM% zWGv^cfcV29(Rce8lwWnw5}`dUg~^=~af z4+p_OS)`>wHZ{8U8D07SZ2qkoW3*pO;;JiCt*fx9s|u;Bd0bb<#ZL@jmH%3W(JEDELJf|s+`b4 z%{XvNr!)PbW;jv4if^AP(l&tvnkY6+v`bH6+)ea`O;CoWf16LieGXqp!rjeP5&&(T zd99vGg~hW% z!ZN816e3mOK)SIWdp?+@`%dvoEh%O+b^}GkFX$fxHp~u zpr!SPi@ta7Idvsv$((7I@cds)`!&~Ab_evS))kB|BE^Pu{j4LTK8-u#dV@bnmcG-0 zu8XC@C%qH@>`3iXPM7Cr;xvb3qha>-K7$C1_xXhcS&0`rIWGeG4gD%S?caA!+|y`R zxZ1LmGU9HcBhqcT^l&6pd@rlJAWw@iIQgt8D6X>y15cU>?fLZ3rD|ENcf_)11k(Gd z1Np_UcYCQ==D25lA`P|ByH?-*{me?dkI$<4W%SI;f&G_JAo8DcjTh|B-Sa zoH&6WIlikt-z+worR=}CJZ9lE>=^#P5Li%X{-9n4Y13oo*Se9}q4NsBpI$=W7lN*E>|nzau^TpT zsuz2!Xg$HlhW9TnhA-e-v7%QkFNPkUel@)Mo^J+UqbfG(ezJX8LZY9?UE@KCTqB!) z6n&$WrDmwZ9e#_R$HJa16fL@LfAvk?d57bTmTJA+dtE1|qL-uQKE3(!sUV5M&u{Kx zo?qU0*8bf0eBz7YzBqBymzuc4i(l&~lmAN2)COHKCE+76REQ%OV~+(PxCDriNL3C( zBp5GCdxgV!l;!@3N|~K2cT7JofoAraP=wma8@zh36E))l0rrFdFrxr5`O+c>A^8H- z2a6gcK6s;liioWRqNV-syh_oFrk9T-hNG^eDN0S36O{(DEopl)@sdnNl*Am2Rz_=@vIR%X z93~|~^qS(Sw5U^It!i{6?mpLAbVImxVy$Tnj8=MH3Py5QU{q$Nk*g2qofc)i;nr*WBkRx<(;{w%?at!Q@UVqow_k5Kk% zH0T=>rfm-KgQiuJ3Eik@a4XP=2udQ^nk(=bNj=A!{HE|Q3*10X{a6yo&g^?b6OLz^ zm#i%P^)dK&(J@bi(*$uTI`h8rETqVI+a!h9_zSDJl!BVJbo}A>P5Au83D#cLt95-+ zsi|XQ6fE=eYgEfCyktBBrnA;U<&Sa-POq3+s5>lf+hxc;ByWK$BkHV&FY{rC-t$)k zOnd%f($IPm$V>SCMf=L+KA>RVqSaL`^Yw6*A2T)Z?cTJ8O>mR<-`P%gzKL1O%PnTF z0fVz!x6OUjX$G}}X&pZ9K=odNnMAne7_c8O^SOT0UgqIZE7;xATd!s0LG zU*&lnF2tkv$EZUU!&Jcolf4ZX1opSC8HesBtsp2xmfGA<(xY$MpMnU#l>ZLlBM%OmyBk^vrd6I5#83$+`bks*UZTQ&lKOulDYt3%nx1AE=t2kEg_72<(E9Dois zL&<+IgGGw2U42|UlU5QCf3rXKP8RQdC?vYSCqdSEhz(px z5g2khNDq{?CZg}JzmuUO{SE79O+>Yusc(hy$VCQgSkSNM^qwQ&{skKE^E|~YE3lqN z2OGEwMVr>D-cwywm~`nn6sX)YsnepP0QX;IDo;DDYV6mV>izXG|Ce>Qu)DS^f=i_2 zD+W38^Ef`Dd$o*Xs-_-{Pr=3a`7w;uXftHMecHbTv9iWrwNyooUl-nsD7x$5{}t&5nn=sK5x9~Oo&+xy-4Y`#pQ}yfMwA^R_*=9 zbJwB(Nk<-2hVZ+tz=7QRJo9ZJ5zNWA0O?%yHv5w6 zN%hyZpaJDC{=)3MqbvXN={^k|l5xuodG|^zP?+Ck*J;RNp)Mnk48nWrS#MosKDlIw zTi5k>OV?hY48X`XEmpy9A6$mO5@ob-Q=%E_dKf|RRU#oro>6R<}>m0neeSr%w zb?Zi^Zei=17q+0mBwpVg?4A?AN4d-0A6|I>vb0m@EJqEd-NE=y=bAJxdCYYoHcdR{ zO?^(_=<_Q(8t#$W82L^LIvg#32H>NX&DmcF|bFQ@-CVLspHLN2W4S(7@v)^By( zpx{|{=bwob?WZDxDC+548NV=X*z?Sy#Y3l{J5V=7jlfxE&cKA{GR;wvk484Ss+|j& zQOd{V@_!fg{R|lg@*-XY^tj8b%e)139M;qLEWi4)P-L9mR$jU6k~!B;%Nvl3sWSEq zw|g0Q}PlARooTx>pzYk$6aTV+{@eyaU2$R z7C?mmrrF|L2+_*xMV)DVc(Qb=t9syrZ(Xeg*~ngPa_Vn?NG|%uz!|Kq!*g6*ueeM3 zAJn~vH=BRp_kG2PAR+c9R%`ECMPt@%6FTgov|6Kdp;TkX-fFMfo7#fdK@hWQw6?ZX zDJ@0o$@h1k^E}UepXVQV{)3#HoSf_Wd|vO@D?glTaOo$wb)|t;UL(!XUO4)wg)yfz5G?pwZ0OD3hp$2N7>Y8d zriX8+L9d&s1L38Z^=*HK)}Z%q16v{q z_tKZXU_hiGzU`OAzyp?6bWDrCu%RkEh>pGw9fxL4xEr#^&hhu%YyMSH+Er@iRoOBx z==*yAj7H`*W@xn%>@9^roq`rG;T=g*DGQ80S~9rD_lWzR`RR{ z-mH!*oDL^uX7b@`5q1|OcUNoxxw>e8VAV%Uze;DAC0CMfJh3cFi%(SnY_mx68>9)eEc zj6e1v3_2huxLC&|V{Q^-L@y^hD6)b*w!Bc*IY}DylR+nl+gkU3E{jR=0&uETUvzOD zNGFKy!A~w@C&qS1ZVfM*5vCB*eV*&grc|pUWe#r33M|Hge3Th-+Ch|Uj(m@t_|8Fm z1wcGWEIz>;HqQzEdmS!R7|ms#tn8Ppe8EKrFHg2_P1gFDj2uqZ`ID^6m7+(R=)eTN zsAHTt5d1pND5O9wC!W}40n_&8XIF#o$xG``rrQ5Wb>K>KQcEMhgFkr0x-H0k2IBti z4Q?+>QlpLvwSYauP*_?SQF%lCeA5EB(%RPEI{kU;AfA5DDBV6%;A~&K$dPZTjPKPj zWt2{8)&10ZK^7}`3#pXK8lFdfd|AhGIZm`@R7Y-?$UV5Q&(+T#Y;PnF16zm z9-DJ(kirVQ-0iosKmfI8q;$V`taSmaSYr-GNbFlWG;b;{77fe&^+tc1v2mW_2ZCjg ziBZP!?R8h(A8G8pjy^ml$yUb@=cHtL51 zWAQ%MpOw=4kg`1Ct3NN)%0?_haI{5KQ<_rFdK{^YVUHQ}=Ccya%V#;>SU*FDo^lDL zmg%pT=RG!8RxfKpRv5cf&`cZezYWc@t~7FCjDK8N%58X|RC&d*5?_H%|5nk|UYW2_ zsl-_|5>?sXUOp(HMNpR-si^9!C~t39D0`Kmc5tg^s`~0|bt1R>nsvqcY4xV{-A@bE z#ENoxgYbc*YFw1gthMXrm0~gTQqT9-3>s@RI51D1$(}yeJAC!XR-H2a%CAGY?yBFo4ut7(9>$#S$w>{ioV`esuTu^T4MjyvM_qMO%+n?Lq6vo|(* z*&yw&w)|Rec5`b96>fR8bM?hyOI1h+2l~)25TO|)$68z%-gc*#pBP~ZV9y&MhoTIv{Ny+m)Qsub+jLOx7V2PSMYSKO|~~K z^49rx49R!2FLF08cBGLnWv+7JuHxPtbPVor^k(5+qjAJ&cETC%VLh(Kgptyb4$}i^ zM$x7?(AAJSiZ0-QCme{ubYdLonh|s;b)+*({f0 zdZc;#g_wFT+x8nQ!F6MLOtP6JaeXT1{UV?~Bh!IP=sx9`0ny3+^PNs(;sCW{j~?%! zlPTOjyZb@FAZ1YhUE-i=Ri7TQ&kF}f+YY`U!tY28xCIPa#|-&Z!5>u(zLpxiX4)Sl zMR9mGIKOQ54vLBlcbqagfnhUsW)z(}+E2tH;cf=D2nxT1Ia+hh7Gd5Oc& z!696Kx5hvnaWuztEK_RaSF`q3a0PCx%N@VSJ4P-fzlV;Lkhh=bqqVkU8`+w6YQa5yY9mSOQVOp6KyzR{1UNjcjQ+#VcM1yL>$d^AJ?oJThky7R}p7%ct*`} zd8vWsnDO)MF{Ye}%m5O94q;Ae@~?YeA9V6x%p?mRDU?W3#f{6v_7QCdFJCN=O-S{X zX^aUk~zj=wWv9#gkH zCRB1}%&Mo&&3g65X52NV2YKfNa5Judds<^=`?IG)P3N3;Njx6IRGqVa0W%_FlbWx` zxL`9%f2TRVe`pRMwc|!#$9~W?n+<;5OP@nN5uc@q9Vsjj`2}!)JP^|jtIRY0 zLo~JXcGj787RRExSZ8Mr~)4Ffd#%xnoZBr7r|Ltu5qyI7``DM!F%fyA-mx<^v#L6$k(J#Y0 zUxw+w4oZFV4xs5dXN`wM;$!~ z^NrfR>>C2!ihwr&v>@aTXyw}!X{B}V8@(W`&wkavf?==*e&nz_wE`XSqL+-@A@D<~ z1nEoofdW-BH)^MbVV455CmXjz;|-&5+yRjoI^^~#@2!pAU?{MMZ+zOFk~lzyfMVZeow(0`!Bzky@o@PwLHq;2Zb|>Dwv;^xOVV zus3XD<@-^>E_i~5LLR0Yx1-a2C@8-}SpXFg*lg8;-JCeQeUovdjvlwN2U>xe#qB`z z;5DE2s0yIG0=pJZey#e!77#zB^WY!wzo^KWu1Pva&+js_aP@2O+lM< zVW`cpOz4g$d;{|xgn)fOob1^Dq6|8=8$W(pdst)t`(F(V+RY#<3wt65uluyo1RPC~ zen6ivJQMiy0r7|8;HT9+cw^V^M>Rk7x_`bA08C|>mAW_c;JH(%v-h&_q-(qRd2km8 zcwY?-D1o*DwLN;{XD#CiRQ7~UoBqv3KHLueH$v;YP3EYxn?+gRZxU&H_9jEF>`xtm zv+0Cg*&lzPiT|h)PgZM1fG6h*7$_hpjl{T7(y)s>M6K$Cv_iX#djGe?G4FQ}WyyHH za@dxkf>bLhn;bWxpt2}?oSzH4Q2*4Q@n7PY?l9H3(g2(9=HdWYxvmqWIs?CFqY zMt~`ZP8_#jv2&-!?s6bh995}S47D<=QkP5Bu>v{23gfw3GZ2s$EW}sdgct=npj}P` z75qY2g>z?4mZkUIIvtLr=`?u8e0ERZ->LL(%noH~&`JfI<A_4Vd5=qy67-mlLZi)~r!@PoU!T0( z(+av|GbGohpEQ+j-yd+tDWhjz)=tQMKk4`0uj?E)1AlV=j2!vc*h`R&sz8-7o5@Xv zYW1(ZuhnifWua|KxixB-v1ni%rw~%4Xqa}lLh%b7&Gn@k`JzFKvZ|mM3z-485^oRP zNQZ;_`Ik;OzcBY0Zg|T;284_T*or4fg~9oX5U#KXR%OsMkv1x0vHG2Q<3S|zH=SUS z!kDty^EG`u@aZI2GfV*_!>m;8{H(G)cqCfzQ35YvRQ7LD7+hVVfvQ#cVq-YhI+$5( z5ZL8)y~uI%{3CoN4ExwyNM$hp3E~=PfVFgO&6K$~?j_T+{3?Y4mx5yj{ib&+@0Diq z4WAf!Bc!>0(q9S_3fg3|227ehWN~LTy}L$n@@_D4(1B2F^ubQm~ zc0tB`ocD-j>6O{NVw^hmJg#Y|YW=rDEcBTMZIAMGpCjCq7ZQg>rw2YDAWe@_^Mx)q zd@p%+IM5;=*-MYGjLa6_vIrKKQ?U^g=5w77`{y7G+!t?<8nU3YWM6yE^IlO+Q01#j zfs+(8|8ukm6W8b0@(rpOmrV5|M3j&)nm>J=~s z?Y$r;P86N)uZO(?k@8d6Bwpk{a4g`yoz&6v4fny}@66m&8kw_+jAy4Doh{`5fj!fS zIS5jbBgtSG_)>KH$MfUc^Fqxu-}Je@Q0W+C5JcOdo(V1)VeWm^O7-s+Pg4UBJzTv~ zKgQ5G9XFy{?a(H@-Hk1_&u(tpy5^*mpS@UMoKW75{lp3JUE<(gMzqNC5PmNEyPFbX zturj14pUFrWpK+cx*Sbb-uL=*YJL~{BG+LuG)?CdC*|8UHB&9XM5b-VfA8e?UlNB6 z&LBUAD^ufnSm1n+z$98g*t=ahC)3^@ENoaN5v3v z5qPGZ^7a!lx<;DHXW+i!NMH~YWJI1ke{%>y+`1M+qA=1>#J)V)zY>Bseg<-I1hf6@ z<9rzr81d9zzYY$Vv6=`5VtWLFK`ffMAlSRnPqM*1Jwo7z;jkI332ShSy{ZUsoix8f zaMf_h-g#ub;}nSjm0lO5(PvG}2E*1uVyGysL~XIu(vjt^Va_6Df)KTD%?aMr4lI%y98KUtI%jY9 z6jAH^G!a(JZLNM7h(t+L<^=2;69s2HaYkBPPtEFrN0FQ&-YKVPIFf5ff~|_<9N69sIi}MQBn~iH*5Jg(Lzz zP%;$lxiirPkxu}*-nqW{lr*vYM5r3CBRIbwp;I?R*Duk>kZ!2zQ{z>%aApD^1gBdA zSPN=i#jH4B!h}(vIOfD9nG-J==f-tW$}Db+b)oTzg9gMP7o?Sf6m5xRssvAlbYixZ zUqKmidp8O!H`i{3ok#OVXBn>LmL!n$8Mq=u-JhQ`U+Gl1WE1{4@xq#exoWX!gFCL$ z5J`PvfwOZekKLrZ$6~F5vd1PHI&#R;PRUx=g)+Xv_cC+!T9O`zRe`^{NZlxm$z0wN zN$n)?yh?0Hsn?6aI7*4Q+Sp_V%($>jhTFW=j_W7)%PUQW!+;dJ1#72rWyif*_7mHX zvN6Ohu|DxauCZ)=17TD8+6woFOxCSefR=m;wyDQ)SqH}`m1%=My;P2;OGLy-e&i){ zbYzp1N*Djv<+M9rBP~@!L@XV21^1D$z;j{X6W#zAuTOA=3j>o01RRB2?M1V^huQU#Qo52AT?Y-8p>6o3qekVzL(iBE~TLML(rwRyqXM5%Y2 zca#Ypo-a2gX)vRf%?&}Fw$U;^DJB2ZcXW`C;I2|?!(SmodcC0S=PA0p-v7c?!M!jo zo(--sIYUJ%5BPmKVF2?WydW0jdY@C5vkw9k#md9)L+^8TVH!2{I|`+ZL=5%}BXU!D z0q@XPf?fvlzuNtI20b$Pq8*-4;rdL*S1uJ)yBOH8g#mt;+||cPl7Cu zic&S9))61d|Ag+jFBN=4=e2+6WxuY{a1iT$^l={J8D1q2U}JlaYJuy(>!$tkuHoH< zWn#EWN00bI<%_UI%3*_u7f;>qu$=aQRNvRyEp-sQJGi!ItizAL>%tzZE`3=GOP&Z5KGMDRT3Dcokwi1~JcM=m z8>gC>Cy&U{1K+wu=Uf_EK$e+1xHZXZm$};>rm=@((7i>Jq+7 zB;g$Qy!`wYDPF4vi zLK=y<8=Ajj^6rx#<}xBzsD0CZ&>~Rhr(xKOX=S5;4RiCZWOy0onDwiM!N0kN0oT7L z;Df(Qn*Yvq2S2s+G2(BPy)laP5aAU2{LfYW%}G!{foJt5^pZ>bKZz^P{_buko=QXC z@VDK=d#gzP{`zCy+4o;c6jk?M8|c~DwF4&P6snt&H}OFQ4JaA1DMrs?f%l?_dL`B! zh2`*ReNTH-rq+Or_TqoZDbKJ=YkG=&IA0uX87|(T%uJ*O+k!s;YGLUd4$peB<+MXw z-*WM?C|iaz;d(fZ@PD#Ye?oK?Dd_wSIr(p49eX0!HF_(vghl%!y|FrGM!lk@Ws;^b z4+?v4toOFzMI`z=<(6n=sbmyc`=oB^UJM}n(!~3ecd_!e;Um$yYALxLAaafqA?>5tmiaod;X3rMN^ z*dN2$Ctj&`lS|(tt)u7!Sm9_5o#KhVuQ9UJ;fXIPpfVtqw@NSHv^;6+5a{ z5h|S~3yASXv8{-~>x^DoC06~XY&g}3L$^UI_d&&t0h*!&_ka$OY#Mzi`^urg!x>#@ z5hN?5U;ep53ZV8kSy$FJCkok?qMdY&Ti=}skqx?j<*3(J?7Ec3kVkrKvK(F1S5eKV zArD)ujo!f1nV~Rb`kbL*LL}b>d43jas7BOAD8>-fty*6#QeTQJS0)nn9ecTkuPgV{ zT2aIhgZh)H`chcvVP6T#GecUokaSMI$KJ3ojs6(Dh^|7YNKlq^yOBo!psh1Z9Swd( z$_cW3k4_nOt>BSBB=BQu#W*1)L9!wQP`vYSlo({#7?S!lL^Bbqo*$CO1yO(iCz;5M zqJni!Y{4yvj$C=vNpaB1h}gLyjx#q5ZxXjMav25TgY+glho|U9gnpqm0cruvXwV8p zw-TgnL&rUv#?>_gaE6qnU?t#*k=P)>HwZukNfwP3k^xUSnwMTtZYN>JK_+8M{qahW zc_{GGEB7*%;$q2kV9vBsoTW229W%x|+M)pISHjjo0VdSghBJg60_;?QE<2co<04rg zfTUP3;6N!cPaZRby8z*Se&7%+jc80n0783tx8R3+u&||;ax@qrrTiO;@$sd3voT&x zi;09{{O~lF-$(cXgs_u|7q&P41D@5w+$^u2FRWn<$v(5aaCuINPM5 z$Rx9V2a7)X#YYm`vOe1jbdTF4XD5oW82u#+%{@TkNuA(JmbCe`PIIJ(x%RTTPOQ1^Uvs@`bA3Jw zgE8~#nihuN&5i6VjA0fguPscaEzEK(ZkSozl)kS1%Rr6qHp;^S{ma07%)r9#_N`cp z+hYcIIt{Em46MlvN6u}_Y75R^lLDKw=1sSq`fuCK%-X=_?(p5QlbW;CxZ`9tXZ`E8 zfXCdefIAOj=WOlfEUV^Hv*!fI?%bn={O{Y62cZ8CkOjWl^?0bFK<9R~HRd(s;?Yu> zJia>|@qdFX7XPy?F$o$oT-1!$@p~X&q4A3+LjnMmYKwqmE>DS1=GYAOYhy9 zjyMpWsN{?NpKZy9THWKYte;BX{*#O&W5wW-ck0O7k{pw}Zsx4g65##qn=4lv(B6BC zMkJ4A^0q|M9v4m%cQu%v-y-VWf;3lIvp8v&Xt{gSsIn#Qf5i5toexyx zdK~(rlg@uci$yh8^N-K?%}+giTMdh-hx~_oShd!}ZBj@f#{K+Ty`mWEcK1Ts{i7c% zeaRQL#&*AceI4z1$TrcXNs?owVoiVI5EyhyaX?chiy6wf&qA$=HtJt3;(j`EP-1^` z@5+}IBR`A-21E%3@MK3BfI;$r9SV?~PMk=(;;Oj>tv*u82amSz&Ac}m2gTNP{8aN- zV};14_cX;P(^)#F*l>#fb|e&xWu5a&F{a~|QL!p7%cf{%($h&=C{-}mZR&ysum`8d zu~V|My5$Wx+IV;h^r)nR_-0~>Hh)U`_BB5_z*U>(pc>gHQB=LpFO1)4w-4*$!N-@>&Mi~h0hq4u2fW%Y0o{RFii&U6jAbcX%>30_m;s&I$uZeTQYUs3suq417F-8 zN*BBeYLmBmb-}iy6TT9B{RZ`o*F|RyKrPR1i^ta~$?Z$fh+fcEW)@!yNfJ1#ezF_SNAHHVYeYbG(cB zq7^rj;AaqON8?x4pK!Dubyo_)US9^kL^l~Jx@*h!E?tN3mz-#C-H_a_Bm8xdH>Z^; zmO~aY82Q&D#+k|npzhTXkSP-AC50i99T}Cu`2v3o!x1kE7<7f4<4%Qz_zxjhL|$%- zU~d&6v>ge77^lS0=SAA2wpkhcG2~sfgQ9jsA zOo!t!DGYk}U_hxv6E{q7wq)hR8-fk4WKPCVID(acM~1QslSxlmIlIy+8BZOiV%r;w zw-CTaJ2dJd@AX`H|Zw(n_UZaSyZM$ZW&YCf1;p9@ZO==bGDpReQx&+HM)Q)KRyjldJ4uZCs9PMr2@y{8!mhM?;uLw!o z>8PKGK1u8;>M7C8{7T9nBt)43RRDtH+wrQNz|VuYy{E@~Lnr2(Q-TR!82WLW-}kPP zMn4_4x8Qy(dj>4he?BFD(4)@Uz{Ance@;2NFP5KR&gfSt=;!fNT6MuJ#FY~T5hxf0 zP?)V5S>1S^m`$YdgB6C->kp&A=vr*gPVHmYbir@cB`bR?!NI`FEz#j3G3AVTN%i2g zFeQRA171#=^-=$_CSxd%kP{ot9s|o3900qSKDInbTP&*3Xk1)X;==G;1ON2ft8--a z`9OHu(Ra;M4G!=k_!L=(waO+L-RFfb;wZ|mEAGla4AG!)zJi1#gv8_sviuo!V8}{O z&K3lUFugWP*awqW6Fj6aj(6t{b6b{N!dTTv4lIY)80;RvzAFq0i-QO$h_6P+Tq17= zkEWIQV8MEk!@Axe0(V`kx!cEksW%KOZg(mixo%8{DJ#l5!4v>M=Y#(xZ%>^hC;Kzg zY3?BJx+_#}c?51}>E>V6rO9qKSI-{t8rhaUaR%qP>(0EdX==VM<@|v1bWw8AXfVb7 z{hho}iD2>TGR9~+MGTZ-M@FIe;@s2sUd&|()kn~XN7Cz*URrakZ@&pT+G$8|)Sm&_ zfwuDsv5C2CD$`8)God?iSJ>mx#Zw)bX)3Q^k*fog$4`eeW$G$9Jr*9RBjMpNW^Fmj zO~6oBTuVDPih~E>5Fm_77av$W%l@i#P4%Y2%OjpE2#6m->6Y7SDD!^$j>?)PH`Mni zO*ZGN{9C`7+u^Ct^EtVpp(VFwk;=MFi_uRv$ z7yVG|0oGS4m-AV$M(YaTJdDa+seJf)C&b~TFROsPZQelbXFVfnJrMEk@~8FdyJs_$ zS|f_Ilv`t>Pi*-i7vn3OO)3Hm23mi#-yZ3WFD8z^Qau8xVFbV1#gg#-` zDaP&X4L)ffcz_T5%~0U??ZEF&l2VgzxRWH#^6ia$;JAnIorjMUBQVp27|9+??{Ca9 z8wM+siy(A;|v5mnN~0 zJw-?I^Ex&j;_UDRbGpx1jD)fb0(EPV<*n>P@F*D{Oc8|7Cy`@zh3`#I?&wJ5Wwk(V8|DXy2TmOGszh*$XUEDDp43SS;S3tZ801&PPH;N zIRLC)V06&stB!GgLEbBzd#nw2*huj`b!<0xX-kd=MF0G~{-49Xdw@|e63&&dg5LLuW5 z&@r1QqN;GNY$nE71!}Z>l7?fPsu%RDgI|MDZq6iQ-w6YFis?lmt9ejdWI?9!Bt@Dz zA7v)bY(n0t(cAMju9!8khNP$*OYxdShDC>hgkW}6IdR>o=B*;eLI&)YiDvz+3fRXsJs@NdPxT;Av^~q|Y;>k`Oxfe-{=JvW2Ay+~xl5WxD9H z*e_)og5{YKWho16X_?6M3Z^XeikxS2iIS+QeXKj+TsqlPPFN@>0TJ){j-%+|JnYBEP zwdbeT{+-sYveZ%VXj0kK;h)t(&eZ8T>hj39pgd}Dp86ogdR874cK>>Z^2SwrO^dY;w(Ne%#S)_O#h^RK$^|g^{A=Igjv5{}u*?mRF1Xev2)Eqb(SE{@|;v zpATBXOs?que<>?bY(_MQ2?3 z{_WY0?G+vE<%{i+2kmu>C2y~G6iaqAU*%}c>Ui4Ij@v2jIP18_gzI&y>9@hHMuiea zxhqMy@ebVhDsFz9=&_f_uT}QgB=+!Ev9a*>+JbsTOj&tN@t37og>k)N?!7YSEYiGv z+KIhN#9sCQvP7#-{hXP1sZZ;m56Rmvr_nDV*l&PiHq7q7PPU52Fe{U-;=BFkw#*u~ z10vo7me~W=xBQ4r9oCiRnn1`-mI4A-6P~xjRx09j&h#aV3s;#*Dm|8f|eO?Wh`kP8@BD z87-9}cJ7W=ni2<=@P)V`JTGxDV!`Uqx&rbhYC=0A~Ot*+`KnJxEAX zl4T5uc8sK6MY_F9Vw9d#f=-&7PO`;L%D7M7teWKcK6#lq39818N=+HLPtll7{ew=4 z#7yZDr=(%i{JT@Ii|VOp(`n6^X%>&^@TzH*-D$3|=@96QynCa8`;2bP46epJR=gW2%~CAkNY6&Ox9b zsHHxDOh5c}`*0fl;kfd{(ddVRoe$sX=f6tMZ<)-myUl-&o?oh*pC6r{*_kKNe;k$k zNHF<0;P$aM`eS$HN8ISgww;g7^b7AL7wSwFs@)bUqRC>vg`&}gf}Mq2`o%2C#dMR! zRJX;X=*9TT#hB5>$eqP-`lS%bC5*|^YqzCW(Mvv+OV3A_ymyv7>6hIkmt9SkUEG$P zqL=SgF58YSTV3od-=Y6xA^8bq^2yBYlX3K?>y@AMB%MwG7$_h5xhnoJ);+cq_DlK^ zImtOL2Oq&e|HQsK1YlG7&>lF@0S6l7=mCb6(IvY>{IhNZJk5cY%y>`;e*Wn}fOkQ8 z$Oy;&>g%Odp*Z*m0!C&crclsUxqFYAQF|^(t336S4wXf4SFRdZtHa*d;_sgB?vo0z+L` zW4;9P12O!}xc#rxdjpy^u-ZU4!RwoG9Q27j`4dB{$G5d=;6KN{mDOy664pVO-Rn79 zS~nPw{5yz$n^Zl!)Y|k$OY7Nt+ikh4R0Xi?xHXy@nx}EAAOx*>%$Mvy_=lC14+z*A zKY;wSM;)}cb7MDK>w9hBE~Vh!Nj1#22Kq|wiw$w_BxfVq9)7_8gQDl_Z%??M{niA- z`q8Jo7xv$TgP`;OcDLc{pJm{IHEVEzFW`c2PywK#hAwk|=2VNUq1YF@(E34FKpU11 zzXu1TyJrKm+&?j}s?{E<+?%}~2)o8`DAfH8cCmlN&#Ze5{suKG=Xu0*u|HC`It|}5 zV`N^Cf!}xdY6bfqdjoDgzV$M2OS@~As)x>;AMo6t?camm7B~dg|DdX;ya(s<}u%>*`-gU%|LGWzoBiw(=}ZDiL^UC)cR(V_mg6hE-N1vle;nC zb#!U+52YY|j=X_ zrgsTc+_%1<3iV_8^+zT*a4ynT2H95o+{8z$P1Pxvm_F)RzXIPm;6_-K6uFG$>Sx{Y zuuc}M1Y_Df*OXjT6z_}~%awk@KB1$=i-;!`nIutg+GklFI1R?e%h+x0R*yuEKo&MR zrSLLVR6Ec8SPrI&fpYmv2Dby9!gcD~47`&agbKGK>N!){4uDyIumId>Iz z(+f_}Wx6hcZuQv`d{A+!@D!}`TuBG4L#JX=tH<+X#;d2IX7xvA6(=u&H;%AYiGX_R zDHyG!1#gK*7OmD6mS|O=jU;PrV}~Pu_Zjl6saG(Y$Pe9$87_llniX~nIrYT@^Q~Vv z#wZd7n1y`&!b~-f19tTu#NGc&45CvL6?z!;=iowE=ft@You5u+ZWbKMTUNYHC0#}v zsnpYpzIjc0c%oc&YB1Z}M0Bs!B%tg|#HFs*xN!~b;-#>krOv>u1bAMvrh}AEXLf`{lm~`B=I6 z_Kg0)B5@r-PL97%0Noe zb0O!z1GR5GvNvIyl~YCK`3g>I4T#idafXVeqlYiwkIOymB>GaKvV|;vKE~zmeA>5C zv_4Yr%y+V(;g?RKw7h)xD}|U|QXSao9gT7d6CqyVACUF1)SFhzzsWPKQ#CI5^+}rR zRaoq22Y+qwZcrxYeZTLYRiga28?Ai&E~=HEG$E*lpdZGUFdiq|;PlA1q z5RTN6w|e*&sWH(v`U{#ppT=$@O}PSm*+(hzxwIO0?m5x}>=h0fw84{cH*uD`Qb{aF z<%vR_oP@@a_x;&R-{T^ncm~*AUhL+NH*UClfaL+$%+er1jn+zT>()EV*&r3Hh$9hV zp31iLM^8eFM6~^`>o4eeht1Cl%-2OCUPi&5oM;2qR&ZhP&nPOj z2T~EghONTo;|oKKed7R1Ne9pkj*Hd1az}L?!6eG$)O91p9A8Nse)IZE$E@0KE&{>u zLUIS@W4ly{x=@>WwkVG60jD#=ZF9W`Fy{=HFFmy{tK20CUx*w(GPD`RrGR5c8@<9? zsV#o)tZp`QQ~k}O`ARm~*FoOG}MM9ip9#@8h_S~PipqUV%L(U<+ zac#Iy>wScHo2PtQ0r?IlpA&>7zU-;A+e>soE=_;O=mrhbnSV5z-3Ej`uORnw(P=bs2_ktju`^McSiGFI5Mh#4k1@q|>Im&m4#*ee#!L7xj3|qZonth~f<1@#-Cus3P;isI7NE34n7<>2wSY}<4{GYB@T?*F*Z8K#Wb zwQ}p&4UIMWjVv=uu=81TPP-A?+~nc;WXMFJ%HFieVs!7>wf7z>j=FV`YxIv@v$*R@ zT1xLdY`Oq&tJROh$zPWiqwCW4<3Dl7?QDT{PwpCjc5(dO5BvQkc;jqE-&_Jw^MdTK!r-7#1i*Z`Eo;4JAqpcaFC71;DUBIcV{l92imtr*Z_HtK>8YMZca%QB zg|Q6C7C~5QPpSkSk$-_}LbNS2F9MH>?r(TlKUo`RNl%o(Xht|)eDWU~N7X!|QhaB3 z^_;|i95$Y_w`NOsMb7{D!PZ}CaUAi(pSTGY^nLCnwSaKEo4F z#kW;e-;5s>jI?-)(=fc!3(!h<=GAui_AKD-9sl_0<5RwabeUcE!l$Wq?D%SqY@;=K zhDz{-n(!{f>#eu!mF4RkVZ~Jh*=IrVtK0v6ZQ`r`N-+P~x~a(zeCjax_cV^}Zr;fR zPM2K+D^HuepR{`wKWu{BZHTPZ?E;H*Q_X}^#L$I%N0AEfKtKfH3;*wq%+z_ltQ};O z3G(@gOb4m-n`+NX#YjewalI-obx>oCs8UKqF#SqMZ?$6NSBex{D<&V`UMZ?n0ao2@-Ck+IcM3)60va?I zZoVpiQGHiTk(jI zx$5y`t9Z1g7#HY7c@-Jt^<{xap1k#hz6U2(gW7@*3$VCk*)nFj{3}tFU5%t4MV($|#hfIszNAe?7=HNsqTU(wE`l2`}Utr)0Dj zAqZ<2ITLpq7nzk&8?TDZLtuFUqlyAUH{`Wv@Fa(X(AZr9fS`;Q!D4KOzXScg4&eYP zoyCUcQWQl>HkmR3SPVyUhz!9+5*1D~&j77Q5b%5Pj(F!0=OO}DE`mdw#`qxeGJd3r z2roS!IpLwDM2xO@jp$23-a#=OoRH#vfH@uOoE!v*1&dmaes&#=A@eAz!8Zyhl=CTq zEx`_!VA^+WdLt14A;R~|XyeBbEFoS-HCRN|G}0kFP`D-7p@xuc+FWJ&kG3ZWPvf@| z0bt3k+8S&EadLy9)LF*gmu51>;NwO@_sp1?)YvE1fs4;nH$+y)Rz(umlx}#kj&Fnx zEjiyB2iG$GiA4)fKr6!Kt8IPQA zrV+=FkH&wcOq3K&oQjN{^iTZ8P5eEA9Uo0deVqWG$CT3 zH{$<{yA8!t6$Jf1hSNy-JUoxo{gG^=_vElW(=@*Sf5qKGn2DmKaMC-&WC=TN^k?Wh zQ?gFQxM{1L?e>3$(<|%aHRQ1UthFR23Sbzjup4DBgRvG|!=9?6IsyyrqT2#TOgs&B1kINyOTdPYc^Fa6@kP`IUFto;f)a|1ZSDxmVnLy;g5 zc&1#;T&_^mSQMnHlAyRF@(!v%ASFXJ-7?wnPbioY#LA-6My4UPZ7ti#kunybc)0Px z0;&l@2*W)}wlZ%ySy8PBylK8=9A8I~nACr-JF#M?L1meggRErNGXjc8$whT8a+Tk2 zBJytsYX`GG+fW~HZ~xw=+9T5U9wM$=6G9=%h0moebgMO14sdZv8`q;b{ehQU zmJ5M!QIRr{FoUKzvZPDWa3Y0lwQA{^sDa+dQG>AT?Cv~edJbGu2q+tV& zoKcvBR5cu|vN7kOo!WYLn8~WtBLU9rfe5C9L>t0+J_c6&UY@D&=%*1H1ioyGw_l-~#G$A-Xb@++QRem2Q$ivu>z_fYB<}K*A!WaPCK0NB z3*ULn6n>K zsugbv#U_P)-l?09YB4#+Ve$eUuL|E7Rc^A%&|S6~JT5^e!7uMp+;I zr&BRdAsbF#9lb-q$_=j@PbFm@6^WUZ8{Zw7N^3tVmWwSneP}$Lxo}jXI#zzeXJk6} z^r#dGt3X8<&lGb1Dl;^zFn>ETQ=9QA*(_Lf0yMsFWxAV_d8ZUu^4ffg?gf#Pk^ z7I!I7+?|9F2<~n{iWRp)vEW{`Sc}sFEiTQ{|GV$L@9xab?1%l#OqjW!Jm;L;=XYNh zyz*7K`h2DFd8Ofa<(rm~`I-mZvpG?f;gI^*hIjhRnDSAtE_C5muYgoYq>31((8J{G zX^jsNfI@yB#(g5kGh{wUS0=Zp!(heiCG+?lwZ_QjCpM6O=DH`af9AS||CsCQ69)XB z)#mlf19aSDbXaVdH&1x+p9bK*ip0Rp@H(`6L7?7`{tK*!Vyjyl@GbzZ`j|2OV$4Kf zChP*b^?BPrOo_r{#Q-)$(mlP5ZYBsTwMV$~dq?hgNvnDuwVb!&gVx_-5h1OSxP>}S zey9E;LRbL&gO9_qabcK80t+k}k(l^j+z6xUT2lV*32Of;SQoPQX-0zvXiE;wrfey& zXJt<865Mep3m&&%Tkt*Oq_@CAM|>f5J@MAvUki^6$7SRSjV00ngw-t$@DqmuxDfAJ zmuYH9xa(ZVs?BjYe|)Z3J(Mm1lw%MA04g{=Ihb`n*hs9kn7OcBD2fs+=2}{ChmV7? zJJ-mn8W@yh83djL#)d{}PPVjSH`qrY}HV^_%xN=aAm zX-PJ>(<090^jNkF)@a$H}%SsjpCSDQRO`WZoxyQ6gZlt+W@)8UC!8 zXp^_SXr~-AEBf;j|6b=&sO_vB82!CA|31X|#dPIr5MXM8JmIXxiTSFeC8UEPf zp8e_S_%r|_mH_rd96nXT$)OM&l>cM3FvKGw;d)QRU?4dpbZu9v=@Xe-iy`5OJ>G|K zdXN_*ME!soAksrN9&PZ;$4)*pfD09d+ZtZ*LkfT(rnPX%qr##=MZReDMk--o7lzPS zMERb3B{Vx>A%nP)QI(Ov@83OMLtN2_K=n6~vaM0k>FPdp!hpKS_j?x80M3NwKrcwN z7Balj6PFfc4KNQ65;tK%_jts{xN7fO(1Bvoe4!Z`(5zNy<AL3R*xDo7wtL1w~M7 zO{+sp`X8LC-c+m>APl4u&H;)^=8A32fVH>6Iu~KxS1|8%(oz%zv(TEmk<D7{N5G3q*W;p2?5B( z;3o#!>fo2MK=PFdZE*t^Pv9)xxci8B04)Mj0)b_O!0|(1w#94AMI_)PfD!|{-UOHS z_$1(fa0=n`;-u?TfORo=uQDn9a3Y;V60=d#V}~UA%p`WdB)*CyuC^qBr6eJVWI?0k zrw+-&4=EH;zhvo(WbwBD5LMceNOWU0&SL6M?U@T=Nv`A7A0_77;P91OV`3#O(g5z& zqCoDc<&lxlFCMs4AWb9uGF(7cv*Gp$M8Cq?U59iTl1lZ)(u5XX)oA!!JXIIR6ie45 zzlT)Y!O0v4;xwH0#xK<@GYb6D3a z3dp|Vvc)k^G_Ff?-^grjGs9FTxHIyld5Kc^56Ui-tsPse@EAvXkSfk~E+Eu24}ntch) zp9Vvx5xDI*IgMo`b!{Z48)|Uq%IZw$vDKTfW8M4R56`Ws4X&6ie;1_c9ERB*Gi99|jL0=Q+L>W%flmPt+yGh;n zr*O+&ml(H$5gbO}RgC)6-a?Yi z6`XPUfN>4B$*{MX9TGZyRr1n1?EzNAq+@X0Q${G~ig0w!TK-3PrJyraIRJOeV|om{ z`?8HByKv9rg4_BR6)%gH(*dyEDq=V+FoaAW0#`|rRe4x%XI`7GDBCY$7o_?^XRoTr zj4HWlaUY^qnO=@CW&7p_ube-4Q|#R+w)L@)(SEAWA|3oj2$@zP#LYvxFGqBM?}@@G z%Y_zzRLw4;f`Nr*`=#k8BhE9v<~HC;?h%=Jmbw;6li+B~6S2b1Ht>8M4y}3!u+Tiy z%jzM5!YobUPi+Bh0!L73~C*LuWL3`s??^n~U;F8+fGp*#L+88NF zH7c1jsz@~sAqW^ZFp{4+$oCK_jao=OGr5P)Zx|@7d=l$0e0^Ih9NQ$V@d=BUl!YFLBfG_)z(DA>Qs19&AJAGW>Bbp=o22}S z>8q86dDE^V_#sba&|HIjWA5Hew(r)~PD_#{Rd~8VK1D;aZ*Ft3ZE=H*jp^N#nNs8Q zq>XLI*6j_&)Z&|4Ns}5Ww^teUS)xihfEt}$qdE1rqNl_KhX&KeMBStH;(*q%Veq|9 z)v-_$TFx=4)adKT!)M|r&0|jTTFi8q&7UNgqW8gHE)4nyD-$Z6bu!4OP(*!ioHJvc zop7oSGCDRN0ls@1VVJwVI3<37wr+hzzSVGcwJBahf;E1;{}-JCymbE75;rmtH z*bd;o2Ehdo#5Salf3>0z)%Rns@9zRkK{{S(HAp3}PiU<7g=q`JX5y;IfTzSjZX2mg zPCw|X|F$Z=l^#5Z-77>*X;eLcd^V_xk&9jZMN^WBI|rO$NVSOqGgeZqqLOm4JRX2) zg|GS^1_?tMQ2!z*|CiVv-HD1@MaAEt5Dddf(!(jH!)bxT8F8=bvxal3X@XaWZC-U1 zNRO15j+6zCAah14J4YTkDK&Q^bqu2o(xZ*0qyHtgZ|@xKTpjJc8-2)}e32gOHys-c zd_by@*C58mjb;Z{4G6sW;%KC;Bm{Dyy=|0Tb=xSHwj>z!jzf9dOL*^GzH3?!ta_Q z{5C~=KSjzoO<9WPWu+}O$9?5VT*5Mq)j*OsJk7#5^H^qv{q4+?pc$^*8J?~gzHc)E z_cIUbwx=?)qC_q#_XQ;FM%wNx8W4afNV zZ%(IJG3>$ka;?@-GHk_KjwJMQW>$$8LT4&jG?a}4uyr-%dnvFB0uc^m?0-Qjthv{(yI~Ar6mJ?Hr?^K;k;C&!@-b&bXYx#QZpv_4qCjySCcd4hH)2EBqzUilX`@VS z38LJo6vSvYHs!dhk<1Ek7Nj{q?J)<{>tdrNN@D&3uQ90!hgMQe&`)Hk91h=a4n-|? zF0;(HKO^uRrSGv`WswdzEGi5-N0Txz60_*w5bdau3*%f>Sib!$`YaA+|1fV;9vgf% zAumlh7n3Garc;rVZi~(`2i89E;o*^svPjgxbl;vMeVk$`=`CO*Yt@yM&`2^xr<|6rOD24ko>huRc}&Ue&(G zO<4=33>5#>5^$brPIu`&`b!`CECZu0KlQssAng(CO6jNTJFkt;B~pFub9 zL=%%x>7xgxa<(})%X{{QZu)FbcK|_OyP@dt1^(=)xWG=>c>XnQz5&mH>RWy>K>{0S5OM2dq~M%3o99aI zA+Mg?JVQ=)rRjF#VP!EI%Op3mB}o zwt(G%kL*ba zr4}Nb5*^NkZ7xnkGYp{rBPS1_c@`cmR=tRc)+NS0(NV^yWdcZJ^#(scvMB?jw1^5F z3M5oy1PO&wyyPbRa09j7K8cZCm>=EJE3Wfx`9) z_RVl8j(IL&;+|a&8!3xAD>gG}qU=>0cXWmbEA1kV0t5bZq#9)&M;NGv@JosQmNuK{ z+v!NxSVRs^0o^7@xkg8rB@%hYK31R(FlMPlr8uhJo&7Mi{4y7ovcWin!bY~z;fFVG zSCZiM82Ni3MTNP=o2N5pk60=+89A6%+%OdIbruw`OGV}(s(_6fM8&IZVuRt>Z2V%b zc+^K`?}7wFi=qVIR{c5*^B(P~q9@h%+cdHF6^au{X|+d#{L-NWemu7%g6JBdiv7S{ z%eQiiL#^J=-{VDylUJFyp6l{v?eE%s5z_&%AhqKQ}qny$gy*MR_s9W8bl6G=mp99P=+v9Q`6s$T)SX4FA9vgoWYQvEvS@YSJ0zDHW0*qvu0H>w8H zBnJz9U)m_p5&g<)u+hOa>?uPuamNz6uLmTo{6udI z;QJfJJIMRelmX|7!E@GI^XQOZSjtjlIlJmhl_he8*-HM!#}j@h*{__augSB-sM@Cr z$y|muGNbb`t^meCPT4PEJd7zgq9K!jbPcpsn|Kd6nc=r7A`R1|a7|V6)yzRg&kYUo zuS4Z+@3Ig3HCT#vq}t(L8A09$WQKS*Mobx12vpdhv^2%S`HyH0=`_W;__J5BI32e> z&azOcnQj%4ybAfw&rj-;{W#LtA|QQ6fcBNP$5^r(r=u61QHiD6<7v-GOU@`dmn`$$e@e2_xk< zU+cWz40v9t>G&S>t7gt9> zCH>ZQuZHYd2yxfGaP7_4Kg4G>2{P-+T(`?+!PCu?_iZ*cw`;t=&$<_6HX{TB7b!kp zV7}-+nXd_4670T4;mV$wytv!fU%&dQYV`Y)cF@iTGl@xbH~OMfFnICR=ewOD*_+FT z`}6Ge+h2kjSKlAz_h$2bPCkF$ny*EdEqzA2Cx-w~4xP_KtDd{zwEDNEhkh^!CG_eb**g@e;i@|)0 z;sP`gLakv>#Umc0{3X>?pF_eV#3MLR;eW~_j;le-7WhXfaLL5kI&rG~-f5J&|QTE!LoaSu`pimks2`lJSJvX5;+1+^ie z9jMr@jG)h;*j_GJpMB7Pee4hfHY^@Aii#cIgH3{hrnz9VYH{<6feR4W5;ATD8Te0m z4}x#{27XtI+qQ@Ass-*N;|@{qpEQBTAowX){GYvmb9?wDB>s9a;1&hH--}1L2J$XO zNVSG486w)K5nJMjGZdnE7qJIQyx~fm_Cd%PMhWhPDu{=hqasuwi4(XXHYDx8~ ziNEX<0ToF#LrG_QNdvoyYRE(tv|2I|Uh=n?WM*g*fkU#EeUdXMMTaZpm0F62eaah1 zit%3Z^9qD2H2ei^n8a`jBRKWBL+T6eRLzQ1MZ8pt{Zu1xnD%h0u0z_hy%bhxnpH)b zIx3BGKMf2`b;3*Y0;g+((|qvKl`GO&htu7m>2^@WXS?)>{d5hy3{LJ0Q?B$7hYY-m z40})}j60KIDLtAy`39LxF`QgElnL0+MB!!?a%SP|XIR>2`f{atRb-`tGhCpVCHsM8 z62UcX=_&is)%!7Rv>6@Xm@Y8n^HN4{MND4>WWXq;ZaBL^BE1osk#L=p*p}JUmehh5 ztiF^r&Yd&om-&@Dw+elo`*Ap9%r7T2BL~r%qp_5W0_Sx*{nGa%F+w<5C3OW4qIeCh>51_p2Fn<4h!O9}x<$RHYA~E&Y z=an#t<$Ni}Vj10%Vwqu+wev$q`$?K6K1D;YN zN0`Y-+}n{Nv&vG7*kY@LQkxN&9S__gw%EzB%tgKAePx+DPuz!CxR-i~4^O!terbSX zc~ERz$N@YIjb9pZP#!f>8pDHx9>l@ac4>zGiFkNot2njJy5@Km)q#&?V)bd4ZCS621L zR`eZI4UEJO@gRm{D@Glw$JHw*E32n@5@v4@^XiogJRg_vt5zI8ev3_5H%{Edulj!Q zaeJg{m#1d`AmMO1>E}q*ab?YEZ1tamnsar;rDXDTZ1t^U?Y;U(bY(3DeIjrr6I?9bVzj`1CE19e z(QUNJW3y3iI}(X*g3Vx!G4xppw-3#c#4x9ph{L83 zSX**HR%!=L`e9QhZ(+7ZbD~C5epOJRNk~OiQ#5^Eu15RAVEaej5J!#T`l{A8f|8Do z#IDhj&jG2QVC|(EZ9eo_y|B{0(bi4B&VuaD^0rRvK0jYn%h4je#wSOD!neF&;y!7Riw>O2ZZyVaDkJo?C z+h3sGf9lY02JNRC>uUw~9ar_FRrObo^aBt2ZMZv3t224{1`ag_&a3($ykFv-2FUKd zpa}+U%Li+C2QM`SZwZD3_=bQ-eHaIW&*KLBssEqW8IAvG0wA?nD*w9)pzvUwDa*2|~jKhJuDX-fdTjtxxD6F?pi`zt(*T8q|sVCMEhG z$t$?|rDRX;q{T=(Bh3Nf+H@(n7`5_d^B;&~KAu0I`CvZCeLaj{B+h{e8y`!ER8Hc< z?zq%O#vbYU`>2m*9a!}0u^502AR!tAkdyZNvm;M>n4_~UG(Im5ROR=-o#DnD2_e#p z?~)6G7S?410sp}@5MDuL8t z5;~edTH(BhAACIe66>jGAGvIT*KDiBB2n%=aq95yt61k@uI^DArn!dl0n)StT(=ebTV(O`J z`|-5I5?^TW(Rj-=)>2I^!)v+7ua7SK0#HUw4@Wc@ifkA6XFOPH}3nV^lJkk zo4eQj>TOxC2LPdWkGg-wH@XioGzEG@IDp2U_Hy5F>%aMXdN+wd^fc~toJ7jnja2GS z9O>k?p)u1C5d~3NEN#lsr^%k^g`KH^X1=6efR4!Qy!zzSM)NZt_=mO|3;XkVj1-`# zuWj6u-+GjUqK7N$%;;6l7{;}ab0t68avLYzCy9Cpg9zBKUit(U2nkyy=PKkY)Lyi{ z^wAL@1vtkld8?S84cB&LAIF{T(xy<%?D?HJ05l5th>Ym(7?uN47KqI(PWAX4`+KA>YHw9}x)W-O2)5Y1y$tS+nzPOp}N? zQ;tmubqjExUXtKG#tM&5-oW~l6hkZ8!@6C-I4KQ!QKReRQeLToWKd0uyy9a5THp|; zM~lPibXY*ZR3!T5H}N_22hG@(8o;=Ri)6{o^GLV{9zNF_`D0Uu+2|G5NFp)Y(*Z8` zq-3ocrAM#uuwn(dNs=k`2Esscx{^!a*Ef1_#&=H`jNXfVKyE-M#Vrz+*Y$oJCF^LfiK$QZFFd;m7u5sYSQd^&N+;zO;S?_bU ztxcC7qUiE}F$sO&7#bYQI4fyOEr~*+Rjh_dDQo?p=BIED>fZ@gJ*W9J1ABDwi3rb^ zn}i=`G*4)Fa$<-F^Dx}X6?K|86_lNo3*P6iJQHAMxkMr2`P=R_TCWumrSH{s!?8vx3PKO(2 zpunEqiPa|(Pg!H9Sz%4phe8^c@FK6`vrYI|?+BU-x;$<0@62ZXvDE zG*z{nv-x3_vL1gsaqs#YQe`b2ov@#^n?0Nm&fsYX2 z-S(yyulY<*OV7QsV7TD^I`-$5Ug8~-NXEboyab)zM`Z+&B7E&cA2NKH{+_T1^I3L( zYw2fvA{?t9xJBh-Fd%><{O|c-&eD7q>2?orss0`oc{ND&%N_2=_k(#>9Hmerm>A&v zgN99FSbEGoDf?)PQ_-l6Kl*8^f%7)6kI|@J-tRPxI~!ra%welX?wK$K+h;9C=piSS zKbf03J0wGy6CZFqawP)oWOlDn0TXWd825IZxXWK6o_Q8l1@7T-W=+F(Jc`-w?7^yZ z1F3^&CERzm(q_iv+3(zt$}$I-c3ES&7k|osnmS^%EYH_!xm8l-+6Yb3%~b9D`RM-E z>G`hlR7dk!Eg7Q|4oUW6uZmZLe2}v$b@uaeTkqN+85eB>lX(Ls^G_08&TrmludJ)M zHFgELyiU*lx;yCAjGNY`RMYKm5A%xp_REm0-9Z6LGKNHR@Uy*&O0_4-K?k? zmeDv@J*8c49<>4Nw<;IC`?+qx+NSH*&)fz$*4(0AFtk$-T@7;Qo)SEaGBTsn-BFr( zzo~0;f;nQYM{Q*PtPGg;v2prMfV)2UEv)Xy4Eapm2YJA#zbz@6ZI8R>d4@5+-PMlq zpY!|sr<9Lz@AY%{(V%RvkM9|W-ZGyo#7KMP$1rYb`rIt0ntB(ueEa#{;AZ|~o_EC1 z+n-JezrUU4`S4wS8}d^1-B1qpeuQQ`iCFO6G77$$6v*2Npbq@O@xt$m!MoG+p}-y1 z^{cko`_q?#(x~T?*L|uC`z0hn2h4>2)z8;Xi+rvRUc3lcUU;|CLLIOxlW_ZO=-ov( zT4v$Hjqh3P>0g(t}>yn|9Be`O1q`&6BOwi-XGts1`~M z3MX0&0I7wLUWH?3g!=o0^QVVn#zb(JN8k)aFz-er;YN~hMpCwf``bl8Vj@SBBM)sO zBX=X0aH29equzZDTVDugheREfM{%K|%6TAx%0YU3< zp|4QBNuZdA20=i;{2EM%F+_|n#-Upg_!ZD?P$G;gkpYb8$%x0GO}a)Q z&U_O;XCywMg>&H{9&smS?IEymA6Od6g5advjHJWC)+9D=#Kl#-s9zG@HI$J%nZ_ac z3r_OLPO|cF^8H?-q*3xq+C+7{6y3H&Er%4Wm=r?ll;W#IQ!vahGsPI}ssv6IxQ1Cl zJ^0#E>}cT*4xVNeaTeSz?}y#px#L~h;=Q2$HWf)9_T54%(xfuee=Vj<&}KYpNuP^J zj)G>8muGC)X26Y775q|DmQoR5uOtbCHZ(1MINb*tpO5F2>ENBcl$^VtR!o~&m>HWc z5nYPs^Dz?a;lIS>{Ah=uh(7k~dh{y`kG0aG3z|L{N1 z03e7#O$d+>{$F>97GH!g3b3wr>nwXsF)xjr_l_3_6M!b64=L-%14&%}#rhjf7y3U_ z)=56>YjJ+%%UY>U@eX%wGi=lUNm-9HR?L?FlUAxXRnAu#{!3XmRV~z-SEMB=G&^%w zYXOjN4GkI!{CrG$RXLwQQFvSV8B%mCD8ymspblW8} z(;~-!m)P-+JI8fcM@MNwOFZksG3oZ=K@95BGPcuCZI-X9=JMm>`1>a&isH0i-61Mo z#*yStm^7K3bQ~T%avjNB$B1;FQJ2LNWmJ=XS(rc#B=i}392A)}9>7l zq0R`Dk{c&Cg$`9$*cXG51ISRD#_NYsb7+a`SH2RBW1)A%atk#?B?CDoGVFWU)#K2A z!F;K9mc!}PR>pkiwNFCRZcR6wX+F&nS_%iHvD=y>ke^<~q>oO*Z+kN^ACF;tK3jVQ%= zxPI5!_#8tD{P!5ZeJ}!61y6V+NT;^& z;7g5pQV$fTJ-|ZL*@dR`6E;2wBP>E=N^L>2)Pe~Q7wH+#?iXG$H__2mzT;5gtNI$Y zO*bwiWNsPl@g^ZjEa1(SQW%BI9t_qbu-1Vgt3!eEsWIzdQdcI_X{|OBiqIfuI=nj3 zhbM27&stvp-Wt^A*RYlLUd)^*zP^$CiaC8Jj;r?d%Ar!oFK!Ir-{${P3-`AM4W%k!cnO-G;15>aS>l5K zf(V9M5ra67#;zakha;sDcx*r)9u_R-LRqiJ|FvKV5CQc{zD8QO8IE1eTV#~s!8ydl z3#xl{3h%@M4G=LaQHt~pqH5z_mUiS6lI>o)%bCmn08|2~9Z(}?bD@Yo(oi;L{J>A;jsiAN2zuT?4Pp@&J{uBaBSjOz~&yUQe2vYK?>~06TGC=8uq@FJGcee-;`@sjp_7sf=_Kn{T3~@p z+E~&^+H!fqH)oStj~T&wKq6-hViHpTntL~uVxS+nB1Iray&adm zb35L)ym*SyR!M4jtX&3ePdMK~H?4HHjoV<6Mj58u(|wnx4S;Pi?jzRC!!zF(8N z?QVtBhOj3qua&G*uI}*1vlR&5kFB)~*Klnk5 z_*APr4Jd%KHtgABJlhvNk7>RX?@9>7rj6=hc34Hl;-E zayG5T`SEP#<@29svpTB$=X0+NT+ZhW?LMA=HTC&E2SCZ~}vyUvVxjCqA`E_$xHzaU-)VSb!`?Hm|2}-XpDyBL8 zho-3Y#ng`L-6@K*_U`xC^W(ceQ>w?8vd5%{hEr77|LYK9h&hkR0pS0y<&TCyuI|5H z#4#3|(1-af3dzt7p(14nF`W?7x4yU+hxn<-*&>-W3YQJ6f`w=KSUr_mzD%OOrx%#< zNU;ph&HnKOL=tc24m#bdRfxetnrc6{F;$8i@#xNni+e6y5ASdB$OcbuHAeH_KQ~SL zb04jNp;Q_d8KKzb7e6URFAg$W)OTh+c6h2|V5|K2rA*M21;BPcpE+;WE|c#zSWtM! z70xyj0g-$5pvHdK(Pv(@r70(X=t%( zB3=^%{uB%QNF@4ARv_LVQq^=(qCq~W2xo7`bL|_3)(<;V`Oi#<4c$_ZV^}Jfat`gE zLa~^Dmp|!mNOVH6$TM6@@yh{`QJPRX#|;)>eIwfPsr@M8VC2*L&1Gqm%RQ}52OwaZ z{;GDx%AYZ3+r4a{$MMv|`}JK9K`)93yWXp(?UUUE5vBCrpI?QV@q8wg@4h|li6Cra zV9Mf^hy8pg>-#10^1^WdxknehR%fgG7M>lD`cduK)Vf7B^J}KB`5*E*7yx!V$7cFJ z=ex>@h?p~^=Ud%@6t9_CSpH`R_LTRA#j)eN6ZOR#*K> z@8pZ>Q61NbPGhUzF0ciI{IL1Tft96)Ayz?PUnwwKhZHN}sfd#|=|&h3FaL?YiZ3#3 z5SITzB98Xqi?~o%3aF3|Qz2qgY2J&TJwZmAp043h=hZ9=e;-OBVRk_@VOhXPRMz*h zjZR7?GOw-PeTsaEw~Q7e-zHqk_pR8Te6GoSk?(g724enysNd6vtz5=#Q(ONQi6}9z42ZcMlGd8s%!U%lL%9INEWVKu#(`6yYp>kQ5gSg=)-mfq-31j|) zrX$ox3$b_`XktbtB`pAjJ++~TP~N}EoTn51xLl@(P8IoXUbEQ;&`Vi{c^~NZ7+`Bi z)RFecjbieT5}gzZuU7{1*N7R8V7#7E(G7VM@S&+!w7mE6PwuqlUfL|HDq@XW_m`{f zHa_FSVhNiY9VP;rU_z1Kg(Fr0e0Qdz;Gvm($=Y9;9lai_PPOQ-_x>NQ1~-Wwtp&gH zx(OLyF=5V^f%{zt?dJ=C7(Sm|GOg~KSue60Oko@mq27e`Qi-OA>veImL_P zdEemSvHP!8*jqChF}7JI>d?j%1%MTd^zesVM1MT=Y$G$$)CH(*!4S=TtJJqy?CBU7 z;-@T0^Dg__xN|3$J0bQ5&5N(l8#`N>?(zHd^1-oOobGl|=-YgshNcABW2MSM4Trz4 zS&A?3|JX|>dh=B1NE2NqnPoWQ#FQibC6kRHm`0VRokQQBn&YFJcm-a-{O{VRVR{IWqegLXo%x~G?-3%#iKlIP@)mNx+N!`Gy%uP49x1XH%~`^pF8 z2a0c5?eLRrdc4poNDX~X`b-6$?Q$J%3}iar!qtucy~~-(-lm#c+^x64o$1q>Scy!q=^vH1_v<$mAyt`37QoG(aE-k$&Jlp7GyZvH+C>mF#G;Uoz% z8ozxf^IbUo{oiZh+oSv6{?9}I-tJ5ub?v~ke}-b2*cYPz-d)yWGaPaVS-jk{OC%|uOHDU;Fgg@ax|&|>EskD z|93w@`k@JM0?_`?nfhN7;9<`R>mMsY0SZ_{ahSvT)EABm24FNIj;pBp;-Q3p!2h=T z99mpr{YosMV#?wFZUPK>=n+@1X8r~WXUj$4GpeUpbEilrOA_k+rwIW5o1GP1pa>Mn zNx6Ad`HGE`$=kNzQB(EOC(ZK8T#FM$?j|(m)t~26*1%NU;G%D%Eyt>@`b*?va)fop z5!*R5YMBeQ4`*s31CG7^I*W+@Uy{x`#0|TXxGlv>%`Ux4sk)Zab!>qK#XJZuR z2XeE`1Zf)Irp6A}dz6j6laeZwS0U8TrKkP@|A&auXO~VQRAzDLOFc2W0xoAA^xDy# z!R_XY+iSD9pBd!5@!RP~DcDtvyMm^Uic3v@=>F~b11ND@4~?&y0nld6j!2;6~$C8dQA*} zzGbl^!EOnc8|g3bJ$ZYz6(WmM!T$0&u~G?4`tj0~wZ@w^D_7uv_==h)eq&Mmn`m0I zbO4TSNunW+&ICXrk9#K@SC}SJk=D)68n7%e$B+|9*KeLjlt`tQE+TIIHXlMhSDNMg z?2IkT9Zxh@v75t@I|4(ebv2JMb=SNg?VW$QT&c5CI3P*qDp=((J%E;lo)bD+hBf%9D4q@= zJi@VP+2EF{?-aF4UggwERO)u<;<(vZq+V5aTNZ*zR&1kATf*w(f=-zQnZSR)s_lAX zS-#T76SQ%HOC&yAO`BgC>sE7xKL_gINwr57M3s4-45&Xg(2>+SIz%V~eBGP|_!9Y^ zxH{mc3=tBDdg|bq>rgnz3nlPAq{;0kUg-Jwy)u1hJ(xJxZ946`&uS1OlCOA9 zUmwo>)%g9e*TO5+UC%|pnE11$wReY}MA$&mp=A*g#|2>lA3GG3%r&SWKSy zoz`8`@oVbv-Q?x@Tpsb^BFu=)3FD~vuWZ3y(&X(HBspGY%TN%pz5RVz`|SEG;VR%Or7`HKr^NE7tub0iv2|+#c7AKmwkUSZ2LsEjj z#}VrIn>f7o3Y2faQEb+Qc!GOhh4$2z<6nDO(g)M9z%v*#`YPTOOE3O$KPw&Hbvz->Z$tv^4`x~x42ynX zQuxasBywER2?V>mhj9l zKL``^W511n7`UI-qaT9^p!fnycT{~%FGFdXgN0ybH26-DH202O6jr2>aHhvU*0}vF zYGyp1ML%<6tc-Waf#P*|NtPR4xyX_cg-`I0?9g6Yp?wK71vvIc&et(J5$$2^j4`q& zC!%q(O-57c3}+lyjd9X=%ToyH6n4PCxWa!{$(|j_QdpVky4D*3Q30tQt+Bc>AUQamwt|9`TioA5^wjlp#G%ASrp~+R0ne4 zk-0N65iT+~k4BXwX*m-`g)TOy(C+Z-T37ZGeGDbeg^{mK&kE9r-PjF2wks4`pJ(+b z?U?)n{*N?O+Rm%JL>GR=QIjKpXjWTN!xp~?i`CJB_XK4!2`VSV*bv(sI(V>`c&{!R z1iE;10Fp)x;a^LNn!th~4vUj{&1{)nD85hEs0H+wXH5^vZ99G^leqq`kDbI^-aEyb zWKE^D^mU=$C$CIyJ@pYB4XTmP<$Y_Y*V3*F74TLr`t~!tq+^Z9A0aZ{gd1c##Y{J$jA@%y+n4hZ=*RcSn84JW?{hb7%pXGEhyJYJ!MUg<+LUz+-7VQy+Hl2QOh~+^hJynY8$~x9xTb zx@=d&u}>_DH=VZk>W#c{Wl#NqKg~2XsQdg>&hmk|aSQwr-4{BzTyer*#F;a`!rnb~ zH6Yqp%JlDzD0?qEM<%u4AAvDmFu6w>FMp^~68%!$Mb1u|U+NTP?Dq0S# zEB^M=*+6QwOR)c$>9dbsVQ|Y!MWzCP%8O{$pTUjUV+0d19dB`^_a%-u9VVW)oUWR^ z#1;P<{8y>@*1}O<H?f2jJUyGy#3eYalA>lTriptHq&Y&Oa^(&;<*d{+v6b*RqNawGnG zZ&Rb!B1|@EH0|~Pt>rW86ug9$A5NtOn(wxDnYSV;X|-W9`JLYceIq$3i}t!KOfY}m-EUlTaoPJhxWeqx>mJy7x2qj; zeVhGZ(&xnmZSGmg?e{?RZU{g;ba$4-RnPx+LGe09zIK;}h)axwOPzp5o(x4zrS_CM zL!BZ+j@IxUJ(nD#{aZX=C04^n9FWjWP9^4y7o6fR*=UsbuPB8fydsN~Vl+I@X*78a zWhKNZWv=|Bt{7ez1`7HHC>ts&f+)ctP7OnC`BrI7H40stC%G*6MRIr#V)Ys!Z`D18 znjW(XowP;U>yfMnmmnOzP zBV5xn+VJ5T5g8hQiXk|Q32lwGK`%;rqael*-vmR+Am11VUx>s)a3Cl;Qw<8ukW1%+ zX8HOTa>)fjqN72vY}N!`I%0&EqsMP-@>_bvcFvJHf{cM{M6Eem8-A*#K2f z919)!5zDInzi~pVy>8g-yH-d;^i{+O|(cepUGc}5SYkB2tcE+ES zI-(kO7j2@KQi?6+?rigp+2~cG$o{m1J+V zoz|)m;=QcaP=d%33Q8n1M=V$!Afb-e(@r@HuC-){S2<#T--_hRVe^It#(%{5yqwYe zJ*8&bV%ppym)Lj!n_z;$e!9=-t!{SiG+ul+_7z*`C|N4!Zd@(1XZKr(nPNIp5g+I# z>HrtbptLgr%?rA?_rL_p?n&zRIpx?lyincx!eI zfb^%tjqVc?#bkro3qK^Mi?SPSW4LYra5@s*r7dj5h4T3p6SVaS%WDGN$nr|0bJtV8 z#01$fm}X$RXPxwTkkGs2=c+uSWJ*24KKGvxh{Q>WrL zn?(r;^0eTT(kk@gmSu-0gsErJmw%?Vy#$42`h;rVQ!DPv6B}KzoxMg=D^|jiK=);y zDMjiv6&)5?S>#E@_r)?ha?- z8E3;~gT4i}B`cT97jUV0{>c4L=ZL3#*Xpn+6ZZ+p& z8rNIDZ?ZFMQgd(ok9f`)X15YWr|lkY(GOz&5_ERzK`ERAR!xaQb19l+m_!fthxezwN_h?LWra zXK)!8a6?zqI(U$h9hALTm!Zw=3hf)pZ85EkYVz0_KAn0koo}Q%TUfi^{B7&D%sP7@ z-)wH_v|x&aXWfc4AYU+}ay0IeGk0iop|>+i)Ft1ib;5x)_yz=o20grXJ*1QbCM+_B#~xfBDi+H{S2F(@zZ=h-Mm~P#KU391txS;2Ritxii3oK1jth zNF+N5{xXOjIQW=9c-cRA^m}j{Z78@u^O9L4-_*ubpl>WK=Lc^#{SaKn3hE&$N^w6# z5oY5n3gv|;6H;rGOgah+B1$#J)GZZABErHqlAW(<)6oq z|C|v}Jn;Lm)%{V`pvn2)MS<>Y>EkQu`1<0-I3t5N0L#~t6OiHE=9R^SJqGBM@t)~{h)2tnGJ^MVI;G)tD+;+GGb z&DLA_lO3;gbDu0Wk#gj-PB#}01@=)wgzb)(XAOSGYjr>=6gIL6{w8b*8Nr{6Q6A1}fivp7&0Xsyx zTjA(ebrViaOeWD9f6cJAqab(Ek-Avmq&E_CmqXhzkgKonEsV%Qf5$1}?J~yea1v5~ zdt+)|5YK7xozYp_EoCQGI82Yp`7YUg02uBaf>qtNH2Y!ylD4i+N zE2Kf}jY3|Wfs#N!4G!vUE|QQXT-givTgdIr59VQ;1|KB9GUKx*_V3K4H15} ze(-LLkG=34ym&vF+rglppx2b#)7a%Wj8YiD$7xvr#@q`iC+ZzMMgY4A6U53Ffg=S1 z%$9L?q@jDM-oH2gyR3grFv#dOyT`TEIIG(FyS_#_9a_h`30 z;0$f3?!y`84zHqwI33Oj**T34e*%>g%-!{tdeR|e;9b%ga8tjM{1Jk%~P@r$>mzn9$(~= zplj*9){i@ueB;ZOLP>W>13SfOu(2?EA& z6ZVPqMQyblzACM=hr&794@KXQTq;hTEjZjR&`$9;qHRv0mHah=aVcA0emdo-p9F9~ zhDHcP6mVp0V!(XJgR75w|TNtlp%XOb!xfP(VVz7DRX)7_f*8 zd?vOQm-+g-d7cQeHRL4tnd&<4_YV{ef#&5g1PcF*ttk(C-qYWth*5e;R}xKMMrpEk z0^>TKRD7M#g?fKTpnrFd#f|c; z0UGu}?qGI-zBNzKA1Mi0LixaG>JF*H*h+9{*o3*S)e>AEQ|f()RZ@#Pz5+RUTg+b6 zDed}81-BGS!d)L38shIHk_tDvA<5OIZzsyFmRIp*z>MVhz#VKp+UMm0e*haRfev`q|Z#4XDYZqAhAPKGs5agwRrlNxAkrK?qPaH=5mOAPCQHOTC zwN|qH0G)zBrUi?%R>N8(h5}ICN!p^nfq{Z%NSKc_9o?}(@bSkG=>`CRvfcCPJ17KG zz;wbpd22C|m=#$o2F1x?@mponkTskM3K*{>+yfzSuAvx$GpW5m36MeS1|1|g0CIW1 z#)dGeh+zXmNazm!bOyjr8W6&xa|ab3@*Gn7nwA_D1R4Y~(-E0rUq$<}>J)Mo_-de@ zfX@(pOZ25-IV`<1DZ&7mHeveQiEn(l(Wan2m@igk1F8fpa6@=a0BeShT;IT`Ga$9;>+Ulw+l1mQ2e&mXh#X#^hy5cS z+=BBtonO0k9KGZhUK#4VYS6AZ_@>Udu+0gtoi#i$Z*2q2SGqW_be!r2ifn9--t_cc zod#tMPZL1mdwDyVLcBfVCpqszL_7W}hKc_9%y>I7+kc*EW3wu4v_Bd5?{7XyN1b-p z?VN+xNo7&!A9b7i>AYW8@MzD&&+B?i7u0lhO`gYM-tG&SS+{-b9_Q-b9y=^F7h_GH z7dgnsQTeRf*(R?mCU4K3uUQYP-X6%C9Hi%YaMt;Dlh@sh_rLz4tcODv?*}l_>wGBd z-vy1w(~P(G(=N@~!>-p8rVnz_1*qVSYUYDp?1EYBjXmsx>*@l=@`14W!W3Kx%zTJK zd`U=M$cB9=_I#hu8g@4v`LO5llpK!SivlWoqArJ_D|(#{ zN1u~M;FfrS*$@!(s3|Nzf=~p}el&@>A6bbf_DD1g+nWa4i;fM!VD8Oi?!^*{U>os% zG2-y}PFVZ}gKh)=SsJGBatjNBP*uJ*}Tb!h#ue73%Y-pT3b|fZtEQKP1 zYQ#^m#7B8QPFpcS6FWN2Hd=2!!sJK7M>fWWjRYUR)HOk7Ii7SRiDy5F6FYf}HJMl;S;;(^Iy70ZB$;m{ zxmGYrZzv>m$R_hH#fr@#ODHu{DBMv#wK&wqOv~0SDYayTxtz?U@-Fpcz@{QJ72Vec zRntc5Z%UD3YS<7{XNz<9ch_d_RI_*K0ZHV|Y|g{Wt|Ue2dN=8C-%mfx>94c#d}?T5 zxp-IIl-4pC)5wvCEj|2$kC+X7OE|l^9-( zD`l1wLKH++nu)I^PGv#z#w@`67RETLmTQ}f7nY(|o10h^K=+pn$2X5K2ePM_cRdmm zx}B$}6*QhmB*zZBC;x?smyTMdP z3-+nh8$tQx26prk}Cl|?@t& zsB}I%1D{`Tt8q>oJHZmU&2npn#tI~~6fdI`cf1t$eRH9m8`NVjf+Y#sIP#gc26EO4 zQHX)i)R>)-1Mayn_w~s70ibR`<+VnZxv*?oDWiXKcJB(l^f^o!R_v!wFmVk72v<*& zS72KBV^O4`(^cWTW-3q3+$bf#0#sk0VYet%y9?*c=;e@8Fl>!hqi!%f7b74QELjF$I=ftPJ&COF`B|g3<>JKZ|O)Gym&$t>XuOn_03RkEjV~AF&>`AR& zY^~U@u2>t*pi3)G;I47qtgqlrE4VA08>Bp1sq_?to-0AmgOzjNGR1Oc4CH{(%n+mZSnw6cyXC>CD~5uf@I}4c7pQo)<-$8DFTIN8UQ$J1D`#E z3$cPNph+*XL)~gQWK$79oDp||mwq-oA2IOG+7{e97Sm9|qzI}W@`Wvr`m=cEz_Npe>m5oAF_P0*Y8$}AG~iq|#GSV5V$7^glCa?gy|OI;GTvE` zo&AqCY4)&f(H(H$Q*V}(kRLE2dFQfrm&hVr}`%i75tJ!E6&_3p{Lcj|P zY&%lVR!s57HYF~ojA%cuCN38UfLaZtO>e^S80KZxM*mU z*{U2Ct#Xw`rMUV4AQ}K*W(Bo)gsygXbtwb*JaS`atn7ojZICfgsa$kr+Dgo7v{mN; zXbo8Lu^WSnM@o1ov>iP8o`{0~J+D3rBy~_11oN@&P^N{Lnq_5ZLe|YwFdrE_T`6+8 zhG76RmLA}OJ79^nK1si%hl60>#|k{-PI=ais)14qf;HH7*m6O~lU*i68|y-;SRdQs zss~v&2fLIF>5G~-XE>5QMp<&uJId|1Kp<22C%^`ZOa%U*ZO0&VauEbl_5nc3(c?Yv z7ay=TDN9WBQ@a6Z_aH#@$H_LUjyIH!kIa;O03ZZ3&CxTaqv8kwgZONx2|MtK!2s~F z1DPQze&n?9`Ha5LOsU@Vy(oaL0w42Z2UUjy8L|V7>FEb+4H#Meqn!z%OJld8?J| zpN=uj28 zj1I&~eR`H507EX8$#th*5;5;ZIoQIK%bxH9Sc_&t56sw=f=-P<<%HN=&v$B zxp$PPF)^wEPfy>j{#3+2KXj_`4JIdE-9YZT$?3}R%`1PiFSctG??7R@7XLOkew(@& zSZihemMou^{6y99QJc-82Bh{J*pN5g*(g>#O)XOH^ujypaa&T<}j69D|q4qBs*?U|1` zB#%*zkMZG0?P^^sA5PZPpzGoXQ=KQlvL|N$PR=q955y0TypFm~4#vJcTL4ckId!h7 z4=Skv@8PL_w9tLdldE4RH<@R+Q)fWh(>BiCai_D2e?w!Lse7HL+nncERfAO@&WnZ4 z3OFq&)%O9>f7z-|Igsjqsk{eRs+!r?S)L|0R{#CYrTF`JwKm+j!{v1$0XcawrS}rK zC5t@IeSpBLF8NOX{;|4L&$@sat&3&tzV*K1LB5rO5E*)3DO6pIjV*jSy;PsF(e%Fl z_mA*1M|^XZXkmzwev!Dk2-9{k3I=GN$yhB4&E;?+%FC3;xbZN&O*802?O z_;pb9U$1olJ_7eU&9U}6f!r&sUavb)(~XGT#l*L}WSaZ5shhErJ5mX|+$w@9aTIUw zyA+$Fj83R)=0lO%O}6^F=;=^v)dPy}Vg0KO8+B+;)}z!KAn_F_m+fx2>TxvMA@CLS zhxgMQgo78tQsl%X<8UeAuA**K@j7s;Dz#^RGqXUyJF$(fU7}s8+lAjZ*~V zoMxB*-KM+WCLreY=d% zDodJwR8sk^f90pxGqJ{YtNn2x%e0dl3SfqZq;`i}qXJGh+k%Y_(mzB@Ar|aSkR&|5ul)AP9E!U-$)11ucdD;?k9#dS$W0U#}#NnH#hdvJsmtYCu=!s8lo2o$MP;;M!lv}lur*bxNn1> z8fzHM@pqgI{~m=Jsdch>{Q66FpC@NuId#NV@}yfm93ns?@WMzI~RQC&-DuG@FIo}|GlGGAEtx>Op+Aa<9u*I zP?T+u+D2$aazK|07ONt^PE z91&cV`aC|_qq+&{xCot@`&*89RRZn_9c=}npH=dqI5G)M=WpL6%xg;TnEe2~2;>*k zduc#Wpzq%1)FbB-Sg{B+N5AGbJ|3I@@rh03ZKqKZxI*u5NMPc!7`D^&tVM+(;kZ`a z+FKs;o;(4Ao$W8uy8Go&o0K75dsRNKGrrXpX(J^5ZW5&|V8t}PrkYaX z>V9~-Ri|+9%Cz$BX3OpyN5UZEHr-K7qhzPfk=;z=%Xg*GkTMG@O#?|cBwIn!iEBYk zuGWyLp-fJ`MOoFqmUYik_Q|b2$D9ECcg4gMEVW~D$>e2bbrYQL*MdY&QvVdb@Av%Y zZ@XtAXEzYv^dyI4TUhrwnnOt?$G~ndE;DV$tG&?Vpy{DAop~sf@|#(;1mq`kH|msa zW3=pDtM#a)dPd&N15@Re39FvDO{aMkRo;AE+*$3`}SG-voG7PE`cY1_jEDPHnry-(6(BIzq_6(X16gDZRWIK2PU}tJ5gkGyE;E^ zv@2*VKA>0WO>{>CxRDlDL+kd~6`_@#lP>{uLcA`*H>B|udY;lJk-k%7*=W2&#g8qg zE_Cf7+b6qakG>VYq%t`eEFoRjs(60f=^;<;19a8sJ_Hz!w0Ly6eZ(0GKD2~e(67V2 z=vrHWk}A3QuZLyuux)*~2J>(O4)`hFg4S(1REjs0xP$feO$lu*Pe3?cya^!*`Hz4~ z4d$^+gi-LqZjjBF(`!J z&${$Re&YmhD!D7YahFRddhcZM#+vO-^%h^+KIK>Cl(6}fONVl!2DWz%-=_+A5=ueO z$VA?zg~HT^GMvB{%BSozP522_Ry$Z47pe0dqmHE^6Cud=^CJ^|QUbMKotO;S#ulr$ z8mj3H%M6}B6!U@>$}=;pw2luJTio6hMG+mDW2dd8rSdcyKfQnlejiyK6{yRvsIZo1 zUs*@FZs;Z2(_&0}8%-RW({E^n!9Duk(pkIZQ-QU^7hS_jR)IFpFAOdzwFVm&@8~7M znRL>&4FCAO4vv!jW^}Xn>oB*mBk|2EkNs7h`wy?1EYmri0uLps5sMA<3E6vVy}$lm zHyJH;RK<~cY~=HRd%=TM9?Vt-XzRn>l$EyO0_CgQVYj`6c$I-jkvY63PFc}-vmF)R zPj5_b`7ivS!E5i}O~9A|DQhZ)(xmngPiq_Tw+9|DWFdY;Pcr`aXNnuZ+EQpuK1Z(4 z&tJE%zvPA`k2Lhy$Hx?Fv4=NvI@e@x<*temxh+{1F>IvzFaGhm`fAZ0eWpVS2_e^ua1%3PK1XGkvp^eZ5W6!lEq-Ke zXJHvk_@)Frht`M}1Q&L4oSfc}L)nXqM5C528Di_b{;awvBvRC)7j`N6Nj$un#*!jb z`cd--Bm2JGU3SA5kLd{8%NF(`Q$9BO6unexjvCAOBAsqu``gbQrSp9m%E^ERtj z;u=@2fAldkw*@0kKTL}^($V>R3AVkVzA=lc=R_LrfHq##RhL-p7xDtFHbJNOJ*ypq zKC|W0kYK?C%FeT}A-OHcscX|KJo{KCQ6tRt_y91|No<<#=IXaQ|46>`S3!^bG`p_j zFoD163~M_qH+d82o%R-o?M|Y>EmL3cE=6%N)@0=G$`bn-Y-626biq4fH$9Y!;ZSae3JO_-GmY0P!q`>)*cc@Ny2!^s*oOX4leTko-6$x zsv{hd%N~@&9$Ly*RE$z}rQHmU>raQ^}SKgF2Hy&$8V{~ zrQTN_Y_ACW!m;{z*05-0`qGPgk^B)HJdV;uW_^P7Sp4~YeCd56=~yDqI(Wf8aYr0M zwEmj7Udc-=Nwj_mzW#l9zqn4nEMJM-T%UY^jCeqQNOr$$eZMkCv}k+3>Tem0^M0lH zevxq*X|w?iMj04rK*wr8bFN=2zfYS|=G|`@eH9tK2x$XH8AC_u59u;S2GSq-WQ}E{ zKc&ll=8!g7ll?*{ZTcwt^-;=dNpJbGWLNui$B3&Wo5gyyF5ceA%zow8d z4o`ekNUDb?Q!1vU!&5~S(*oe>28tP0@JtWIEFE}ux?+wfJhxpjj}e}~rdWUmFML!i zI+7@+R4SR1C>2#IYnLcDP^w6msPs^(@{p)bSE@0QsBKrOQ<11&Q)=LoXna&^qLgT+ zRBl0&Xcbj%`z_vXpxiMo-sz#-RW9D0uG|wL-rKI+XC>ahraYh{KKQ6SL?}K?sWLJy zHY%zz79lonpfaH%HtC@yop>NX?e?={t(ONKv>s=MP1dz5PX=?n*=YKI04 zM+R!gkMt)VYNrwOXX$F^D)fKb)h-C>FW1zr`suD8)ovo_ZYkC8Wa#ci)gM4~j|S>b z~R4ctI#kf8<`OpWKM z0jZ#ZW@x}vsqi~A2*6Z?KQ)LtD2bmmNWM^#QfZQ1QILyiQbbZv8fsDzQBZqo(o~Ss zW@ysMlGAr+GR%`P{?ufOBx8QkWKkt!rP5*}B4ZcRdNEJRVW{;okd)I?>(xtAt_&^i zc@mxuEnZI&B;QXhetr^xC#~0D5AjY%A-+*{ zm_y(@U*iGZD{%)Hu0!Oa131OWv&F)0(QNFUXU3wWXU*;f!UNvh%v3L`}QV@}DxR?%Io|s!)<0tOdkrRuap4!aX$#_7V-m(No*LSgz@0>hm zJMzNR>!Ms(iIc&)DH+;5b>K{Jg5$7m#xY+=1LA)Q5A~lLHcS8AutB@MQO}n2N5iK6 zule2o5FUO~S>iI5jQr0ENAVfwA3{w;ukyXN;6Esi4=Q(>v=ga34$lo6hi%nFvF8;I z`DKxO?z8Yv%-r!mC=Ql?5lRj0^CfTVET~o-pHUo~k@jfHjpcGR>=UJihtQX*jke3J zV&qMg%Pr=|2UjccC%?Mhoc}>raV^>C2_zsGC~LO+(GtbLK=h)ecDgc=_praT#X)5} zQ#vkyqm@sgsZe`Lw7iwSzfaI`>_Z8nV12pS+ACi~py|{f?v0D-<=%X@F&Isvo=G8e z@uwr}!I{%g;Od|v>GM>jXWRbaFJ%`bwQT_F{zSd?0?!= zTt_!RzAUb^(`fhn&Z}VH5*IB7DTfIh03p_WC$)oS+XqIH^=D)AJXTLXPYML-B(nt3 zfY?A+R(fN!ySSi0;Iu6&E{5cWM!<{Ft7vgj97h=d3f?UO2(3Pok8*iJjl_|sT|!{c zqtW*Hz*d%Um=$7Wr+L^}mo)rY$O-9DP-f2L00H&%8gzRm=0x7e?}~YFI=mJQgnZ+^ zsSX<17NfKPIbk0*rYZmk#uTdVNpb&h1)+YubhhhbA_XtR3RuYTN5F^}ro$sSuhof3 zlq?V!n37O4fFh*~j?57uvR4ie6hSLlob)6;5GcXi3{AoC-6(_Smv1BZo5`=I0-?s$ z7V)@54659-lxgL~yj-hgaBj3|T4@F@nJMYLdkeFci0K--2$2cl)y*#442(1yxgb1luR0n(y>wfjnj173 zW1q5{HQoRQU{bG|jbgnF`E)eR^R%u0@<_PFAI{!M(TyE|!-z^DMPX9OI|7IViH)FT ztCRuP$N|+DP$aY)1%?j*ED~C$tXFr|W`6?wEF||~1y0*TM<%(}CWVK~8F27PIt*Ag zt)B?gz0jhmeD?8R3gyj?(P<#D!!HMzAIT1FbEcQNgKXdAJEPKeCkrDwchIKk zm{@hCk-CK--vA9-jP98uJU<_Fk4fkKoZ&N4dpOqJF+kk|D`eWm2j7oVP(JNBed{gu zhvzbNALJNWadpL1=isB@hLUtCkg&{I(HFZZkUhJwpkKHFR0@&+YCun~EDJyaq)3L? zL+}yv_%+der036-5f{2$z8kAhs3K#ErOC}8gs9#PG%nDstX5(AsD^l?|_pYGUO9urhJdFc9_ z4}io~i@rN-VnC;tBCIn%2ZO9%+DvH1m$D$6P7;ukNQK1&^r`dtz0iH(Mcsr|B$39rP zQX^Ah$I(}wGQEhF`Z}2h4l|celQX^f^@Uef@3qqi=4uxhD?N|RWL~_VM^-jAChu^3 z<5paKMgTQ-?pWLSQ{ex^CyDJ7tF#p>HHaZ?YWc3p=@>J%w$HiPs`8!FnFM9+c=W3A zR{^JMpNQCT>|*<_Y?Vu!@`o**rjDHiPLGzdU&jm2UiSu0_uVw3r)!edhrm;Bpy0b9RN_l?U=m(D^1TU!ds57_EUy=?_&ZacWfE27PPmpit>-08;ni*NgGpSVJP zmTeKO>hwbe&O^UE>JxrW8ss0ev#>r|CvHm~nnmaF^=$t{_j+*{hnXiN#>0S_mvoSO zp~gJJ!rcQmh{)}|)?3#ZH5F{VcQ_#BRpuPmQ8S8{bGJrVEutCo=y;a@Hy2F8s9 z8QxCTHe6&}ap;QfCQp80=JmUKd?!V+GHrLoYYEFRlS|T?G5R&3OKGURigiB{=5!uT zQMRw@UpSk;&lhgPZV`mmI7eMrkFEaFq9Rv#F7=y5IWPEN)a!mIwvj*EUG&%6vQ`8l z^KSuF`ymc8wWLo#Kr$Bw`1Ct>dCFO!zUbw#h5W;^B(s7jMzBSToB!%h0e;C&s*|V) zinX0WRiWvO6V)b>{()b%wc3<6ZZ~cV7oF!d?+k6+yF})Zg-0FdKW#oh+K2BJTzcy| z&gf_;H^CBrI}`5CnAAnfVCwb*Rq5x4O9{(5bI2{qK7g1ub5i?~x4Dr_K89 zpJi#jP6vlwx_h-(Gn~54M`v7BoIcJ9A-^wG{kk$wdOAWz-uI^dyX;!mK7FuySUt=< zXkLFfkLh}BevLeBQ19IGKV?36w|=ic{x7FM;%Tev*M9Z67t)D?((8mJcw}espVf4h z*ZB+ijk7H4ho49a!$s3y7w^2k2OO+D&U!yRzBBmu)eGRN%gyUE_1de_*$1`xty_a5 zRUdq~!1GBZ;N=n#oW+#J^U~4|h0#tJwP?$xn0G zoJQC0jRL_tCyIAF?|4Y{&JqLB=s(==vjs zeFk!e0JS1O7EaF9%s%$XkWv3&ni)uTHg0Qnus5k25Q!Do81MBojpbwp*{%<61>k(S z4a|@67YHG7D;C`jzzSP}B!)Nzpa)2>28U||hZToLHfwz{^WG#03o{EY3JHTLfSvrQ7=-gY1_e&+0;#B|lX&g8$^&0KkvoZ?jkcHVvHW7)WSwh^HB(#?>Xb26Es1 zpClPmBXZsqy0-^xIKw-+jXJxHy88%mLd6-ejUG)7Pd6jny2S&ZW8wNlp_oHaumSwt z;PYg}6|FW99zCJ~sVa`P3?Y6vivs7MqniUbv(cibW1<0AN>B-u6yP8Nagq$#f&#Ju zIEh%G=3=b7;&8T_XG32UcoPK$IRZ>}fu1#k^``-Qu7G2+*a?l`tLfP0WIT^zJpAu3 zziGx0w?GB;BFQvxA+YEjGr&A+Jo6pixCR7xhIg%jqPuHuwIBT)k?)aW62>5&)A0E{AahI7zhsEX zay$>K?Y%}aZVebH6dBf%d`=2jMF8h-Q-WHc*BeREa!?KPINThxdD0|eSZZ!b!Vg!# z>KQcNJh-fd!P*?UY8&-q7&y+CcJ{11hNeMcQro}#rnW#yg(5}tVA$qRO0LM}eQ29` zie5rW7aNp>D^eNh1gj?lgzTr_^`x(n>D=3Auen8&n$`;1meM#>tvB1A$|*unsa8gd+6;_}Jut^JVBkODcta z5`Z=f=$49Nm+^x&4OcQpvN?w;6*m7J%8CPEcZ1UC=d9o5;gQqf5=3GJ9PzpG|&Hs4Y=7anZPc^Fpm8sTo@r-=1vZ<5sJj<20_mY%3GlkiiMP^Kv(Q? zLo&=gh2oXxChjQoTo+f}5#R$T&$*9U%`VV_k<{Hl@Qd6ZW>5@7&bEF< zi(3T|5Ua7J8kYh<*$p~r&i=x)`IklN#4H|KnB)g z;lk`TP+lr0=+hQqv(;tj*Agfa6j}VAU|j_li&4Mil(mk3w9w)XBL9Fd86Kt14wY$( z?qMg;6NyCqh>0SZa|aLc)2qimZ}>=2H=B%tIgNp_lD?0?H4k@+T4^N4#(b_?w9?{W z(&Bs$4ZqF~>8{RHYiTr1B{;#x#Gu7#twzJ*!t^qSaD|4`k`zb-G0>{fyu$%MNn=9N zn$c>Sp92qHiWc~Eu%~N$9k}E+2?l+NTzzzntF)OJ_cnRh-|eDZg~;+ zcC1nNp-liMX017*t*p7$9e=$Aip$pCT-IjfS{Ia32jhqb?yDmk#uHScET0-#QopbIjSGLjPW3jiTu<^SWA1Mcg(<@Dn0Pmpy ztc$!Gw@MyL{C%#$Yul#NJpdShQM1%wl|J;1qZ$8h$R0@DuW55 zBay}Iz-mlV17~Xxe!jtA9A!8d0E7WR+r?##qT?-~F$fR{d8T!-k9voXc~cJ8EJ2*J z+2ro8w_BBM?b7Cxfxg@yWFE33K9cvYF8(mB~MAX15Wr zt;f-mM^j`3?9yuRTGSKW`uTd=P^{Hm>9F?8N25I^wke0=JxKj%r?V1=e(`YkI=L^g3XzNh#AwpS^P7rgS#=G zy?Fw=X<+v(@@($Qgi55!%)-$$4HaNTWr1a)p~PUA=y;SyY=i+k-{SMb;dn83e5gtk z<*mVjtJ0Wb$E5QFl$&a?Ic&jvVxH=F90NGZT(OMd)?Bun=^Z(iVfZ6ZwE!`ZnXQWd z(GwP6pj@GfpRNiEHdG#48;=98cGIqq=*BF7mPqYZYe~J?4p+i5U^Oqp?TVqZFUH%f zVg0JD5}Gkq`zsA%u#)}NalyDLBzT&*0yYbdn(xROrWzUjx%dS$sGjO45%({j<^YD7 z=|WZ5YUDB*$2xt@+!lCrO2qyF5&C6m3U3C&*%HcHyiN<-;3x?qHs0`3*qBrGC5LU~ za&3^!Kw1zWtSGx9DtypMB>p56>eVzz;ZFqHVo=-S+~0Vkyh)O?MV_-s*|`-N8^HAq z#*?{;8D+(~`;DPyn-sXosb=?z?l+0#HdW?EK=5zKuWb@tdo^m!m*2MMJb%Bi+A(j~ zRQ3wwYlC-kNB<-QjQNLv?vLiL-(M!TVNrjKKI}?Q{&C3M zwfMHne6sTrxQj3O+ZwMe2r0h@%lRGbwT&#;gVOEFEBx^m|NT{b-~1%f^24^L_?}zl zZw>K%#}E72Uc1RByQ!I*9-IfoUVE{X{x<*i)xRB7XYSQfYnFXD%*#AToZS4}d06SS z-;lXqnR%%4>%jEnu-^6V`nRK3ncIYt$Kdk=mZ)QboMR5P!=I6# zHaejZUV(0J@OQkRYbTqcjVI>l$0wOaXPnU8lYn31u>U*6_JKuw#7%%>7edc2GEeb0 zaS)a`$fz@7W1Pn6Q-H+DvsApk8i%3h?CIYbR2_z4gNuPYx3DC<(7^r%$FDqV!h@VK z(!eTd&k2!6=Reh;djRapY8>HL_@FA>%8hdpNo;zFzr?SE5gQmnT^F>#GsMFMrwxo- z;v9}#NArawe8ds1I;WUA{de;B6$FNVdWwm>8qdHV(7@2Ex}>Z5o4awTZUp0zxS~FR zTztfdKwPu0Us5Cg{+m4QeYo+Vx%ETdJaOWrf5f@ig#DYwitxFz=(-j=z2@_VHh#qQ z7P(E%y7O5-kE5aHvxAsrT}M~J#Mb}Xyn@Da;iPumm%nNcioX3VN$^JlL-Ex;qUz>@ zH#8p5QnCJ!Jarm;diS~p7pU>j_>7}lzp^%SBO%eS5r#hB0UZ-)6|%oo`8Nwi*Zp zu*PVK1U)xw=9t0=`a{?~|DloV?DaomJ9A~&;|o}o3O`}E3PE>uN?SjQQ>MN-T*#4C zOqFT1*y~F#tdxt;e^a5FA==UzNYRwLn5Q_@YGHo8ubgW6#4P&a-PuODV^8MX=#MWO z^*D#~(#hqSVx!lwOz{TGf2EXsvAr=SX1KO0!i=OGS4fS&e8iY9$rEicl5oOA@~+0I zzR#J=P?ttxP=CC9Kl_zt(!j8Vrr2+U)rfg-?Ze^TRGN07*R-qcNlu3n;aJ17(?tt+ zW$d-#hc0b&alS%-z9=<2%FlP7diWpqfR(K&32+nn%l7^={Rq)cVhb)Qtg5S3(Ox2sY>(J`YW` zicO6jVd)C=A^eg3^eLZvBx?`nOpX$KWIp82YEsuZf>dVhVO@XQSDA_lLI*rUK@6i*Lb%Q5h72E_{b*)~PDMOhq>}8n3 zyN%C$%_Y{C!|$~5BHyYRD__(v=^KU(n{lPexOvs( zLF78=BEd-fLW8IiHpyOMYqPHn7DM}Ur_@x z-*y6HJoH9_>n!FzD_MOAXNz&j<8zx_Oq zut?gXz%e3|!^D_h%5#R%ZP2}bcZb?~QYXjs&&((9NcXwm8`|Pdt_`~1Q(8aTefYew z<*p4j+3gqjX@b)KO;ak}|4BGDHTR0L<&gFq4eb~AIVfXP|J*qTymu(ine+FZ{rn$8 z!`1F-rhl_9cK=F}N7muLUuuMmcUz*+>zT1HE-!OV#~b4@3%I@nlsNzvY8eN5l)&|$ zfm5*9qiK&KtY0OF2}ESrd8Gn3dm62V`={|c>F*cZ(6?CBt1PSBtejUCG+xq3cKB(gJ6|8OPq81Z^7fjF6@xo95&E|v z1}x_@K4L)&`0WOmN~Jc$={%nP{TgMs*g&4J_DAJIX2{Z%YTffUBS->zp>bl_k_VD;GUoh3dm$6uZ&sm%mI1q$*)M?G25<3lAD~jF8_avM&D2?pl~m?h7L!XP)wy6K>7yO?+m-gi4odd+njKHSas~!C zU>~YFYCR+5DY4tdvLCMWfc&%Q)Dd14S(}+U%UZOoBd;wvNq>)*NLe(2lkL*8p|lqL z%Kj)m<@@LHdHCqZ?_WANiEbDz@948UUvN@(lnG~FC@e7`IAmzBH(g<-YW`~BY=}>3 zH2Q3+PPyR3wIXWS464xTtiWpuqwP8KvTNJnlylD-GW$mSH9f`YRJ+12PB3$>>~F)d z`JW*S>Uxus<@K!4}8TjrEE24C1?l?|;NzF=F;Uh2bojg?D^U zr#q?kym5_FMf&srE>G-M!Yw0x412ek;I!#wQ*q9$i6!~xADrkCzNCgy{D2Kal}3fa{wlS9p8$GT`C^17aO7 z&D;K64)8O-!>SYDwrdk%+2p68c#d)?-_5-aW!h^_QN4|ivsz|nj5{%SbL4MB`?Hsk zm2aFX02+JU+5yx)=CY*YBB0u>q)UM#v|rx$1ZLlZ&bu3cf5bHPFd&1)#*irGck z7Baq06V?^h zInvnuurxE`ZhHCr1TE&byvr_}F*D-)eocJlOyqmpuUcnK!`7AUKJSjH_D@*fDsh@Q zvTL91?oWYpCQCSLe>}?jw<~>dM)lL}HaIsAIeqz)<AY_;273)@(e(`H%c% zeEctxFIVuZv&`?Y=W9b;j14Za^E`at_T_W_Ijr_ed{2tgHe9>XTvd{6(hczQXS_Xy zVlP|Yec4(PyWN}XNWcW%nJc}%Gu`O8+Ryd~z=z(Pr~J_P@MfP!T7KXM4rL2!?}vQa zoBA8VbG0Nq|CUcvgdq7OAf-eAp!0P+v_6WEB=a#?z4Jz>^KV8cim3}i+4=Z3oYF)3 zvAhHo-H#{HU8MdpcM`8D>$_-rx(*X%{vOJ#-E;xKvMsdTtozU!3E5|ly67Cc=<#Lo zJ-XR4124-DR?Ml`3oNLWy%Va%RbYU6OX(s`V)>`&MVtt4ul!Mu)0B*6xs2YlyyS3?=BwU&CIzMP z-V>;TDO|zWqxTJ6j~@KHerB%$xX)0%*Aib*LtfEbw@=ne@tuF4LbT$CO!@b`B9`TS z*19r|)51>m@}E3}T?(XCmwQ|s72i_!-p?y|4lA5ADR|#1*vc!}we@*e^}dx<^gB}Y zr&A1AR`lgna-|b?>-nLU)a$p^Pg@`Uxf%iB1lk|FAS+FTdz*}B zD$ojw0HlTin&4)fRk64Ip3}W2I)o9O1Q93#Wl+#>;-L5>#3y_V#A6_S8DxhU2w5I* z!v}hvsl=cObCQ5Ing|n6eQvq3Ct%P54KkX?08nB1;2=YgVCZtfKIfpFAz?HW;l-qq zWu@ZdF;J5P@~s9XFB4eJhjF4nBA}p`K>}6a&OB2>cSAxqP>_QmVHY^)9SC4et&))h zs?-%K#_vw4M>?QD$>1Qbd4iv>)Spca@#7=%Si_^rku{R4b{KVurC|Znp@{2Y06;ww zGzeHH$Z3Q3sSm9K)G)WhvtWRe*zl^OS_D!J8&Ms?Uj|#pyz#tNb2o%VjKdJ`Ik z{mW{e>mwLe!is`$wC=DN3E*XZTh@$l7OQ9(RnihA<@)aoz^HC;<6t zBFxsqBKMSSFcp8NQJ3mKPtU zi&|z!!zpbD!oQjkXQOc-jp6^au|BtOY!Z;KS39D5a)nYmiW4siqap5$LTE z@fDC-A&AmxnjQ92#7Rr85aa|!pv!dz=%%BQDiJ=RtN?Cx(wL=8(Df@qu_qIe0)((m zP-V1M#NHHOd`f(t)0`k?(|;xQd28i!~?Hp(=(9<)yOZT0G|qw9xCiJU%oFr*rO2S z<}#kqHjx8DyxY^p#wdrW0p=I#@k8|pLScq_VLjMP1Y`!G)s7U336n)nM(G0G$H&kZ z{7B_6>EtlAJsq`cmar#a82wuowwWkSpc6ycX(sHptf>Q zWoDQW#)9eP-`Z&h(-z)W|zPHshGz>Uzv%G1yHy z-7DC160XSVe*?B9z}hW?Sb6PUqE|MX% zMdObjx7|snEWVEe#8$cgs?4oSsyXefLEgSxMSdU)GS@`J4y(j&VWQCUeAxs>sRZWE ztF9+{EcZlrZSQ;9RDCLUYj>Pz=AymGD&x_01i9aX#qxDIag-vuC-qCh|^fyHp=1Mgew1IKqP4WMg(JmX^P z-6X_aAqaX;(2RdrC;!Xb%f4&R#Hr6ZIddz*)>yh}JHkcP@2gr%5y-D{txv?H_+Br$ z55x-sz(DUK&qArMLoLv%Qa*ShVuMY$VHVYgnSFa*K1VT^AZ#Ca-@Ivt1q2vV7#<=+ z{0BGTMQxAuIjk2;V{Y|WU=Gnx^?XtQ*Hp>FAs_D_F;3TtP*g3*-Z;eB9ad^zr~ zY;~)qFn#DjB;eE!c-(}3??i3N9Cic%0o%Zikw}LZBToHfQzi6zZpe?3XTJdR@Sm4! zA#CrXQ`gTvLJdyL2Bcg}J@GyYTLo?tY*iv%6%e5QO+X5X5SMKPNYh{jNxFtHvkfo5 zkN7+a7taP|7P`_gJH!=#k_DR5klIOQS(JLHN@=RkeMM5=g}eY*bxT`O>@GQq*u)|S zAm2cb$nDnUk1{e11I@N~MsYZDhDMaQQAO*0Y5Pp0gSiyB9iUq8J#)e~rZf8|8L%ZV>?9V**2_3JiN za6Wj-YlZoZBeB$AKE7c(s~JZ)iDcs^NTGfX9EVp7m)r2Mw^> z;NL;U0{YV9c)S8mQGlz@1|H++UtLmXhQ%6KYYVHp@==dnr05<26lnFqT0MxsTUq(~ zb*+1Br+ZEZ$m#6Znu*Z8&y?-s3Ls#C1QrHw#83Coj}O0G@w84%L0V>mxH&_0G)>k= zv?nW(T792=<1QmsLB`aVCTLvlYfpC~ZFmH=Nav*@5vaZ}b zes4eCTTOpC7yte>d`ZJwfbDIc=xrv=zZlMcvD98BUy&Z5fN0L}&rKlzRHVBFVTA2Q z*$ad<=Z8Cwt+~JeBs^gL)7D}N5^GsZu<|KoWDfbC#uZQd#Qj&0E#wXWx$^)KMuP}< z-iEtD!gsJhR}{#(^FG1{@i7(o@$5cA0QeCEII#hqivmwXfgd1<_aMNfC@?|*@tzv^ z&H`(Tb0016m)vvB-!t3;0CL3v7LhRVXLSbS|9r_?eD=Ht3CW-#f!3tSM&lq<$~n(j zFeqjv)!VDn6^R6HgVK5f?lf_y(ISE-5zX{LH)8rCl12gOTQvEPu$w-LyqD1`Jc9H) z=bY2Uys*3^drxa=i%v`N4<&p-uf2cK5ruNNc4TaHq!Ff0X9gnL^k{sU9Hzl`Gk4aQQUHM z%Ja@mFW^5*g&111DTdS*5#6B!;AZ{)qL9eXLf6&~m_M6C8cxx_zLJ(|$5tvDMp37> z|1jkOcw((Prq4ePW;2raSN?1Hj4Dr2`*Zy4LXHWiT1)NIJJ$bhAf96v=6_o4gZ$Bq z!PhGKX!$P#Li4U{>TpuUzt4T%eF52j8->n|7cdG>V#&XFIb*?ppo4B%C%aHs=er&pURatGgR=P89R%ksjI~ zzXiNiz35l(sW=8$?7bPEJg_1%FhN0O_-;6-qn9}r;o!6?`H086v%?EjE6um=J z!q&UG8Q__tXR+54HWirR67To^nxZn*uKFv!l3x_NoS97R2c#_?rBN9n$9;aMZ4GvQ zFMbqzMq0F&UDAH)sLwSXhH4?^R;%!MjH?}RLOHgpcEyi4dP?afU6ZQJ+wA(jab3Iq zc%D&YCIt$-;AzI<&8yQh1-i@trtLEU|9|4mpIZIpd~lWsfp9-GiZWihrOh zt`d`iNBHAHlh5x>m_QUBg$Wz$Bp zm3jYv*5uw^qSwu;8GtE|*Z0eftP3?CXh!pAFEyy38c#-b%1NMn?A{^~O&@|siQjz} zpbD}Ma%LTM?SD;SDbw0{!tM9LL|$L71E8EA!ovFm7{}5|?0aMfd1($9#i^p2Erjd; zqa&Z%lq*gKhw>){@8fONIG>g<)+hndC z#ZVp+6+hYDGJuCnH0$$Ctsv!x+~#=9^I#S=D=Kn{4PYGR^SVf92#r}5Srpzs0!En) zrDWZ6gjd-I<|oa)it=P3{1@At3Hi zFdi3!e8?k!6(>AZL50eKGdwid zck3~81#(wx*DhDf`IN=5K=ujlI36pQl^E|mryO1oobF63?fIjR)FbB*)z7ETozXv) z4xr&LIN@N5fLsNcgrN|{tppsgT{%#0czl!0bFvXj)i>G$q+FYU0#cE3IcE@hrkCF+ z>{x|VBgj<$c2jtAmdG}ZYlg{B$128Pc6V?{FF8>;6eZnHpcJ8iHYNZoWK-`-Zak&~ zJ56^qz9;-8o(P#*UwW?Y@UEQZk%w&(y(YNxah`=ikon=)XC`H`%i<;N>YXt@dLYFo zlW%jm;dwZaU?W=EM^EvC>V#czjY<8|lNq)jB!;q&a65tA)iTdJ4S@n}m*B9T&`;+W zLRAHabj<2TJxoltmKit37Cp{cPYQS)dOaVE(tn=owh!G2CV#Q`fx!=sgg$Ow23UB+ zomMO9RjL`Pup7J?q5q`&o!02WzNXDvme(&g&%C|QfO|>mQ-Ge}n(xkBN6QTO%Z&rm z6)>^`*L)!0m)|;$O$zkT%*6`i&rKkA&2r;p7DgipCAJYmtNFTwZ#TccM_k8Zv4voy zT&4v@%6vD6d3vzP(fb!QhJ8YndNEFIgH&(WJNY`QV_B9h{t)uP<{- z%57jb3-EXb_iq)c@#Mc~0l@4H-Onc#iyAtt__no`wx^Lh zo-|IR_NG&Pb0iv`={#l@@5hW69)G;7jG(W1E9%!%IVx1WseEiJ(ds+y{Ga=GBg-Q^ zmYbQCliv+5>7C2>o-I%6k2DdOIy?R_v0C!FY8JY7(yeM`yV~(?e>>|Ow7WEZbMM)S zBk2OC@{hoNY-$*C{7CohW|p*nq_~-MKa{a`jdh@@wb#KqHt~k>zb2nb75-0&QT~DC zjjF1e%zx6R{C66K2HqG;KSwPU?nqbt8-eA;#TeZ3zr?kezpsW z?b&WbCGnuvty{5j`=Jrz(@_#yue4MDUs~ra(?37{ZOE`YV*A`b_r8&1UWKR8U? zZkHvFRU}2>w`g`79Fc)&fSVjR=YPty2atWvw5PU6ZE;GR5CCg&B)ys!hj{QekAYhz zyfJMM2nrn6`d+!x3Rxi#V?)IlH{^*y#asYY51~h*ge6+t!b%!uT)NctTy$_xs*s#D zmBm8Kj}|cj1()>)>$)$&D~Z8G9`&bGRG8TVR)uwfX*NsTufFJc8*Us3(8E5%d15TtvonCON+AaU-f5W zekyOF$%EVF7P{WcvHpH&98XuGcl2o$@OpykY8>IF5S0IsmQ7tO^60Ava>QwJ4x32g|2&g$9a6jpeYvY+2vtmv4fj z4k@SJql5%?x8ij#@pZ$en1m@wNEQsYQ(xJH!5#wyap2TlI6AY`>zQ!bf-OV==#?s=U5_L zK-B%CAn+^7l#mEq1t=W)j=<#?&Lezm`hI3X8xqWwzfJ+=#@WO91%^WHQIrqPkF1(H zb`v12uK*9K3NM~pwT!qK5+ZxgmQfDIeXy?4CPUysBwe-knh*SsuwCZ9eFhf@cLf5a z64yQtX%U`gas<#7EXuTor6G@SrdvpMLb)&|@-l?u=qi$j-+Yi-FfH#cklf8^+=*}+ zauhfRTn~|XH(-CB!r{o&4b&DfJurAqc=kz#JqKJw7+*sNzyUdmLU72`cp*iPsT}`w z;aEXg$N!VHsvTGQum`m!p8)hg6%*+=$FvNZJ7xQ3(L=K4pdOjoV<1H42hQ!(-yIhNFw!yj*fq1jv)B!6CR4?s4?-VnJ)yf1!hqD7z{CE9DU^Kr3H( zZ(1lqL-`-U(fmC)7A^f0_NHcdyCSVn-vxWBf?jADIh^~@-Pim?1_^=t07zcdy?xX4 zI5Mce_ldXXKIuyh|8qFMmOa3rEO-1j?n2$`3peKKZ0Kk5f<~Ex`MR;o<3c z28CD4!c2hQuh6}VilvKVX5q?K)Sg7Sx3RKU6|3wT)+ROuvvSH2VYI&QBo<9abLx}~ zYS#)175lSU>T?YlwbXtMk6`0Jl^rts{gCsikKzwi`D#v4m)a@0V~8jjE}^bV8&zk2 zRoFdj_up39Y+KQ*x`jl0Hyw`oTXwNVuF*`Nx=c1A4)H0KQO|^}%oA{g_$Jqw*W_cC zvo;%rof7O=z+znvo$#!ogc-)IOVmAGls=s=&|9kh_P^sKSJ<1G^ zxpjX;PE<2^mOJs48Lg=5Ht8o-cq{N2&e-cc$PcQVw#y9fTJ$?t^{PLyIlg;sHyg+N zy)u%X_X91@kAC2jDvH8GYraFBVQJmEtnDKWsUgkrSp9l2HYeGzUmzB3FB>69n3TCh z$vk%S>vw#YU`M-Fp_SFkhUOJM=YXN5_4}{2eSG|`;XJ16{BzAC3YE^UHH8Xyz5*9; zPr%hCEBO=_Kw%8OTcbp!?|4;>dVa7Jh-Uf}H`l)@rb2vv$$V{c?pt5`sm7n7<;}dg z?}N$5p9^WtE~HaB?}Z)QZfMu>-+Fe9dkW}2k6s6w_%xwW)rJAZYtzp}>WV8$>`Cnx zrxEjoEDW|03jQ0(Mbu~>Mb{{uXA30aLhrhY`Pyzg0DaY>= zKj6Fd<8r=CE!H8C_GqjoW4#{y=~oxJ#b-g- zwiUJm?`GPyXHcfm<1is-diKz+T$1*~nttDR5}}0l*TtY}rBsznrPaRFf}gFmv30x) ze4B=o=0)`}e8(T=+?t2;&FUjxj%dmUJ^KcPz`tS3!fI$(9&PqkE~kszoZpMK`K*?> zbviiI6$Jrb(M+2j$Ai~9gTK=$elLEnZvQgJxM%2OH#Mumj=}xeV40#@Lzk&_nMg*@ zn4)X_-`7qqpO%JKo*p*p(K%Da-DGcnylR%qI%%w=?K>`VZ9nw=WVcI;nfvbcJ*&KD zPTIE!@0(lKoA%QYcK;d@Dz~3JL#Moa< zgB((B!Ns>s+)6pkcnp7%TibTRVLl^`jqYii8Iw|L%}H+cg0w-iL(h6pJxe4f(p z{${b68v1upWFWM^>>obcIQqBJZ-t@o0g`Mx`RkZ)cVyM5L`)uYSz%Il>@wGq*ZT$4 z6x=OQai@tyrn^9@bU` zvN!)iEbdRnr`r^m<9xba;9vNhw#eDngi%;MsGSL+c#;6PlrqELq|@7%3V|pm+xIv% zNkT*lY_8vyUQ-;(B+t(1T!1Cnkk zLWrvmZVf2~>KOnkJl7c5R1mN<9#Fj-0+I2>Jttd2zpB{{l|hC!6a=V3{F$g9MFPQ% zg`P_mfEsTAhYuWF9Fo{bI!fqA$0YLz2aZ$i8Po|EO%3a)_dlTW!{vM=AcipM$I6&XlU$<6a8Qw_s0Uit#SP@wf`of<`gF`g{-H=ZpWB9W*xKWSH5EsfQzJ>0 zLlN_m_VMrEa@t0&Kh#)b00I)N%8{g~XZ@F<+r=b3MKZs9V%aF74v`U#k01D#7{UiV zzoui?Ih0J7{IZF(EHzHWP(r0Hs@IVG+%T?73}Q{~$5D)G&_&?A2j4ZuoLa;L%ET0X zi*O8$uZ5#dbMb?}dHzF@_3EP@&Z(R9hZW5u*K~2+u}uk=Od$00IMYUWu5IG-1xVf2 z8^9GGi+&oy4mWFxu-S_nNs6vE2yjUu+b)&~d5W64CJO}mA#4*Gw!*9D08}bo|Cq=+ zpU2{9k%yw6+FLODHpT4e;z4}EfbrxbfW(JMe(y&dLKoTxOd_X0dhiw8vl%jMf$BDd zI9cETgXoL}KBF6b7IaBqL;yknh&Z17u?l2K6BiGXUdg2Of#>9Uur2TI=F@@f9&39b&} zY{|z{Krih9NUq6TEdV6rIT!H!XHA}DOa+{rTF^mHSbDxli$G6OkNj2b$Dg-88qIaNS=3PQy8)rHPfK(F*dz4ZzfyoPf_s2_u zd`cSzJwjZ{IyyBmi)EK*a@q%gZhJ_GOR468*8sPP7N&r7yd3|Rh(@~R6nEUO(ue!3 z;A!w5d{!`Ttb=)0r7d1b57hL&s^}Ojm`|_zFRAiwu=3A=_F3synaC<&Yt`jJ)yaR5 z_r7nzB$Yw)m7)foSSAqe%aWFss%hhz>&Tjy-)a)lOZPmg@ovbD7s;6=YR7$R!BN$7 zEd+cf?jcwJ4qI6%0k_X>OC>jL?Mp%sOuSxRqMp>Hlnju+!CEcdTFVkuN9IzmEzzL6 z1W?WJM9)>@tJQIH)RQvd7(>2WN_@AX{jPZJ^)jOt2T(7{Q__sC0}9u09oC!k;C#v` zqd%-*R_J6CWDxCWh8#^4u0?@y}5iEmb6StG=zi z;Y|^=fC`D$X21Lzhd45s)>vELHb38=JQ@;>NXzWziomwvR4G2MAq#z?Cn$z z?m%pBd*~%(+N52PuziK((IRcfE^YgPNypKR+nz)R8P1RMD7Qal?+zt2#ZrEp-ni}X z{5VnTctDM=B|85)`~b}S04+mqT04(3I`F|ASBE0^5?z$wE?nL&BGb+%bO5U5F6p_q z;NdQ^@=jK|t_#0zhT$LFGluqvhW#>EFYp)T2Px?#($){h zg8LC|ec%RS6x~3U0A&)CsB)c{?9o8{EhfEcbtkLx8Zs?(*U9nInsBBTJ@gUF9Sb{sYUBqg&-8t8_!$FNexaM~{|Ai!xQ$=te8o zM=yp)swjs`qeuR>jV*x3YL=;g50Bwy4c)7c@0X9^WsRSftE|xh1|`RcrN;9q$3XNG zxTLDr>O@7=qfhxJsPD!Eb4NFpC#Y6b)_5mb%_iCJ#^#16xZ1}UoyI@>94f;CCSJhC zc=)EsMh0mEro^(QGHwSXMg~QWr?%;)WL73qmZua~Mxg;ivUlUK<7x27uH*obuYz1fT)-`KmD*=cnZv-WAH<5}$RjK0|{3v6zrd{!l3 zMpA0dmvn|CM%ndvGT3a+C1B2wbUs{a9_}>bxH8{&G#{)xZ^O5cbT==~HNFb-n^PuT`~sWKqM!C^UkJ=vOsiN3pkJuuo5hux6=$BSgDq*r3?O0_S^`FJpD$M4 zEhdvLh*JRCSLO?)X20-3QYw~z1kB*ST=czL7?v6yr3d_^Uzw1E{KUeR{V3;fEQlA| zSIX#@22EE>Mpp79R}YStj*e&6NLM|q7E&{pcAXYi0tQy^R%e`68Uhyc%pk#Lt4A@* zlSeC9*xKKU`M>~30Usp$Sef*0d5i_6o{VaothL&-MooOW!?H9oAa z39atvoNUXS%uDj`c#N*G^6#$6Z%YMi!D4rz{G0f$+lCsu_E_g_W&XW@_9>9Y-aY-E z^U3xm>3+QPSYpRQobx^+8}=l2JwjvMJ9a1L%My|KUVip|A=yDD|E@H@S`OKEUdJB& z>Tcx7fkpOgsq-RP`+hI)e!=Kr5yL_8=x%uBey#K&?EavY@=&kxs8f0u^W}ip`6&C# z;k)d^JGvtQ=L2K1z4xQXIID*Xm3#I4$7R_^y$r|SrH^~ek9T8Fx=#+*8BSVPkDDrw zkpZWhC&v{Gr^neR4c&GC4mSN^!_8IYu)9cC;SM#&ElM`(0ezf!{#hY_# z^7FgZvvKEBl21z)CuiiJ&YrzF!+-G`C+9cl$8X-a-;c0Wzv&qNJPACb`t(OM=l7}k zpQY?`A?$Af>>m$P_j`2GyqdBw38tt1;hN$et>h-z9_0uVBcz)r=@XTeZQ!)c{9O3% z^zV#uh0!}sF@qrMH-G(E!M?uVoN|f|(BuFfCW$%nxx;oRoxg}Jk~{%ICvv*ZiA#F{ z*M~%yZQPa0tuj@8Vb90d=$uP8?W>85c6~ZV3Hdh%5IWU*a=fp+o{|{#G35a!dS6MN zoGOgBBWoI?o4eb80tWv~-u(CHlCAO+q&kkJ?1#t4986W!Rm7|RwuP<~wQmUGubZm= zb;q&vysPZM-lPY<8hZP;B=ENG9oq!9Jr}Fo`R>0otlQn^H+R!7{sK4e`o@%Mt8U=3 z_lFgIaq_Ie}#6(JMpkZPl+7Z$gHfYVwET_?%XwIUz~nv0?%D7luL~ z-=;qeX6XG~yRKdUi|gnqj<@Ye*Qkh{Haa_)&Cm=N3Ob!PZfMmnT5S(%{3zv+dZ^aN_~V(UiQc(hU1GmTU*=0de>WMM zi8Hr1_g+ydt-}sj@W^HodiUMSKHYT~aEBEa^(R^4uv{s`E52VjOIH zyS?E)zWQM=dB?m#-Wh){1mU_82|3NheVhrB0R<0M$%HdxLYRq!dQ_k!wB4wm2ocKo zLIT3*(>4lvW>h;`-)E9Jo`N zopDf0g(k=2w+bR;dSZ~f!jw}5H$~D-jsJ1v?;)-!9Ao~~^EmG{J$@bbtt^SB@>}^s-3tvxT3nB}d{kNWLkDnOB!>2m zZfb($F}?1j`jgTNEtxmH7rJmV`X`gxudQ`;Au850x(4K`!n1ld_{nO9pOS?Qj7b`j zpT7-unwc?=xSQ#BWC|P#=b@@}>O7fCMyP2yo zdoN6M(Wgu5$%^+(dy1LC3e0xFb3`w3HQ<;}%bfi$DfKG+e1y^hj(?J}{$_0`K^4hi z?PD3PpnI(xL7sR0K2S)w>HQbjcc0-{mHX76s6e{cK?yReP2)*Y<}|yBLIDdqsY01) z{pp{+zP6F{Ml|mh1n&4uMNjBH!;a;LXIJmhq&;1<%PWf&vMu<5Xwm--VxaBznSQiA z`nlfh@uo-)D?5!=kQU*IL1A{rfPp-X0;T5Dylr&1aIW=J;i^mVE~Ae)rb(9CTE!^1 zMMUCZ{qtzkBr{6#&cx7L5cm9%SWLBz5ENhyKh_ZJi#fI4}8oesmcB*o>O zS1rqC{Jsr-(HWeg+1pE9&`#UF@u@sf0ie;3Vgd$*GhgJCW+!#-697CwG;%%Q;ua3r z3zxY3B#H*e1b2DO%4gjrtupyY0o(-?fZ`B$2~S0h zftRle7Mg8$9=YUWEkYTdy0y2s)OzO6_r72?0#V^=JCoEXNhjozczvJBI)&RvZvWHJ zj1KusM6*VOi;ggi?oB@mU9T(+i?JS^LK8~auKPwnV5shtA0Ddo;&WuC>b0>TEe=`X z7A>FEZsH7=Tyn^7l6v*Ac!=lh>&LR1S}xOt&-fJS@H7#k$P=a~QpoLeZRE=>t&|F; zlJ6GQp!_V{gtveS?i0$e8Z?=~Btubv$$!S@J3PX0#|8S>Pwmx$lc0Bm#=@>J|@PC>LT9HS^w+!3w(G*DLItzyE{932ef zlG5D7SCJ~5WTZwQMYC7*hHFBb<#dxhIi@>NTsg*3kX2>UO=PQ{aH0qnD<;*cC|LiK ztwJJEi~R87C&K}9*Gu8w%9)!eY(!QTIUVPTZYSpNd5C&*0RoUseMSnBv^g+^n?$LIM15 zBo+mA#YgxxE5$k+(RuUY2i0N(j`_Fb~u%x@Eo3WU;axPhA`EoI416_ou*gr|k7UiT1M|ISzezm2Vq$#U{LdCMC7 z4xy{_v;-wjU(Z&0H>xv87F+8XIb`(_-oi+FU(LI3xi0j(Ss+=U#hl1xN?I67gD`zO$|I4ajoxnq^_^ zyRWLg3AUgtYw>u!6Iqx4dB4IK!@zKPk+%t(X2Y8oKO81(HW81~83TCZrwMF!#PW$tc_Eu-9N=ZJU zaADIYvO9w0TF+-MUkEKU$Fs9!bs49q&Jpn*JvxPV>E3V2_6xf6m}<_-KKWeTezP)y ze?6>5w8%n{v%S|CBk3^E^KCeG*o?R*7oN$KJ5h z1%4cU|C~r1VBB=VU+?seJ2Eu-FS#Lv%NSQFg4si6HeO8GeT3a=JM@W%HE2~PZ@qJc zahoE(dWYjhs&*Mi55vG|hvE|On8{w}7$(EG@dqQNsqeRUKF9esQ2WZ%t3eegM|X2Z>g%zH@A{APehr2ZZWVtL2YpmSs)E`PfIM5B z2vW!JtUsOize)jn2<+o7AN%mGf2>bUk?I&Y>)@NdR``h)(M1$pryv7^ha^IigSM@U zTn>2oTvm1IwHF?9Q$kB}6Ps2sTznmOGD3#`5tSbl&XM#D#LE+oY7j^e$Lay{)-o7W z(Kz(iwZiFLEiA8v)N8HK;kAoheXR@^1NdrZGGQ1vuWkgNRfpf=s|i)4zj9Gt9$7_3 zcA`UxYFm$beGjZnUb=t~6!|L5umRACuRe~iqmFzn*n~vW@hiWfHhyE`@FrZd8o*g- z($lML9B#7QYod-&RYsUjD|l)m{)&TK6F?}r$moo)EO%ZJ+($qYgeMB&i4K3jK^*E8 ztTkR&paNW$`0z)VgZKvjX#sH$>Qh z0D-22P9T6&6EHXl75vKx^ha9a){9otVbxJ^WfWZPVT;_uBtvt= z$KQyc@kNvgL?uDw+U-X2NuT%nk!^_JX`q`X$Wt9;jUGtj#Q+Q+I2T|JUCF~KUBMQ( z_#UpaEK;pgwy=k2a-o|I4W||qqaSC787gqL{B(9z38Ykp@2SGCReaC-O*r8PuEfzSg0YDHF7dU8- z7%*cDlJ6mso$sbChBvmtr^{N({ZlG*kyTcpF?qN(3WMKjN7B znF*MhgbDY+m>DBOz{8=Mh-G!;oAI0$O;K!T3BG(=w@UM~`8Kt$7I<%v+#;Nz;^3ec z7-nJ#5btIrClh>~GK|%7B-sNNmqzGd2pUg9u7CkHV(NB)VtA)gB?ey)BW4totGqWl zE1%&F)j%!}AYFh|6l0-c1jy^qt5Qxd3(2*7-hay-H}V>R>KYLOgzz)C>>2zp4Hga% zWV4TC@*TUL&iIu^XgmKlc^m=S9wAiV3pBFx(U~aA1cxX(5KWAMBdWGw1}srE zmSNYgq?%r9*fNb}n8c&tAcW3 zlyU?Iecs!rF z=ekGQ31{LZ+gOGsP=Spnj9Ty8Je2SF$0o%rIMp^^`rsF^++ z(F9!C+V0_8oO8!LThJtEj10lPKG%M^5vmlf2)T!{awh?i&@KByH0k7?%z zh9Lr3i6;ID=2oaI7=eOFdEpRM1kyl7Ogx~GU3CE@uZN=!v%||7-UW~fi-l2 z&@ER>if=qZgnUr8U!74J+1wEGy2+CMDH?vGlZ!euyai96gN^L2@ebudR@DRVerM^A zN%W;-eDr)x>6Ax}c+VhbBn@qT}`BLo77Prm)QrDnnB^YQf)e8PYz~ zRpOK9l80yXa_CPAbs#Ia#`tSvJ0;4eSl4w&4)Ij597sWYjA~2@p^TTFV98-h)!W|?C1quJR z%IKOMm#o6909wl`F+A&x&;x-&syUKbPjZdInMRD%7@PjB;LSWi*HnuxwA6BBQy7~R~sZ4_<|EK4?tN7GBRGYnw;L|#qfPaqP10i2I0@f2lF5YL#rR2RP)W&cqRg) z5ISWMzKEV%WzZx(wIZUycfBYGj%f}NdTOd@3lhCH|FH82^5EfTRhH8yGKUTut{8nw zl~!FxhgNUtF<9%dufLIcACaVN#2+yhBb#Ai2$r^qN3ICzKksVTf)|IpA`WsZ3>CM) z?~(#N7DK9^#4$a2*E+10p^I?aw*HbeX(@|Pdw>FpaZ4?c2A%2|oZDEzuRLAdnx zhpP|Q20p`J^wCEjz1Qg7XrmLIM2j90y+_8(V6-4QA&B0hMi(ujchNwT{-c4xaU_|NXmbaKmk}P$;f6%t7;zWXpWm0IAgJ>cyn;ink$&i zoggnd-vtW~Mk`<9N}YfNv3NXWfRtYtB&vWW$^`>vBg(hSz@j)?t!N>UtOW+AjD(WW z$$8yVG+*!o6mXz*ID$qGW9`QZHOKb0SO>3TbxzOCV?H(5U=~~9X z<>d3-+fMwiKOSS;%wqVx)by}4cp9HHE#BDcQt;v`@ji>bw7;Jm)tdFy&Dwn17L9$CL&pby)i?;7lBWsdY)kbZD##GpL%}Y zokoL4=JBTzhC2+vje1x~o~2qrrdb6nqNn>0ODykVACwo(iv5YPS3h`VfXVVOz8?Y5 ziEE|1F<>9T0+b{4xtGcr8tIq9dzR8_1-q}w8!^vdqFGPGntRU!U9tD`f-_{u*>V#- zq^+iiwKZDJ&0;Yq!n|?8$|0ZTUfN3)pwPUyv|uEsid_${z4X85(QZ-Z1?PYQ9AyNq zAvPMYfzNP`&p?9oLtr0)0rz1MYa?tWDd0XP;wXxV5yj~Dp!E?!YA2u|!#@Fbe*mJG zfS^C{%7JM6pmZ6K8UUo=eZPGIr~)vmDj0w_XvW?@wqOC`R;e(H>2y*59G$H_;~-SkdU(kKs?S$sdMu(I-(+-q(*VZypUr zSr6g0KgSwoUBwt-RE#i~;9Ec)FxpMN>BLo9Sf~GmdQ)HiGzB~C+#2JX zbu;W5exZ!@t_!XD8U1W1)U*61Mdlw`G`gNOItqYwDnM2c+n>Pt&~4#DB*|52s#rpD z17FkA=}%g5Wc)-;VpHm9xg3n3`>$ecqxRz^wUCpwj*ziZ=FV?31s~A6&wdrVOu07Z z4w6Vc_~K~^c+#IH&Wx{T+Tf%b!Y`P9w80Zg#gl#>3`t>^m!~{LP$J`LDn0ZMDL=jD z84HL!Iu0&sq`bbo#EW7)r5rK^iRNcizw!^dF*xAPCWMg^~hx|blnJK7~oFDlc%g$)ul5tT_zg8 z`=w30+rE1?yYmw0RQ5%BX?2InP>p7OPQ6_tDoupPoyHjMJw}0yl9t_?hcT|HzkZ=m zF=(w@`w65Em_<+(s0woLB&cp+s3xq}pq7-9U)f}`jJcP@VxM*3ZA5XCsC~>eq8V%$H#ZKYi6%xBpy232T?i9l1SMYaE>rl#TE`G z6D&nSpfHVdBNu;$v=}D89kI_WT<%Q>ZE2=LXM{czuqc;nbFU2(kyg_TUo-7iq0}TLXAFPqW=dN}DK4x=ZeO zP?g-22{xVNS8j!P;ZxjApIIRDMKlOqmf}y^h`!I$Fe{c6P%WDxLwy@qpNKB29vGG^ zFEKd!2u#B&F$9YgWklwiGBkN0?lKB@5dC1EDl0%9Uh)9VTUGvF>K&y|XP$aEgia~0 zdRhriQs7mPA=(5V%~V>y!1>DY_83Ue%)Q&o5(e}PnB0(_?^zX($Z7_ty;eV?F;%sv0aJ+hlH z2)qeRmJkiJ7Bd>wtjuM&7u(mHqP_vKOjPN8;?81E+>_s$jRD%?%Rx@{Ix&a^&K))_F-UZYS zSWT4eN8p8Y&I~IHdzn~!vsXSN1DnFSk$kli?ES)4$B_8 z)P}YlpxVWf&I>eCDwYT-GWh1ytv^%IXXz6NfW9t4;N75q&)EA--kuUsARXVJ_1H&K zD&RXX(uZ8)hQ!DV65m3=*oc`lMI;yphTCZ5DQm25U$WzyxVSn+E>l4WZ_koANf1WZ zPQgc>ZHZ$NL;?P&na9uS`T+Jwkd&w{m3S=V=}AJgU0lqSj&FQyTBMuHUq|TEMvCyr zE&o_kC%EGWf;$gwHs|EdVNNfaPkyIFZep>T22jMS*EdAWt}AMWQp*g`JuH8kt{+nu;o>9t>t zsDI)-3%q;Ul|3_$4!oq_SMzC9Ta3r9`V#8MtkUZ`;-<`1a|VNZevIvEr?Ss;wLoSc zev*M0UEVp84X6@I^4xnN(N2V#D(pI*7sk(Mx0oCxEwuXy^_uIzOzt)M$r%u^P&v?n z*J_6&--EJqorp~&Ynz-UFgayw8wodCu_y1CgB_rZ03F1LI``ygQue1Pz`*ewB?I8$ zG3h(h&Eq$pJ`PKsnFAoV;2tuEpX zmw12)pjuN^!REp}jhOix)JWgh_;E^+Ab_Gstk~CgfQw!ob8aptSuO?eTSWb1H+j=a zIiWKW+DjI(G0CfR*?G388E+sy7VGbmrz8cY3~0>RM5yQYi5Vd5LqG7vlMFxx#dX3N z0dA|?qudl=RT4_YAxN!^OxMBEhinN(DoK_-(IE+5!M(G>^1?u+A(NulBbceA(1$ho znmZ~>TJK9ns3Nr$1~(IY&4byG!74JHV+X&O2I#^**m~cLxl6ZQbr#kRlN$C#OYaml zHfn-J1K;&Jv@Xy040`}1*4FHfbXuVCTC$~8Z5je;OKiObH}-9YnHp!JsUPkx8m4|9 z=OJ?Wtrb2aUA_~WGrI6D`CGAYizPf1rC+70_+9oD_^ve^^=wBI*#vwU7MI$p# z_q*Mq7rJ3d7o~AxThhn5=RnaP5y1$BJctqbXctsjyO{3GL+Qn;(&c(mLTr*_fLe2-xI&1K)dr)+Vi^_rMOeBgvIzFF%94swnN)_bF*KV1ap4G z+pDdG)GH5tdOX>gkFZ?Zyz*FC?6ph&T8 zn>Fc`qZ?VWa$QORqRj>sJqQiEr5p(pdSF3ow$!8@{rm1xu|b%a+=wqZZz(|^~}*z`sj##q|LyQ#!yVknk@Xq}1+For4t101b69uO*P{Q7@buM0Zn^cLl47 z%|GAFH+1XIz)O9TzAWr!NuI0%m{O&Ka6%M-T+jg;WN~v!Utt%!a)uM4TCDoWQ2H11#^G>fky5_Fr^CE6 z-*yX&R#p#yna>>! z4|aBZcBw6bnQzuTc6RtZ0%NG8$Hi>F zzENS{sj73E4eY9xyUd!oK>j|Fb$7|Y1C%kT^M@}tT6aU){{tG68?fXT78_o=YP5LGt^5W4oVC_f$Z+;Ec_sP zjD%jfSK*+q=e8=OOf3ayl3!BtYk&&r4$rDk9Vn5>=S%qu&1Jwyo|LF&;l9B~bIMez zs#JR59HhsY%TPLzdUL`(JpfJ4HVmL9c1(`>9#sK9Ts<bYRAOdsp*_&wh1 zyi{ylI&()&EY4bFd)`XDgAJaAeOo^sm#U_D21jFoH(!X2I7q$8A1*s<3vza^4;Zf> zt8yNF(mV_!tbUQ9eqCMlcv*)lO1<9OkV3Hc`M8R3bPsV4C*hkKZQdHy@4;^;(XWUq)KPmYfdjT!;M*HS6?put}gKmu;{$H zCE(NNHTz?sLU&WRS@hXd3LnCn-E{CMtMq-d&k zQ-`@6Lrah2{?0%sZkQvGB9~kJ3L9#Q3O~>Ak(YJP0X?{K1!&2spOe;T*&T;~>6&dk zq$23YkIU-j-Tn)*XB#^2C!?#nH_a6`Y;ixUDQ(zt!9@@8x8$4D74?4NB|TTb&|Li$ zInXT*DG<-0~XwPIn{2UKc}%x}+FnxY)f zapgV=>(2G7ZO6-d^}UV{6)RcudeH(bdIZKajI)5 z#^747Sl-Wigpw?y5qs;;-Y+I?9~%xlHmT?N(|`Y-8mnFC{!~*my@2K3 zJ%fzw_p()Jxh6@aQ8Cola|gO6gFnAzMOt~t(TF485H5fD_+}r!AoKncnV3uB zq*jZV2f?~$p)rUsU<^cWEkc_1Z2#nO90aUYzx1u(gFOEXdc^?m^7c5J5(1Jm-eY zSuup&RqDcrcy?KMxn|CSk0R#Elk8+~Q7_cIE83 zYKYIzD^&?}B1foPqijY}h?rr%Ajd$kZaa0*MTEnj4Ec7|9kdb%DFw@dM*7*1i zH^pnwj;r?1*RP&lBcFtITZp$Zp0%}HtEPno{<&uR+0i!I(Q_wXO3>N!Zqu+qtV20m z8y4PcqF~b*mcK1O7z65!Y42^R|AY?z90Te%?C2-H`5Y5A6m&Y&7(V|p$(RqT~rMsK4uVHEL6*Wq`R&2UjT3*b4 zyq)>nwYYGzuyVV;-PIlQVgdKxLgtHMcg1DDF8J5K3#^!RSH-V(U0+%Mt!l9=4QO>t zWZvxLDsEn1?NX60y(PxtSW#H+viLe`E8hIMleT0B*ql#O6CkX$lH@(O@cm zYTn+3z8DCeRI-X_kp}uFgGxd0spBAkjCb$|e9D0!A=4Iaq66Z9!Q|?ddc6DqkSG$S zGGyfAqAJ6GA~_(%t2=Dj*PIE=lB)x2%_59Zg1oJN-Un+T(_s0P!^!y- z40c~_BbLvUaB%=^S0Fqh01zPPi}M0F4Y>V3%)tLVFNI+H|IZ9)#F!D;c0lV{KPUZ9 z>*n;#TT23MrmQIl5JVxbG;xY(C>_t0VWtgzP)d>^@-hvNcq)Db1R`K~odxk7?tXL6 z4B#CI_6S?Qyt$+|abuWf7Nnqd(n;y*VUQ@Rd^~z#Uk~t{2_C9*Of7S)7lvB$u@9=? zQWKD<1HQSh^kd&OP+5*mfeD!`joP9<_1Y5f;M~9{>~WBjw3(bN`Z+sWwm9{RmnOw} z3?vyqR**dfHg%@e&rX64X^MoqBk~%=*djeqxS%83iSWt~&fmtY&NzEj`w3a_;Q$2y z(rO6?qrEfUdf#?+hBsaRq(u-P7fedS)31*<*kI{j5f9A4n@T(h>yp zX3{9yZTX6h*b{bfU^QBgQb7kc6?mSF*PCoA-ZGJ>gFj^e7}-av zhMx*q?q;=4t4$_ORGW|}0v|;Jtxi+;T%TEhVBZgth6XAPJ)Q~OV-nOOQ*56(lJ?DT_5&QtDWDctP4 zvkcy7M-@A4^*8<*xqX?&gaY7wD+za$QA!^^u)Ol9fws_}ST&f;R2y*qc;vX5GVx)8 zM3;j6h~VsB3M2tOq(Jb)zUFx}i>GN{w8|FQc`t}|AQnP!@J&9M2)CIylLm*2CbIH^ zXigP?OHeJ+I7GyWR&h4!iw2+Ic_Z6E%uGGFd?3LuZ7zlFb+x9{PQpNNG4j0%n8Clk zPcZ3CIe`I-1kwt`ncmooGmkXt6@S0npemiaa&LoIllVKG+eOv8_w2Y$&^NHSGmspmb`9QaNjGF}&XNFQ|7)wZlnU;5$sy#?W z4G=8-zI>B>4#x1MnYg$~1qEr6LG_>GwqC%6lW$d;-g*A~4TLpJ{XI5WI#t0XzwK5* zBG$HWl9SeUe;R@cfJZpVZIOsg3SbYe>g)QX2(=Q<(!KI72}%xe|;?`H{&F(*QsV4mesR>Z@VY|p!+*>`IJZREJu{%Ak@F=%N3td+ zJu|?;#v`ZUI}v~?&ik>0{f`+4nQ3G{>EzKkzGntvcN*VPT=A%|{>Kb772uoQGXpsg zj5swL@r!+8X8!5g#QGwcSYFMK!PAL3jqh0Wc{HRejbEcAirM)1G|jB1Q*zFWd24v| zo_J7X*3OkuI=dUV>X?LYofpdC@f(I6PQDeFDA!`a1{ ziRSlz!k#MN$y@f-KB)aGaqK{2V=z!E`Tj+K;3IkggAwyD4XbIM4tGSBRq%`2oB$q| z2lCcWqXX;Te6O}q)?Jt_YHTWv5|VhlV)^CngZYQ?;_uETRm-u3e&1^88~I*~DXHAVXAL#^JhFreEmW^8^AWN4m+y z0clO2S7syt70=)bw;M6zq+EUW&w&G7lD{O<6;{6Dw6qR5iTk8fTk{FbjtmC)n$V2+KSM4i(bY_tA& z6SvQC&Zq4kXqiv*YBcfLkUmXfkehCfsHplKdSp7Xoc58$`F*6Krx8A5TFlUIO@b4! zv&H!XE-*}tHqw2{a(Q_^Um}Un^D8B%>+H&Wk&>?iR_5ln_xy`tN5+-4qv)WH zytRiRCa>52l>RaJoo5=M7O>FyA&B!-(fj2c<3@{QuoX?Wcl0RDrWZ|cFLSQms~! zd`WPj1rUv?7~%6Gs@wenK$P5J;Thl0Wz^wR)Lfat?@F87!^655yp*H0h%`7|L2LWs zXM^8PI~=)!Wg%k@wSk#?9IVDX9jn9nze~3pSOZ1d*OO|4!uH|Re&jdv&Ci0YwqE>% zXUctz$tUTR?>-EOaap!82>Eza^egN6&9?Mgk{aFoch}%srM`cGf`5h1Zx{Q&S^T`> zLN~G6Ps*x#lU>d$cmI}ud$b?GcD=OHd(k3t^LCFY%=kP4c2%x;f}0dpM(*_IGu@C< z#K-Wu(XK0tL5^cp)k_rT%j4m4t-IBVZvUE=M`wCoR;p~tKbWxG znp?cgyjza=VRv$EMi(JnM!vJ)+XEwlXOhrjUYeG@bS@415u|!zfxOSIwJS0Hg=TVq~Bd?~AD;9x5bb(hq;ZcJxDcm4byn#^5Fc}`S zsjF&_Xt0Eg8&@!ToepKTK%T)9VBLZ;u?QN4VYKig|HYu^cmmIO&{nSGY6L`iWdYlJ zD3i-@O$3BDI6%iT0OLw-<3`?XPd+IctYMBZvxLZEqaPt&{?-a%8H)Cmi6V1E-Nj&( z_k$2%A_8cj6&>a(Q~&4P3HGNb!%XvZW(5kNsa{sr)80o$OQa$)o(yR(t_hl zu(5Kj7(J}tmc`2}`^fj;xFp`VB0xN@L!8rsulYi>5MA_@1^FN}uE{MvV<^FKFV=J~ zO8ZaHld{AS{{-BWgpA<0d99Zt(D-k>kaw*~D_QYZ!7l*AIt{_e1bngkmT{Ld$$GrH zVEPn7KFEb-9C9Oh&5iuPUWYOy`9Vy`dU+(QEfPxq@{^1X^Fc~TOYlR2V61ckR|T@4qnSKDfuiPYMSn_=ZNqxwJG>J_nKP5Xj!Cu*?CoN_yKmm+anFzx4 zd5Z{!3T=u5NOK(?S2FPJG&AuDP!a}S5zWMRNMB4QQH7=*L6M=_shM+`g!QD>bpYUp z>@VgxNuu$ZvagF|bJAm8Q{9(e-j|d1WLLM@u>jyQrx{EY83d=`oTZ%VY}kDXDWOI# zej#4<|5lC~z4@@2*~t4v4`{B-{zm)u76D0aC8dPe zFZmcAw~@A7(ccjk#2pl@z_M=V3w{jb>p<*JWZyO-k``JEarxa3vfrM9@>c3{-u422 zmlUQ96~=`mBawyYpuCW@NeGNin52Hi4hE?j(_vCXYIm9${Ox0%gLce;^I+Wa8P-DP_nI7)kp-;Nv;CIs`dFHT+4Q;L`KQrVuIwXKDla($}GCjD%{^# zABO7b_KMGc>Fxi%*)}0wiYsZb#3}VK(%^?&hLmLMlmGz5_0=$U<-X=Bee=7;H zi61i(;MW0smUE8}D(O{PA0HXV6W1g!0urxV8KasBh5;lnU>k%yL%=vCESXHS9lAmM z_S&dWApYG7fV`(IpRtWbvbpF8z%d1Y^t6>-ziFsyC#%ClZ2;0%+S&wKZVxMai1BY> zU?EgTT~({0e22{j1rpGic-?Mt)Tu_?g z*msOwpx&;r>#o0T-ARkx_zvCk@|_7eU0b@{c)*YAx!w6XAAe4Db7DUBt#p>@^jt7H zS%Z51Uh7wkc5hcHk=>BbG6JpyK3$Qy+<0f68KqjGpF$)xJ*xZNF`LmEZKwt+Z{(4@@!kX)z59jDF+^ zA8;$~A2{mOAn7+1>>te~Ha>>nCun|@Z+Cih?+O5F<$Kf~LB0zNl6nt%KN>8l8dMt{ z)V%3=Cjhi5zzbjf9C7p68t{Sm(Pt3FAe5xjoymmgP7vaCL;ge%*r#F|&jk3K+xh&> zkc8y$yDGeq_`wuGGfsu}d(gwJdO#&w$5{|KwxLnhspC{VQoTB2n*O=!k#7jisEvzn z2*#IH%O`1fG!<_wSHrhWaIC0gG;m<_UfE@f8S@($fhP9^C!y+-N1l@en8}~jlUMzd zXUCJrxKq$3BK#LqRRBBiiz%Y6Df~5CvfHUcnrT9PTk6NtwEELjHPiIW)6CzeS-Ym# zgl0AarlB>DxD{u>H8TQTkNFe)M7Sfdxp%qAE0nw9tCE9$!|pGa4`gjPrO zSKGW+6{A)sYgRvxug-s8?I&H6;96VKUz@)3TKk%~HeRzP_GxYV``QZW`hn2;g8n+M z^ZNJ1bz(KbG$ithm*`xdu-2R9L{Yrfp7;YG>5o2PsXfuPqAnSe+HDV3jPIoyR3C?w z0_K+Su#5~3q`UPd5D^k6(XuJLw+U3)B(+R#2TsNi5K#eBjb%|oPFn)>0A3|XTuiVn z@0Q6z2zf27YN<%71w>CKEtx)5@D)@(UqpZoTcj0=cTR1UMsDG@t=6qa!2(#x^m`c) z&Casxr8lXn{dJ>`U z%o0hP5MIWMoLGzzwjh5lof!N~*W^wZ`~J_4t9FRH%+@x~ODZKa_Sx8e;l3Ao*T#~( zppIN{@(s;5mhup2@V009t2~RtheJ${3?NxQBrWqX5j<$S z#mL{8B*|^xp86a)?Z1q#jgRb(dPPWL6TJT+|8OY(fV2X0Tuw%78hSAWp32vqsST)_ z*zXkHV7UzRY>j#3c9_2Yt?Knrgh61AlC51ih^DBcZW>4e{( zHypEm9_RCAz4|snb`%W`A+|kQul@Ngi0r(6GiHe2ldxEP^TPCB zIG(Czk=E{Q0U3^aMx@APp2^P8pFbaBwq?j^QaeQ#s>oEIg*}XA;UxKMxRRb&apm;+ zJS;eH@AT^LuP$*{zYp&NTkcY@lT2mG*Eq*7aDdl+tTzLODq=I&SE!q6_Uqxh>&2p* zeVp4W_S*&cZCu~Yf#dDM&l`@rcek-yw{1B8{7|>klec5+|7M^68%6!g?)&!y{%`XA zzxJ(vD<21!MDG4PzdKF3+kJlrpisG|vG7P){+Agb{HhqfVDvw&o5C3A>DGPgCYQ_k zf6M?Hrk$@IJME;CA;b*#r+=`klP&4m*OZ;gp`WLCZ$Z(Uav2qBC{s%2n8FN8^a;fS z7^po=OH3-3$I4GVOsj011Ai}5d0J*X8U7*>7U*Q&tUddI^omwkr_E3LOS1sw^YvKI ztHagn76I$JbO#pv-OP) z@-_sgM@#tJS-4d&XN0QMa@lhGd{P*$`Aa zzp75sEkwtR3dnHnIRMt`o)aHCUEXl1qbng;S{gg2lNO7>>?mz+F}9&3-s3ZhS__;k zydf)2dbK|O6?h5_b&wSzi6vFti&ktQ94|wRsFw?%&pxf59!WIJiL|#z8-Il9JC#5< ziIz7BSc%}@?pj1PJ;X=3`AO`Jo9EPhXjxgtjSFor)6T0!KZQ#mx$CgN_{jSsN||;t zT=j4Uhmh@f!1@LUK=}r`{~937=A?cAYlf&PRbHZL=?LL{V*v4ClWBu~M=o_m?3%Y4 z<{`ztj`>SGT3!8aUh~f=y>xQ@#d9bwt$u>SMVHbN)hUhAjaw8g{Br+cuWNr_F^RrZ zg&Iu$w@PcVg`n;fwQrEn&1FkH4Q&RlQ!XO7Io&HVmJNF0Ajm-;e z;(l%3?b>-;NgCYtR9@xzW%y`j+oq{%y1Lh#FT2Bn@6?cYQ+ z(Na@p+LO?C5W#;vcn8^h5;u7v1@1R)x=z^|K~AC1!@sYD6_zBxlU;G+IjVcM67`?C zmk@T~VjT)BL;IpQbL!f^`%HSD!SI(NdO39y-fKHQU0n*#kRQ8Zqm8=kV_ck)kV-4O zd(w4@R*|?=j?_!i5L(KbzM0~ha2QiuJ6jizh-rE}$iL?w3jl^ZlHXeYORstdVuOLQx-@$|TN|g55??PP+9y#1tIOqA-n7&H~_a4{ftNrx*ah)Ixz%IVvdHc>81s zS4{!i>d-l!so1ZmwXkBTrfHcqHd6X?fGuf|1%ZGHImT0EkntZ9kN%+CQ?WMd2Q;MbBU(VVlYtN zj|>22G1OAB8`#9E>s1iR*BXz>fS*bf;5@qfvq4-niDZi^2D{3O*k8r&-Oi5Fuk zBx!1m;yzc2w;bTJ3(p&Rmm?Z24S`efQ@$243tJp84=P*8D&uC8?hkzh3{n)p(B#q* z>vu*5m^?@q5}|B}7sJqC%KM?O1T47=zgW!P@;laCFC)Ya7|xTUe+2t8S3Q0rWK}i#wc+%Kr<>ZKa4-dllGB#Y z$W;F%kprG#XQbbuA|ZF(Cx~Sy%Bpe*!{yN|dA~#(sNoV@0^B96cy{ zfbhxh8E$b8GBHMBt zDz^J^H8aW9{?a8TbM-QEc3?QnVjC%&_f7U{b=UsRo!o_v;sg z@@>3}6&mN2Y)c-TA2WjV@|#7&7_=4lH{tGHOl+Kb@po5$Ica3ZK*^ESRe*9h?f2hi zolgf1LO+^UJFD3Yo~?N};Nuc!TiTNbT*|;n7HmK2;|Y-b@HTtoIEK%6t~UE7UCTVT zo`XeT+o|Tc+a3wAvnYeOxYdW(?{#5p)B*hGJ$S4`hhs73t_$6Ri@Dp6T$NVay6uig zO6T=sW{`WeN5!$7^zA&^Fm;;qf>@LQ#r~4Xb&RNpEb_wkqnB54tQYBB!d4f!>Ql>_%@{}vSW?Udb~m0 zfYYg(W44*HqkZt`1f5IyGFI%EW}I@8=u=^yWry@##_~cIeqhjBOMRK`v%nzyZx?h( zHM|XC3!++rGBYkJa< z!!I756Q;ymCiwxfQX9II2_c1ox&f_JN#`eSHOPj&#lT`zqY-r{4G- z^gVgv%G-?fPg|oz3Zk->@VsOjt%p-NJP99iG|e8?IiO$dA=$(zyEg@@hO7uEG5N|c zyoSmSNO+BV7QSHc+jkUTbC@8Uw~2@;mWxy3PK6OHnILl;2IeDCY3Qr1npN=P#dQUD z>Dx<)=vBLyvo}n$q!R;V5(u?PAOF7gQ0fHZ$cwM! zk3T%jEIyrKfslH8i8`WxgKp?a$!>)fw^)sq=NC46prvGgVQeiW92~{-+==8XaP~&{ z@zc_Wo?sJ#Imc&J9;-8A!zCPkY1|>1suHSuxv9X}Y~Vl%^;{!5I9h=Y#k?m2iDc?F zmltay1Z)!b1E%Ei<9Sf_d?yoDe!Z6rz1hgd}5& zL1#%uCgY<{5U9nvEbkPtA&l65B&Qn=+#WBG3cRw?U8o0k4c7L8VC!|TPa$Aq5@Z5g zr#XBWU=$sRD0RxkJD!cTJwR0!rbmahLwnMn#H+=r=$1YjjSQ{_$m9k9*qZdP6@p+} z%k)RY(6@CcP8dc^l*)x-6m8$?RSzC!0yq2XR`~0U2!h+31ktU!ii7}hdhy6h9PAT9 z;7Fvf3XZr4O}dN1=^$x5bIt7s>ZTLOy-KxTPTwV9Gez^XkTauTPPYd`{31_MgV3EQR;1)pB6waG zGDlrQ2r&Z_k^;;Mb)0PG6MHZZIp#^CK)N-AG8$MoGEyX+o?8`ciKKiTj7Aj9=#PKQ zQJFV~GSRUOp{8cc;b89UC=o@%k2h%JE+aS62^RfWd%$#qu?4C%kJ>~4lbmu+La1Gi z%M8WUo9ebm*Ua`FopTyDkJH~41dF>HppfcGZYb_4T63N9iS3FX?g`h|1a0u#uXiiE{EvEVvYH9Ss2=FTFgyU; z)Vbx<{nzkhOqThMW)P0RCSUIg($!cXE>|~1G zk6Piw?k?wkdD?mC&vfVx_$g7H3WKZQWIY=fXm^Hk>gSsGXQC86O#8 zMdhrX_=de(My~n-TVSk;*A`E0y4(g@gcd9Z{ffVyc-2E^L(fzvWElxy$-`p8LQt!} z9U~VvIWE^%PQFID*`f=~Vp}WITIrO6QT$MGr2;fu3M}l6My5Dx?ys|P03(y1v}Pr# zFHtGgnZ08MoApd~crKx`@VG9ph*oPQQ3sK3Yq%1YsRt!?V!QQt2w!ujP1H68mI{4_ zwF4CEbj-7J5wdkG^TTkZ4Zu|UKxSU-Oq+@4k3>TktRpuzX$G@6R@@_LT{vxuDo4lE zV0DySt&CSIot029-6()<`zPBP@@% zGm2LpneQ4JF)h}bLW=56@6)w~WWI2*uwH{Wbz=ou%Ur`F=}sai8Nf77SQc6mEO1e= zLbNGIKY?p6nHTf=sD<@1Qo0;nPT?LkF(wzh9o6IHWqyEeJ!E74e{{WPP*ZWc^}Q29 z2tD+U^e!MxK){6Fd+)s|(wm?r5Fqp}y>}3#Hvxm7(xf9rQ9!z=6hVr@oBN!1=A7r5 zc|PyVo<08$JNvrUTEE5GJfGgzVuD_ckv#d9-p!!A7RBJ1&!&W33yu~#w~dljJkq3` z4c57pzpj3}0Kj8^yolUjT1g$osRBL9GHAmdhWa8{IXz4w%oE)mB@hN~%}wPq8{^}J zjftq`w~m(+1AG}8srK8mT2Z3u-=k!`qG4a!pQuT|vJHC<8ex>Zn?nFh>E=t5&ckf8 zxjef2mQDGF_mn(0uH&P&Z8XQWqn6FEB_Z=oqSy&~e4DLA*L2E*-53pem=9|1%k>X{ zBSw_2AgVd@!p?SN0Cr&FCZ8C^pc&Qt)FaFsM%M?%jQpBlgYC{ek{H0Mk^{P1lW0Ha z812Wo%9$+0j%6hJ4gw6hIDPa#N0P?#D7Xndj5MPWRwB2>Q(C`(z;k~k0 zOZlI$fEH*#Gn9}G7HEhy#bH<|QQBe6Vw&_5Zm_!oUa7Ks52;~7emiW3ZH0$azA%&z z5QkohMTbG7MhIhSV~*Le$6qi~FhHsaCiRX$W(2IT1i^?yZbZ6ZD)=luDjEY|004py z;v-=wjdNf6R8n+p93VgxBO9m0fDPn;g~G8g!Qal7P*t%YAI;wYP@rxQq^a>+%OTbp z@!J~v+nNI=un?q63FwN&3Rz$cWC_vd5DWsNZi(eV4FD5jtF8`P^3Un;?@?!s(d z2m6nlI{LyM?!r7Nffz9?KF^OH3Aw@F!l5?6p*F_0`#ktQ))*BUgMg^PAW;Yi+AlcD z6D%-54E!PSUcP)_2p*toE`oD2M+`oG5ed|}CpL73h17)FRZ16J{n+cX}{c=$`S z8~l`?*zzlhHzF(rb(ZUKp7$&)wlpk(5=hkegYm;?`C&AGh!zXTJq9cSxB$}rL?5Dg zLWyt0!xGM8qp_EsFyK`U%ov&#A<>i}=_d`f6&aZzMkZa}$qn>!mCaUL4!)6iO{u317+JiW8Iw3`ya)+Xt;F zA84uO(r*2TPBoWl#A>b)QwbE{)X$lM{IkZ$qJ#&cg1;|}l2U-B;sV|dKV<^12uy3D zcx?l@sF~Jcx1+>D;0z<-y@OMSR!wvaO<_|#FV=s7+D!EYjZsJ|2cqTl_iC}kLDU>j zA9MyYFB|QMFNoD&g(mk-yH&*D=-sc#N!p;PyP(gDOfcBL-`1W{xu&Ze=H#)nk3gFt z)BJY?TSt&v)TW|jCVy`wRB<{B`-M}{R_(;7taH z(`Az52oHxM$lgk_)ds(tbu9vGSrpzGVhr@rFWDS1boK_y*{VgP!=eycg{A9s=AL20 zEQ93{H5qfPS$Z}c*IBlGN9u{w;&f=Mbb9Lvw7WUfs|=#qGwWqYolE7RhP*i{v|(-e zLBE;O%JEUHa7}ut0lAhn72wV^Q{@Dxl9a3US)^9rhq4|&!?w9m z;oDOZUgM33r80UM6@}IyF!URAnRA>&NwH*zyZCt_2{=aFPaO+j-|R{wgY;KH-`P!9f;bdH zE5+dP;WKN({x%hlGEuis+^I>E8R=W}m}SAtq2IlTRa3=P*rESu7u!uVYpOev>CW%b zb4>=|M5|Wh*UTW5yjxjk&r3UhNm%I`Lq3v>i_%XZtwUhrl}+#i6m0p!g=KkkCU2Q7 z35IElr&jqD7NdhE7+njQBYMl>8vNW@*&A$`ehY@t-@Sq~aDSLyCk`&IK8!b62jjPm+@VP7-*RQHP{b1t5&L!_w@eR9`tXna(@o zG{#*=B0)(`|DQ9sJICp~(c-Hdu5LxGn6039!o>LiCw6)i6PGK;sbCL%Cw|tFI+Ug- z8oPeKwXd1uU&bhZWGMWs_E+2#w==H^6G{uRL1PR99n<~d9&?Ek&<{e>*C+95g0k$P+AAb1>y^DTVzN$?k6)QJ|C1q<8K6z4 zs`DXNtb2R*(&3Lp3- zSTx$1aRmHuFg4oHJI`v?cUo;QyXyT|Tt3X$75Ko0>Jw8p)UkygROf0$y*yDK(@NL& zQH3#TnLE!^D{kwdf74i7O!sf2<%|)>RMVMiANmftJabiR=1kTn&Xv9Slxij)n^soL z`MBhoG)uKQqa$^~+Ox23PA&vIv^<(h0zY_8tv|OO1aZ=RXI7E;DDAL$U?q}Ip%fm5 zSuUon`}E}d$LoBWVnH6?6Jie_i$5*C^H1Wh7`;egVaMmDqU~ZRS zRG<_#YAyrLv;A_h6>YV#5UtiUt2Fv0lT^HjXW*)YLNqo#}$w>|pP-R|P^OS*PBHRQ2J;bG`WDFJqk{|2RQis>3V%g=yhxJD`S;^@&b7VYcB4q0|x=qF5quNR7!$t zs^>f``}Kso_Y?RIlD1ZlDE`%_#V_=l!{o|8<;62;cc$AV9G=nUuARo)skk~XRz5dWoLV*)d>OOzXtA7-wV7vdLDb#)E#ZP`!B(L1zAWcvj zf&cfv9Glz9$myTZ_C%H+Ryh|rJ#a!Ej&))SLurOh_RMA$$QR$8_BT{uKkTbdzohRf z=!`h}JV-SAP7)V7tff!XPSk$@^^f>)GnW!3H&irw5b|e)`0FD~k`e%+>_xI)ho%q} zua;3>uIb$Zvin%J%)}M;sU%Jd<&_SpN@Vv7CWERS)`?xa!RZvw2*Y-+IcN>!)Dx99 z<8_`K3s^m!TkH=vZCE*+u=snFDfo}Y0k7N>k({mT`JrX+Ef6k0k%_noi+>$)0TNfz zIq;2adRh7Vn)O+t726y!m}Y%)g`bzroBabYE$t?7A8q)ix0@D2lY#@$2eW5WOlnv+APREWvdSq?&{D zohn&uDH(}s|EbLllf!ZR3Fm0D5SD~>hE`7PzA}oCFL6dl zCLY6C6eqDbgq?ku?F*-}NI8Osi%g;%xwc3eSw`^A$$cRjiRVfwr~o1a;}}LNO7yo4=KzOC|Q0}u;o@7iGJtBdUs3(=q6CGjFzj7mV;sBGF+&<%6-`4 zbcP8$`zm^H6bi*RlfBw7w`MVq_SuFXax*Q)NPA#Yt7%#@ zz+UW4rQYL8lI*okhXBn?2Vge!gfNun`+dy*Y&1b{dS0#`vd0c&UC(v=Iw{h+to8} z)*J4R-fY_+Z#!LX`_5JmEN}Z5yZcYNdNF&rQ}6g*SNV*&KhWm)GWPJ?AG+Vi=ciN| zAi8t!;f|+0e^6(2NP>sAJb$?$Z`e*N829BE1oH>wa+>?Q{H%{@@*yc?xyC? zrHy%}zx&~k!R3{vyp?|ZB_qKhYu__d-Yc7aH@j&&Oa1Hf>e)nUWv75iS=H=JNMERud>HG zr6F5oXCCDwd*zP>0)7g{$<*g5)t5L6Rj3Q;dDrI#2*n!LXGM9}X4IEURM*bdRRz@4 zxeL`d)feJx>V#@z$Gq!0>oFTbX)E=`Z@i;~JnKp7n88KkGF5|^8X%2QPb7x-6_-1P;QO@{wD$W82k>*4nlzbD=`UU z)olJxVv_Kh^zh|>CjfOdTgu-iGD>=X9%-rgPXf?8OS9EgHC@1@-gdOLYCMO8^XzKz zWrws^+V7iu&_iPWD%YJ6{wfnVp_q(E{_fcB8S!cKCJ8%Jhl4Bx@VjozPsnKhGys>8hdagokjVCz{@=?oSIK{ z?Fr1i)+u^WF=zD|Bu~T8m)1ONI)gMRl$MeKKfbLrr+>xHA#Q0CbO5N?g2pUQluV#_u zn~-=5dSU`BH!)b^T~<41ut|Ak)^+$^U6C6JQ);n%_(z_K{Tsomy4sIpg(_F=mb>>0 zT37ZfRN^J_9z1^jn7y=xaUoVRN#+dlUEc%_~Ey}0|!iX>5c@t4X;_8%DuKlJu+!iPHFs=uulep?w5YnZHh zwN(SY)bS_+Q9eA<{uZ0)*T4N#p1V$#WTfiFQb_pGsNkqDN&l+QgjbG(J@1S7NM=&; zG1&;y!$C0b=ayvo;JvDpeKKLg54=-(C$r3M2af>auMZ5pO=~(`kbHk07`)XDwM!op z$-D}5l8BB^54VbFJVV|S>-HZfZBt$Q_+Zg4ZO-YHZAnLn*p1@Pug_jBo_yWmMgshc_u>EtRwJEoS`s(bRsE^ z+b?%m=-7`#dhH!eHiO!2o*6*Y@D2C7a~MJZO`y%H2~BEwJFPZDsJV&b7H}Sd+8S{X z)vB@3#L3C-ixWKV)1)E>qZEF&JW7lnqR7UjTT3}|0G>D*iaHtGf^(ez;fM?m2ORzw zm0^GNNv0O|MtA=q3)3zSpi8V>2+}8(cjeLi(n3xE0Wd_luEMu>8hu!)FsxV&&0gLf z*0F#bhN}XGK-u?BA&CTCB9)@)d%ga49C5sw%lCfgs+b!GhJTTWr6>@j_SFIkzP@np zdQJ@3c%QHxC?Mo}c5dGX;|PU_YbcgwZ>D^bNs~F|m6iIXC!b!<*@Qqi<;M4Jqrhvq z(2j*}l7x)caykoEpNHQ>-Mkl^x6$${>I!BjtMzU@4$2wlK~5 z5m&Xk0#);PEabaNi>V9R?gq++ypFS~f2G+YfyeUcBD?b1@0LvZI_%u6Ze% zcCq`p5SJfb1(!45?3wN`WwjMwz3+{#Tl~<}m~;e_6r3orG@{KY7qvHaCs%^QKqaQ+IB{H@OcZ4E(rk)NQBXp19qfU&|qwy!t z;SHN4*|BB zj(Xvt_ucvd2v=vHl+OZ&@kPiley0jlvAqp)0$A=R{EXw!{P*3Zp@tKzHN?q*1Bk_k zZcW-#wzG+YVSSe?%OB6~OZoUbjJwAp9X_rfWXzrG+WUEjUh6&vq)^XTHMf>>xAzIC zzx5O9PZmLDwCUJ3Op&2RNqnhsxuWmz)(u_ zL`3EOrDal6P%}^eo}-ieeD?A0I$^ba^ZVKhZBJ=m1pec-xw+Ko6AgKe=|5o8`eWed zJP=)B_vLrUm%}fU8BY)IJvKwzzuOb_jdDo)C5)VWvq*+_;$0tN4f-}1rq18pyFN-w z?c3xxxEQm!KF*!$+rB$>F&S}vQcBsst6^|CTX6lm)}VjiV(RkatLxL|)cykxgR7NK z*Js^R{XaveuD)Dd|G`lX9L5>^-C(&nA2Ap>&YAkVeedRCI(6W8jlsWt{1Yxs4V-mN z{reelbG1hK`sVz-!S!*$&EH*v*O!Y^*Z7X(-3ILIzdHsum!F|-MzfQ zxQ79o7q^qgsnG)Qr)GVXV60#q9tD{t!j-LZ*svv_t9D#BKpy& zoy?9v6Q-s@FNuRe7O=?#j=-m6DpJmaWNXiSjhz1OLr9ttBvm>`)r-$$r^CmA32XtQ z@KcFNW|4&Nh~yNT5i5{)Q?mnH!G2yAt|v8i76=<%`%k5t1vO9Oc;jKisvsGGCy zL)NO8#X(i?CR$%eMJ_#KRDvj;OOFWO&ZZXo=PMhc8xF!`*y@zir}wZa{w41rGW0q@)-xR zTn>dtkdUYXnq<)KG9(kk4+zn`HN{2(U!z#@c4~M4ilg9tqh>m2OAJs7X zjiR^@HVUsK;K_vpigHQo871NnRCTTkJqKLOtlJa`fMLUS=`LpyhUMZjmLy5FLZ?3{r+Nfl85@F<`c^H2SM~dA`UcH0})v=-d!a?ineRt~m5)gu)lRHS!ht zSgBPFNdVXwa_lK}i>k#!(=-4<-7H^+EB4M}0?CDF-+W zIT>xcxRuXlmkyCcsEj0~MsGC|e>0)`Od3_W?BgLWI{W$9KM3oaF{(IiZsLTN@InX{lJ?<6r z{uTrs222sutBvzS{3!GkwMw}_sIiA)1hXXhX_M5R%nBE(l zs^W)Q)k^+XDp^H0e1R}F-+V(|4zz8XZUe-ynLl(YqXh8HyC5($Nq-usGJvR3@x3fI zl^7#~e0@)F+wm^QFaiTRc+_a33&3r)`hRMIKne0bIvptjmvVK6ziv^19LE&(zQy8Q zHc~yf$FI~PCr2oM52#Ahf+i#qb+XA6XT`Cn@Znd*v`)}n?`iXoW#o=8qG>Be^pKWW z+-bC&z=gQ}AIH`tVC^9-IDQ5>qJf}h-=ukCTxyO&Cjm)ZY*9HbZPt zbpYuoA&!s_VvW3kH>3FEHZ`ov-Xg9McOeU6oJ6}uw7lTDy4^uuIi6)2qgJ?2o;L@t z-)zcbkKrgs7emdzT*^t7?=YrEsy>@ki6cbag5gF8TRRp^VxFrV; zgwl?dBRgf`YEYbLaPPNR3V0`Rf`CUAX@QuOsz6;*tzTQcBP*fvuu45PR!-Fl`9**( z{nQf_OqPyx)=E=JfyD)rWb%-YR$Osn(!t?z>GFBBhVPO&K*Cr7lz5tv`A~8Uh8Xm; zlN+9mBb1WDazB`VP2(oXwS?x8`WBZ3&Pd{D|E!{n>KXHl!i16nV9AJp@wAZ|^G)<9 zfj8nNof+d#MI2tOEIJEU_E8OE_aD@NPyrk~nF-t%+UdRJ6s<98q$w~2i{^ZGwP*9K zlv?u3&l`#9Uw8xx1&K`#oMw;0H=$OwCOR$~*^@6eh54KYi0F1q`NZV$AeI;?WgDTJ=tucfdvt^d*vZLZ{PX^ zqgm{Jx-WKhbu{^vUD+)^TI^nQ`w>*eV*j)HZpU}JUt9SFpPNHu27W$i3d?TzaxB`_ zzsvSA=wE|9@Ze8>^;=)mj*cB9)qIfXqwmuTQU~zRB5sYYIW*#dJz1#b(7O)5D8;`H z@CO#dlzjeZy#pKC=(9emYQHGENC!HH+_&3RE$&W*PE7YL-#_0vihJ_cnZv+*gqQF5 zN%Dau&r8eEd+x1HMUgH7L{?)FRmWKWBs+?n+`)sbfM@-E&f>oo2aNbml0PUoNjX^E ze6Vp3L^Vdbio7=)7o-o2SugaEd%yG{c>5&Lr_W9P?((G9+mq5$1sCL^<(ok0?=rT2 z7v-JhX%qE!OS*rax*k?@wp&3}O#fW8iI!&*&wdvn8`b~gbykx(O*dNg((W>w z{av}Smod?i_{HLTIJFS#7yIwCOTz0jrc5A)o&)fkJAMR}W|R%+TK)0V<HQ9jfSorC8pM)!D_1k6FO}@^lR5XB$E&^{&eUxFb|4JrBeq7QFKK(P`Abn`_A!75}_2S#F(?`)af6Fv(kaHeSk3;RxHBtwr+q-w$B|qw4 z+_RT8&z=lEJKcHqgv#s&Zb`t&0%~Ri`B8^U!&yAhB5EkABT5=eiXniED4n4xJ*qS< z3be+&b3)Cfi3U5NB^l{j{i!|P!uL7oBnK5$>7zpqsf4i-C2*h=7tM2oPrzZI>&%i) zaA8@Zv*u`ksyn+Jd`B3f8TvJo7;9b^qYii!wb@lOrCfS+R6s1vF6k4em{a;_ zDKyn>s%WMy`edrO8&qsBB94GFD$M`Z!?L)4rKII+aXROemvD?PW30hVN1Rs}`_?JcoZAr*kN^Hu-{(~oi4l#JVhVU-)DF=&$ z2K8qb%FX9wgR;r5U^HdBi7#_02bUPn5b+PuqVprBr#RDb*%a~Jq!P>68G%IQGKzy* z(jypI7c8X|p1NiUpBPDO3`@mzCo$Bf-qfb@8KuGN;)t~pXatgBgY*~T#Bjk>s8*_| zQOcBM?5+TneOWS_VEX&8)Kkm!*J0^=%W=BdDb~`Nw?;EWZ;mK_rBTSWn1M<&zk4P` zYsLu5r798A$a`Uxh_eD66CBDY7{e1~mecpvXyo%KNbC&05Hk;h@TE-OP(dQem9P^$`D=j#pF6X)%-m^sC zt(oXT`<>kIqMP&=R@Zt)+Ii@$k7ge?q!un=$~9COOdw=kDw(x3idp8IWOZPuR*Y&nkn~X{Bsn%fX^tq(JHeeJg#fhTvmfBKr3f=7VCf~ zft6*tcgEB##qi(BH*y43y7Op2S&Vr(AVeN`o!L9hVmOc1 z9$CC~K>-TLit~bZ=c2=_aux3szrLW7X9D)pDEK)kHVnznI4D?UOG)z4dq5T*g29(d z0~JiN(~3FTEd+#0f1!|oc1iC@%uYZdtSs}t(HS^nF>>60&>5c%iy133Jq1%f=c0)~ zMaA3uz!1#3N7a^Y_74AW^^l4nxbi-zL!9cukW#vX{>?>hDp1M6St$*# zz|%b12hATz)8IHtwQ7Y+iVj?@@(S?D58i5&eb)jVby=s(OvEu$ z(LY!xb{9UGM_H#`PBl|uZT&)Qrs9rrBQe#BXI>4;-VF=&we=gd{rNRhmpPwMY_ZIg z&z1`c_Zy*QjZyj4g$cFKh-Ejlo1TYO({WWg{mxBGX#BNbqga+1CjZi;EVF;`n|=Y%g#uErZR+mQZan32^)7Dp&kd4Bb_ubVQr$1%(_-o#c2MpH3_1y;cb5rAKcoAl{&TNwMqQ zHXz^b!QA>+we{Ort9)W>*O)=bW&43p<+qg<(})+p;GF=j<$i- zC)`sw^fI-yiToA0t~Xpcp{22)dnTbF$+`^>)2Ljjz{523NYVK@;P_6mPyM56H5 zV-1AfEV|L&uYc(D|3NmV;*X{jf?8`MGh#6$#!;Mg!A@Z!ZRG1ENzTa8A7NnKT@BLdKI z#KJgeg@cE*DNa^!Po0#`{7MIK|qibXa%9LRrB>_-KMn`$KqFpUq$-{I%|2zU?^SorzYn37G#x z_0|N@-~_U80{O;zHVHoeVz5S+YWks7--`*7mJe&6KhPb0h|T^$g`C`b_~90M(yMBc zdT{dS;UouW%A0ml3^{f2a4KFP3SgTC$YBJ-BmI99>U1Z5+Qvqez9&DNhO^C3{{yHw z$W9}txnMAgX@I(vkp15b2iq+Blfi$V$GMiKDGX;w`bYV1kN6$D>WJZ^NQ2(o_Jcjf zGcgVy-Dw>4@`I73&B`g-8kvFbvdt^|j3XN7Uh&Rp^*>Z=oTsGz-y4)7Fc$&)|IaJ^ zxUbwt7Fh!?{*nBVF(7`Eef=$O`)gSNb?$|U_mx||3Yn~Sjr}SzzVuU%7=;Fty~4%b z=b|W$5+wxUe+0^6{1LGM0{?|{{YuFA-vVVIvFb?kI*yElLB3G78KfFd%O>H-!D*q8 z#Khu!NGP#62&I&NDmCh-8V#`Nv<5Y+r9}g9i&mZ`Ko>y5Ifg%bH9G)^yMbecnkQco zrOI^FKdj(_`l&i>%)GGR+Rt(;Uj6FM!;8@KhXxH`fZBnF?Asw7hQggbtD76p~J z{LmZxARF|zJmp7k=l66F$5aT1Q{wZlxMEfYch=bTXB5ildD;=j?i|Cf*(`!9fZ zeDPP=+eG635pok)wOT7jlNfHD5y;%B8js<387tIk!=qd!9pr8EUO1=~3Hp<;X}8zT zRFDO$7oOAXs#M}pu0_mr<%+?h+I%J!Q^ixUrb7vAI?umZ1c$iSUy*da_|)Z>emzb! z;V$u#?%V$A_@b*y``ra2%yL)r`Viq&Jd1ZK=f?ZAKW8*DrbXXIawQXkrKB3Rr%KbK zNc4K8+@E;e-Iw^#+cE#NoO(ZB&*sc~u{$tR*C(y>*D~R=@9g@KE(c#;#}H{!^mU)? z)KY#VT|3#|T^Vn=`*gA>Y~UNgFX+vPg_zy_h~$)efy6tq=Oxn@6_DVb&bNihf- zYuhe1^w*kBvjbI(N8`#gcFO*p)1)dM7G6-4q2W-+O7vfJgPY=3d%wf}e5~*g)6jsc^R(n6kMP2>|g>F~dx}hG1E`)rF zC2^H08V~QZ9`(4p>?4tmq>%w`_<#%gEcg|tk5I(5+^%QAt7Ll8!k<^aUgsRb zw&Gu#OmU=yy2<=J+G`pH;WTdb6LsW97%FW5MP`NUl9bY2slP@4o#Pe{_Sa?N`%%8ah-S!AM@LK!ZL^$}>t(2Z^IhLC2@E%#YFUQmpMf~hhvU`$8IM?up zjx|7m7gI@3|J#n>rn77iy-O7LZIp;Qa4G*m*1TCp#*c52IrM7!HIDyCPaUhWBzG)6+a(0bDwWOlx2^DXlN<4ipTiO=1$jf`i3Gm{5z-_g9IERCPLinUH;L4OJr>s(NUUiJ|ibRCC1R&k*tUSV9 zPM~h;Hn*a#96eeiqYz((#u`hgmO-Q3)74dzJ;+CL(G2c9Z0`%m|JXuF2;ge~5x%Yu z-unl0xR_JNEz^Q-aKAggJlT7y@{Fefh`DTeHnZ)iK@jWRfgoU>a3roXYkZj5GP86u zcGlVbq481Z_@`v&A59>f@FQf4;E6}x9n;*o&?$*aPymjv( z-T$dh&|+jr25t_-{R+O=|0?JBf%L=avWCg`?mARWj^*4`2|FOC1Sxiz(7*_LcZ5NaW_cnuCMwG^ht@J3``pDmISZ29@U zZI*C0q@!K(GsqeqD>-03Yt;YfpJnHs_wDofxZ`!ev({tmZ|YRkuf&?H_p!+YWNSAc zL@mjb_cLx)B)PB>TolUggRrU0n-%tlQTK_J4aKld3Qt&T5Pfi%hU^Me;9(#zD^(>^ z>qH@=xE2?=9iucX#`*lZMpmiD^Wj>o{vi#F+aL!SPR_%op~vv|7^&q*(Lrl$q#`X7 zWrD69oce%MZ;oR_ITpwRTkxH#+wY~3nkx@)v7L-1Fc%<9Q@GuC=YKp8Hk+tTee$WL z5^hk~dEi5<*y)lkI-mC5u((|%NS%bW&(Yh5OLZ1J7+wB@s(Xm=(d|lINHdm#y9ni&m_H(56wRb+a_*1^ksU37AxiM0T;PY+87os9-+W;eqN#KT^vZ+jB z(n)tEZ(%J?mM|*WJLnU$kL)?}kgbrwdBV31B&ylRkrHq%2fX?z;~ES48B-9JR5Ol~ zxq3^sX+YBSkt8T}W?`;#W2RZgOksZFfg9bzk^*|8{odam(>Q?(JE*x1&|}*--6? zn~R{dHudKq_2{$#ZmNfX;9R1rP_b<-mrV=-`v_n6bp&9$hJV7yp%TNwm!?5G^r)gQK2{$KkuSK+O6$p*z z$CvXf!5@fR{skM1;H>7tj>Ay|e<+=Qla&(kezrgE&GASrH{k*We&TsH+@*Ks9>RWy zvIkC-@LUbD`yfFkgrF=C45Ancg)`@(N;s?a&0HC~C zbR(VZ6cR6aOwl8*?dJ$kZa9Y+GVD@4C}tF6f+wUxppa&WS`=_eZ5!N~AUg*%%4#2& zCm_V#fPlnq#(46z|4c+jhjOdnM4dGjCI0v!+52yIfmfCaze=I)mMpu_w z`??F*z=6y2lzC&y7IR*;x8VeGtf|gvU{2U;o|L7NG#di*6M-};!Sr)kII$pT*_F)u zBj+9m7w7ME3fc^=@bt1JGJOsB=``8iAx7jTkA)^Y4U(SL2-AZeVdd&nM3*zg$vg3*4I%9A+9Kb-O2GSwri?9gRZ%kbycf*`NuoELX;*jsX3v~o++b8Z>s zBxo_m%E9%ID6w8Ssao{ud9;~5JW*bGIfC>_b$L;1DRZ^i)#3T*_@t6}rr13=Y7MB0 z&u?YQ4d}{GZGqzl%KUKHPXUk@0Da9=h?6UPlLtNVD8Ql%yw>1x@Z5eDOLl?WdlUpTs2^ zNXCpj+PhBqUoMKzwCE^WNrVN`?Pm1){e?M!phxS)sm9ubE%z!da<%Nw0HR3AL^?)}}YIt}^qlvg|E7?x`YO zsj|iVk2k8=nE|BpohZ*Rp=P|8P!{g=I!`;o1tAJ6+VyuFoH4nH1ci@Us&(lWtMMI2t8 z!=r8dYDN4{NZ8~J`DZHNiOJDkv~_b)l9tn&CtA0(OAXp6vZ!$Hl7Mjq@Q2#dU2-}Z zaA`khbnH?Ka-8JfV=lk~&TndpxiS_tXoq}<;=~Oxr16n=FSqi})KN5W2njpPNg2ho zbLKQ58**d_;}M~u{deM|(^?!sEhE5*iXCAQ5z2utJfRtk+u19Ooc!@UJ|v9t zzLJ3%NQiL6vFPtP#Sbs3!Y49!IN&TUkWwNwB%>4udf3cA_5L-alpP~;M;VHoRh?I% z+aBhgj$s_b*WUR;N|&Q~$KE=Cz>Oo$i4rZ!aIzqnDh^mamEnq)+8EZLB>pXHNDra~ za6pNrr9+xEXl*vr@JkRe5_Zn#hD4Yzr_12C%YYc{h!G&-b?xFo{+rl!)40cqH6$dk zgCkG`S~FV(bm4Fuh2USnSl%aNxJHBAGRO{ifX8i>`Qy3#1Q6b|G)_=Zv#0Wvp`e#C zT$LUdMv{crjcxcU4QkS#?$3aT&u`pa>xnNm>Kfq4X@D4dTI;3?kqr=TBG$uwM?iC} z(gS0tBaFzvOwC^HRBk)0j79SIW+2td5eEo$Wy}{)pj5+cRU(Ar8|@Rc)6X7ir{M(w=}J1mf?vgpi^&8WJ4x{!x^tBAJ7KW8QYD z{djAg2}O#4ICdb^5I2%{S2v6ye-O%>ZBlD+CdKrHIPOR38xT4w9KVj_k1(W)ij)e~ zsp-=TRYh&PG&tz|*cHnjXev-nbGl3|kGc>{J*yL_$-;#j6AvL_SbgSx-%Ot2b=_QL62_{CKRrzHWp!a)9Z{Aa^GiN|;KH!etwFAyo@x!*r2Fpq{@zAQ zQrrtiE>2HP1(J*e%t6Ji_kTw2>t|%7v%2zehHL#YJB}(DcI9U4(b5SC2(Oab5?IgG zHrhAJXvlIARt(oRos@W7R_P|bByVH3b@9eaR|L7(L>*Xn5*lLZ{>E%D3F;;xAs~vW&_fk>6kU-Ji zAVFOJ>-(7!^O;$Fn^e8>ME&gNigqS5O|$6+wue#ga0&98N(FLqY;`h2bCuzf;rK#}mbtoqXmotcI7B6eqsdcZA z{SRDxVeYsZpCjgXTuX!EvrRKTj*izHcs!VFvNJ@v9v*aN+Q6<(lc!u~CPM$TJgHzS z!NJ?iX7y}VL}iD3-+T9?In8!`%YhT0D~_Y#-|{&ONQuV}8fj6@n_PF|bJEy5u|^@5 z)ycD1k#}!ihb8rQ;eyb(GLB!}$PBtZJrMBw=b%sC*Vl7O*g2VlT<}o2GzC<;20TyP zq;)9ilX#L0)Lhnf?#Af}d0FKhKxf2=Ge7Y3m77=gusLhH>VSUY?=N+?*1Yw}gT{Z{ zz7Wt^3WTH#<2)8Jv!r8qT)%)FndtbP+9CN`oQ-<4yTd*6BArI;@64#j_iFpA18OCb3KUEH@jP{|ZS|t!@W;OQRzTF|owD?SHc~sZbK!bD zTe_;r(O>drp=lgXHvRBGOjLDlPen<&I^)o~Fqh#^|3wL9&XFJDIck9yTosnF|EVxw zfr+V}cY5N87{}#f>|zM!FA!oz)y$Yd(ol_!Bc?A_SQ}8OuYFDrFhesl-mUhxTIM*v zv+$n46=`S^nItCbRaiU59@X+H_?;fcnNmI8y)0*=|DDKI!5AGX*2wbYROfT|28q^- zCo-<2U;cWpVCM(3u56(j+gBc|l)tB%^Cj}` z5!A*8PyQejTXNSfckUIr*=x;7z3pzNAF+1?Vy)M886Pc- zB(JZ~K3U3+kAy$1CK25~k#D{xUVVk|OoH|P`A^*>n!h+l}H?~elX-`Bn#_3qvH zFg!!o_V1qn>}X0`Vmw>)is2`^c^?X}7cz->Aj=sb>KF8vsBzZex3>3AFWY7a`uSh~ ztzUjw9&i3+$=}pF3*C2ve-WQr5TCgC#pn2)vLT=<-kt>>NF6`+d9UAw56;;je+UBL zp>A*cJbzI-cM*KTy?iK}j5eD03wZ5#p-ptgPu%gxJB`xk&LYqv*>APp&mA1_v=E9c zkZPPI?mqEr#l9wv3~|%n@!>TJRZM>0bQ0j=iFTs`7>9;AH-xPyhh}GFh8pgKZ~by<2n{Xn_b*imRq9^qcz9`xoCrY1p!a10d(3p{uns9?3Wb}-pzWr zi3J;&$@swum{c}FT9w5x)%_2t`;JCo~B9#-QZLn2aBx67Z`MEw4B>3-DlP zM(}lz$q5*J1x9D#;<6&*6M(%ki1%W?pXYt7x)NSAeqIep2xB%Th)qmvNUXXf3UN(N z{(!J*G>&A~MIS}v25xh!35c%6kO$NDX2!*4J;gxV4zf?uzFWt$J@#F*)t_dVA ziCHOWX^n8`c$&Oe3N<=CJ|*?OR}p`a%HW!iGhq4MICZo!e8~k6(*tDwjoc&vPhc0) zJsKlc3h?5|Q&0lFbo{Avc43~oK9na$4`NBG2GUO&Q+i`FIR$(>!ZMC3B4SKMaHl}Ucf;9JpjYcYJl8pqjVVGVNju3B;7AN@0coN(qsFlfO-eq7@f?mc?>37PGXP z@(QaZ9@xiSXa_tG`DW7e?YI&ybe&5DF)1W@ZtaD>;0Kc%2HfpLXITI+Sa*O_Vf5*O z&xUa}Nfp}G($%s#Q+`Wl~sXV-9FeIZ0aB@2q<) z!vs+CnFIU`fGePj5Ph0yAeQpSJ~?I^NC&73lLH9J;PkLOxQ}I2q|`due_15}6NHQD zf2?D$fJN`tAomKMF8SP-Sfp+wgtT!G7+^Glcylf#=FwyO{kr%)5dJfvLOFm8I&{~w z-u8L932EAkBHTzQI3_kwsKGy&HsfQnWb9Dn=Nlsz{;Y}5#9w1W!TX>Zaso%=1iF$( ze`KmIJnL)f8iQ;b>i|u(P=eg0&)?k}0~UQ;$D25JC9blX3M71Mm(tQdiY0w)YHMiD zHExMMYZjsc$O#v$h_u}Q-O{vgVZ9-8eww>V`Jc!}4A!M}q@?MpvUT!#W1)M?7ylB4 zg~qKV01>9uf?8_tKB9r*+*)WG+H7gVZ@+(zIbF&xuxs8;Yb9O>JV!aT$zW!}TX?$K zw<9q4OtAN9m95V)WH*Qr9+nspbiBZeov>v*Y4Xt+zTMMeBpL-bZ%aac-*3H9e zj0LpY$;gGQ15B5DUflK&p@72}!O$tt)4|$lmZ4L=<=5YlXh|bnOwQ z12HhA5XYXdc>Hv4mADouB5jbD>%!%k2)mRv&J1?87(?(~u8iy9Woo2S%5N2gaS-B!_3chkxLX+_8=< z-3||M4-eCg%s7tDNsd_Ij_wSPtZj`fn2xS_kDjHEZVeAz9E^_Pj;)lAV7tNJwF$pi zK*~?F@-3h_GKA&Y<9EX2-}%R3^qS=^I3wA5MC*PChD|a`-YK;4~F6Js}0391EP{ z(HN&1nd0%8Vq2MfBBdmpF{QJjsIoG>);&$3F|O~UD5Ei>SvDa?KP%fhZdx|U48Koa zC>lD=I%p{B!e{00rnSqa!}4ad@6^pRrj>kD6f|a>ePo>uXZ;SPxOnEmgy%`k=7Y;7 z?49O3h38+ls(41tgw@Uk!WZ~PrqEJz40rR9t&&`2vk`}LZ(C=4qLf|BW;4xZi+ofP z4re*<7D_YbtI8JAG?w1cFMfBQ_a0d)%$={en~H8-`d+paA+>Bpwlv5y)1R^2CpD=j zwa{obJME*A3t!B?Tb|Qcp2TV__8l&M^O@_3TEs+&Cuht}NZt1?6rDz9Hp>==eO8ll z=Nk@J(DZAst=A6A6wfr)l0L7R`m9-;&!IKek9-#QqE_ri=E^eGz~zc1W=nBp>({MQ z+lTA(cgu1aONu@}Zk&EpkF0OQ*M9h{1CB&>H5O5s>-|m}TX#Qrh?I6SmN|$-@yl1p zM}M&Vn}WYt6)AtzDYZ$$J1gV6Ax^YJUH+rnX@#C)J{SWkzqE*&o7F#P2Cyh8SGyPf{W3#TntqU{ZhUxvbKUUwU> zqkrnGt~r*iJNYhnxBXQa+|1pQf1_oidl~;mzH06lFznVbj9ohJ<-FOA_1>>$ z*qgoGyWu{#k=*Zkb5I$1P^fvZGkg$!bkLN!pO?OO_l3CXX=zwsGrXsrX8RC}djx-Q zv{2skL$jJj@d#^u#2s<2_!n>U)zR@W(aD|W$<3P+ zCGHb~vBQwO<0p|PvanNy;bRHz)3EL%pz~=+;3?kNiD&mI`SGa(?r*}1Q%0@R2YkO@ zEBr=Q{I=@;9kF$yf{pym(|#n(cm~0q@DeKtN}oP#SCaa4DzbJcCVeLTNlCW-RDSJ5 z@%T()O;PpJZ)N9B4Zd^Tu`~UOb3@__W4;Tm3Pm01-%n$dE!%%v5ucm!{drFO$IkhW z!zV=>?C;kx=T3ZoowXEQiIw=Z&OI0vKaQRIe3HGDAf814dd5#5GrImn93wq0L4L5o zlaoDuct08j5 zE1^0lHbSgi`(QiK&q|^#1YoX`XqyqxK7N%La}Dyl-P~-+Hb=~%5SfgC!%FDx*MB-+ z0&BF00G7NM8UK9{iiQ1 zC6XTkaq>rV8)I?m@U(+Jqgwr%)lKZE^>(zws71;YaZI0wxAuh(mfY(|uXi;wI9`Q#pc^o7Iw#!asd?es*P4&@tRyBteBC3b+<@8HU< z&8Mjffs$#wtl&q#EC;zsOPce`UOf+;`zIKOQt&o*tEj@L&iOOCvMWj%*0#P`BOcahe=CfeM?w!%Q&j)`)L>;t@E z1n`m8KPYm=Q$NKxNr*LVvfz6E>WR~rSDD^`^+HN{?yl^(b1;fje@7y+wNdn`ZPhGm z&Ngva6FWk-=3uF?#ZONHS_pbjb;6A|aHS;%H~ajGrs54}95aHtn5VmlfBH~1xK_5e zgo4tFpV<`b#X?A3@G>T=b$FtpF?e_aH^&Hc5|xF6gQ|>X3R2^05B6dWE&VRZ6e=I8 z&72no;3q^WEtc1+bQEC%LdiqN>DbAGtqCpE9@BR6SI~YlDIKT)d-X8M;#AgPne?qE z+{XaR)}eGGM9k6OEPPdCa`bpP$R0eU(6`Z1o=VMs2`15|4)iGymdDt{c_0mc>T<&8bB$#somsDeLh0JUF+O{_BusDx5XHmVYL%kNjWRmiR3v?$}ci3GD= zZ@)UCLe+GBvHJ@+ErqAC^UjYRwIIF%beXEEb#lojJxfb%SgS?&OLFn6Rb7w5 z+z}?Xe5#Uf9_&2$D~Xla((~Z;vrt}ou;~{ND&ymy;gZA-4KKSwDjP_|isDhi8oR|Q zp@~wmX155_qi$03dGm_*y)9p2H(9#HXXa_1fms#03G^{?tW@#*v)>+IUvgUpT+vKI zJ>Y@9Fyyj~x(MxX>lpJQm%?|09?=rTXrE@Tbb_E9L8omZUWir3y?>o1FRYtYPeKcH zRok+!6BztZPf1hBA69^JMJ0Dy9$5=ODSQttxjGol)pP12Ej7Y`<4mgzpyoi>a5%+6 z&*^+YGX<|UyN_!>?N~!M?24HAUUvQNq(41afk;)tyc-_dbXCei0+xpUZ=TstCcwp{Ajo-Zf3(y*t>3*J9b3cMZT-js8XF*ErG0c<nm;hAiV{I5HJ@BD)HfV_HKw zFjcG@tVpt#^n7{y09@3mxalAHycU!I4=bWfv1O&zV5Q0)dMKaV*cY-D;I(b1Vc$xYeFvAts%uNE?$bvc2gPBU6tmhc4xW@C zZo#T2{s-X|hE2m78>F&Xjgc~s&*7Wr2pWGPRyFfW5caNNK&rsxTNwEjQV>Cl{CtVa zn_9+t42o#SF5`02qzy~ZZ=@MVW|Oxu?RaZCki7XZ1TVGLwXxX{`b18kf(wyRBqY%z zbJNXkgQ0f=7o{hAp9veW->o59r)ZGCc`5J!@;3{Lh&wNVcJ}=K!HSg=n_VguM}ZY4Q>e14XpD zU$k7R#x~3S=2(Pb_%Jyg+t*=_o`&%m0-o& zH0e-V9Lx}^&&E;&F4go?x|&9VGuV;v)FjN%Z(C5-S_Q%RR=4zrEvaQ_&T^>3UpqJN)01YfoMP7VO zgR)$$VBJ(*RKa}0PjaPkMx3bJmBqnNoLmcAn68PG+ruU!qo+)N;51(K(@vf?MJ94% zkq+{MvauicB^GZUU$+wcj&kv4VJ9b+>5+JHVR_Ob+%(f`!{SEj-XQ;T%J-^`R`BGF z^(O6t=;ajoDlB6yzn`c)be7L;uW)&Jj~45>TGIBn`6=GMOWE)OK|EX+ink~1ap~0- zE|xZzj&fp)dJ|Qe*M)d7^X|BLBSqqImhR7Kkv_?#Ghf>JqsP6^grGl$;y;WGDJXh# zL070jfdGr#Y5Hl?A~(A8A^>&+M@>Caa?3ZFL^zLnUiKh)tTR(-bs6j?!iyzThn<6;3@UH8NTNUcvr_#6PWv4Q?+CEKNoqwkJKmGZ7 zZTYx6MflfPZB#?%tS8QO33SO_`h2N<^*(scQr%+}DlJ2|WCRRWk-@{o|KX5U0?3m} z3x~kaL}0+qK7W`I|0bYS1H$p+EEF9^ymum91h}W8Fj1l8KB+J*v{VilNG_T&7#|YO z&P-SgJ1UWVhh_*DmCEmoC+CKxd4Yv2JF^>L#MYq}R52WmgeYMQuO--dTrL6J#tW0r zap9ui?i!@(x_By&6*BEmifCU0M?cPkM2*YjaOQL8btQ;)xs(X}TI$LIx5)^@>Wf2M zy25*@Lk(FJLMB4JsGwmgBp%=fCCB1e|L(9I)pPrXCC`xRb$Mu!^(JCRCgS%c+G z@%1g`-*naMD)cCS=;q}pmVOyvv(s%9Nuho#JenJ7;Mm<=Nze)C^@~M#qkD|rmRLH5 zxsEFaBa~jA_q^WfihZdxn5!f(4Sp5b;TRZd^H$K=G|ZN)kEd4YcDL7!6>MpW->s_r zP9fLb6kjG#d27D6WIULRsp{o)kBw=tE_E_nDaXb$Wy@OpLyow03#5~6Jn4C_O>HpS zxg3jXw%3;)taW9G(^9KKtx9C2(t9I(pL8gDV4rO%oo#?@_93hc$4Q(Bk4jDxZ@Iag2z0; zUNs8XRu~mS4(P+K-;)S`zrw61^8R$}^1Y^%0)&JcZUJQW@@ZgssFnNu*>aqj7rFL$heES;4yuZUeyTUENI$Lg zZrUtxTE$6C?a{PD?X=p6UQGJ53XhI5d|L5tS`n_VK(DXBGb1N8Bd4J+Yo;&jq+jo? zUmvNTpRS)@I+NQnlRG>Uy*v|rpdWFo9|4>7qMP;No{eYK({|F;GBbGQWS}f%AQNSv z<71##W}w?@U@&5!zhYo?Xkd6}U;;NZrZ+U@F?=p%_(H?b%*@cj${)ExH8TxTi7B5|Ig~+e+6&;KmL#ig5hugMV1QW*#ierOL4&D$UC)BwS}q20h_Kb+I+N93t*l$w0?Zjej5{4xt=;Cm09+Qmwn zH|xX`^~BOOG*ELgBLP~)2n1;EiEZ6frnG+2yU1s4;b(k_@v0Xv*g0{vcmQ-GN{$@= zU6Yhf3c5;KP!$@_CiX?aFNM$my5w&Z4Nd2}fEfI-ayS*O&`J$Xf0ZfUn#6hy&pzBY zR`mD!;9o(*(H1fNju`@_G2U1&^snp;#&zi@Qm!4R+f1JrwVu>2?h`EptQ8-xJsCQ_ zzKUS`)HZni?bd3+r2BG;(GtrF!oUV?EC7#g&VQLJ$nzxMKXi{EvID*K3rPXIj_j5n z&sXw32k%FTG6g*xwTN-$tY%Bnc-De5{6QdI#avqYTXJr+?BNBAS0tRnJWdI;pck(^ z*uxt4Txww}{uyVZPJ(W6;Dax8PAN7DFWd-qlFfM)@{=JKEGWB?vfZC)F4b4#sZPCi zztRvBMJpNJ5URLLASNaKtKWtgyPdz>>(}oh1XBxh-?$mFXT=W=82z`G@PGY&yg-BZ z!oo_>e-T}NSQ1Xt`#n&5!2ct<{zq7dqz@+}ya%~H|6gID+eUv91g|q)toqwXnyCBU zu*#VYI#b5#i0*#pq7zHZI9Qr;@@p(hJB=Yjt*%%<08XqF>) z60WF1VZT`KvRQ3rRLNu5=y~?Sta+MOyA_Q?Y7;thY~B${TES{M=c3gU%ks%ua#lcN zAX(^np5$D$)<~ATA%*y&yT(M}BljbRRO`LDI74ZtLz?gR>mj?ZZ6gxSZ&rvtLX&Q2 z8xDT-x3)cRTSlGz8qa^DfCy^eSt|K23Ky^;8`E|Fn-GL4}5ZBGe~tJV0nld={&mc)0f%wTYP2Sg+Op6% zWz2^)56KD@)a(L|vr2fIi5eq7Ex%J8mIQpV5WSUrL2kk6+5D*|aS)N=lP;+8@D6=6 z5$tn^=(0dedkejlV;Ie$J>7jvGa zSC2icv8(B4U1K^M&H-|t6yY(_;pdWpwK3E9>Q3)~`jjXDnHJ4JVcd%dahHA~OS;|( zm5^7%t>2>0->@s-T3`S;6K04NTm%9@0Cd4pqccq1j7Rt#+t176?b;1S1ZKX|n?ju- z7JpTD`Tvz|8q2oXY!vl;9#Q%#N80#PH-Bn+;E*H4n!^u&q!-VR(jWJeFy z%AH<@`vVGyyZ@>-)*~=SgcrQ;AAMhoHW6PcEIyhl4D`eK&Q9i{E557}gL5%!MO<`N z`K{)jO071=0E(Ba|E2EST=`^eB{{e8P1akS0B)z?Avb@A*5U?F>#t8=xn`qvspP8K z{BDWa-l}C`Vy8uLe)nqfLvfJW1*EWeZrDhTg|nb&eXg~3V80(V9vIV+G0h#weoHx! z_c(#H*Cmhu=LI|hzl(M<(t2?z8-w+p7eIX<50YfffqhaYr{z3-#1Caw`j<<8W3(0Y z%QfNsI6jI~3HOzFdJd)eJ0zR0GF>BBh7NzS*t;bl;>vPVA&0#etY5%v)S^i{tqpl} zsRIWU1=DW2LL>pdWjq4GRIS#1d_JcE>wW<=E$hnvra{CX({cRsa#c|F-HL|l%%0Qy z1m@QAbn}RNG~AU)o+K~iSk+pVVn9V}1R1{;XAMxfAQDR1rLSYheLz{OstgH?t~($? z0Wj(SM|p9+Tb;MK@1nJ+NMe1t9~2ohrhhQ4hQBCOdi&Ea1W?#PIc!Cg)VmNW3V4=& zeDd&N>p0Bw2^&KczcuRn05;w83k$K+_?Fv-tE#9ckkJoszc zW4lnPqt9tL7X?zd94a5aTPE#Wj|vVK;lFS@FA7L4WaCn!pCEk7Sa+$w0m{OQ`i&@_ z@>Y5>Q`u+M>CSKk!_d)n%zm$)A^LfMBe{u;v0wZV<9V^Ev3WIOwrKV3UpEdz3jpT( zMmaODG*~ptDk``bm~9c|*!W6S5Hjs5e#0I_nzxS2W-SZ(YKtq>!pT3dD#UP>g^zmM zIQKdJUHtqli>^~@wkLKA^f|t}M80)=(Roz1YCMJDUe_23*s=OHDNsyl(qk0zWV&{o zepALG*nddvH6x|dL!k@|jQ6MOgVp(784Id0`7cu_?9`zQk?M066Hv-)}DU%+b$~|Ux zQz3YQpdA5Jh2j7g+xCB z0r{;q{Hw#4pVa5%;-9g^A7zJE#clTE8ux4c491Q2MC_g8jNzmCzus}ru>A_0nlvM( zlW0YWj+&s3$@*kV1!66&ts6H=1qFU}IE0c(F!vg{du{D(@q<|@4~1&qYL2Mmz&07b z8NI9NklTKGX7pfv`a<@kBMyy^VIXJ1_lD-YQPmGx&}@@GBeIB9&N>uZA6I60rVM+T z$3&ya-t&a_z&`EE)F4PF&|N}3)*Y2P`bh{kMM%(shiGe-1en+G;q0e@#FG3HAdqCT z%DE99K!uM@mgQk~JeK~{@&K3BJ>=M7BbR@fHN>$-CeeO0m0-OP0Th4L_7O=Wi~>+! z{)*Rif(d=m`NG}NP@YW(kPuBpyx<@ywC!0`Ie4%rF4R8Dqh)Eo=kFS23B40hE zpXu^cQks84mgDAXwebi%!}F32(__MN$N5$k_wUyz9iL+_rY1$e$sc=CmV+-m4LZy7 zrM8G9#{4OlsH6EnnCmP0j^Xb*NNV~BQat0cCQAj)@ z;0DAK-Q^<_s8ESd()8-*O8(o%XmKR)S>n8oP@6&;Tz94(>7)088Sg}QAXB zc#si$Nq13jDr}Q>A9TnR)rCsG9TY zm(TCN6vgoZ*9ZwLTIg>)QD^nNzy+{l=zXGu3?<=)?V$JlJqhN?cV*yFLL^t1hsrs` zo!SsA+PZM|Q?Ib+1iwGCj{gD)gprDJrt&Jegt(V@IXC|PDZ?935h5q6%XYj`VnxQ74orP{l48ZTTju2GV)0+myU8eNGQTZ$fC_@4qv&}Slwxd*?&(Fh&MKKaK- zRQSW6qb-0^t3tjTT^ugckz^B6F2AKbw58^BdD1&$UY$Pij(>7yh3w@v$)RD?;f={vvNX|zv{BS4VFD>%!f0bZqy&6OPA#HIUr32eNy$o~ zP83V+K26ClqAE;DO=wIlrKb9Jm1_GVwYrG1$~eu!HLYQnytXmTH9M`%jvPast~Zg^ zEtb~%A-ypreQ+QxXCd81AbnhnY*H*kyd!G!gE;$j42&l8d=d7LhVEc{FjkOloE)gY5IsG=<*R1*X{W!mzIZ9mgsqvG|-f4hL@I`l*C_`bPkqc#7nXH9vh#T7S$ z6@S$V?`ZNa>?^J~D@Kcp2yXIYI*I~iGllmm6(CizUYS<++g$r93AHMV@G6nPD&m{; z?m-$gWOWpm@L7hc0KSVL1>qqA2- z$yrMVsnt}gMTXZB+1EZTu7&K?;t$rUK-V;nL)mraDF#b z`>tpIT_^mzX7Tr@gWpy5zAHfLWjX7gsMSl@*NcSL3m4Z54A%4R)pJ1_*f|>>s5LO# zH!y@Z&=faN4mObOH6S64M4XKfwMKmVM*XzJ^zcT&VB_s>;}v1k1xM4VYSW=z(@t2^ zc2U#DK-1c8(=uW60!Q<#YV(v`^LSYENKy0PKy%-2b2nj22S-brYD=?SOG8*oT~SN* zKug7LODSP%5l3sjYHO}tYgSlmMp0|(Kx@)&>lZ9xTO3DQv}#*~U0Y~aTToG(|3KTP z-8OH+_75EG?^WB~?b=J=1PpkOA)uf&fDS}t!HNP5bP5Go5+))5H7Ep#8{@pFF_hIwB1_EMQg=GtNtO+p zL?Nb7@E$bO@`mWL5;k{&!99h5CWt7xJ8>o;X8T=3S#Yp7q65%TjVc(@AsUh)!g1}w zo9MVl653C2K|ct9Xgr(!u2~DBEg7PH1Yq9A78gwa9gIiO$gw#x|1jR?5yCXz%n1Nw{kzaLxlM5+`0`%I$~0W7$n>0j6!5c)+c!P;KU73c0fzjJDi8Q z7c2V_ez4l~p8oMZJlC$CtRd-xegY;;qv=p69YBQ+FmqeqY&xuUFvNGziyJqBCkyo% z>Mm;O@4fBE$%YqscTtoQpuIbRC_<0sp(1a@+<3e8^YJcP)ez;Yu~wZSB(c)-}Hxcx3v=_t4Cv?9-R)YFOR zgP{o66o2akzz3-*h4^$bjej?Vi|po5(Z2fUh>5B0b=_6e3x>N$6mX!F2*5+fCp) z5As_8xz6cIHpgio-i#n$9!@WK&*8;Ea4Z*aT?vcF7aDICykJ8>x-Qy@o;gWmN-UwS z_k0oxS~|W|Oy3fBH&zXw1ER*uDhU^32aHT%n#;&SDMU4TvDAkUXt7ceMcnNI2f>GW zv1W)?bZ@p40x>*@Je{A2S}DdXRt?SJyTTo~kt0sCq<$S88i;!D`4kJnMl(bTdZjsH z43;r=B)K|yK;SNg=__u;S~xX2YC|3D|to@B?M_f{Z2}Tk!noKbp=FG()E0~$8Z?gCcN|{wMp&KTDYY&ZNOT!skLGH9wkbNG zD6=t8HX&}t!UM-&XELxUzy_jfq>6u*mjPLi0Ay<-;$tC|{LsqS#-#FX3Z`k_@p*!d zY257YS^%`DeD6akva;>_Y3<5f)-L%E*z+hN3P0HMvTjPr-K3@ccHd;B?@>9L9$* z3|3>-KvmGc@P#uB?8CohJRNX>Heys8HqnL*teiWmJS2~sSvQ?YmjffT&i9j`p6?3f_X`NIxFQo%0%m7kf@BYmV0V(C3}Owc** zOHao2XUE7+M})C?!}jV0LI)oNyb2o|#g*;r0Q5(E{Y$Hbtg`5`G5-T;?Rg&6Va7di z!;2_iS%ph)y|_cB0-&i`gf`mv%@(UMPkNFp2w(X&FRrc>mcmz8hvAMFM6eDwQ-s6` z&L+sLbTK1*Ef*DrbgI!a#D%JfQPUA{6ueU80_Mtr@N@V#_C91m1S*dUFa${3`~!1S9jx=3GWh(%rMV}%augZ;)BCsq z0}eFKVtVhn3}m^1tGF^0`j&jwqU4XMrzUrds%=Ixc_Q@e#&_9msLnp6BGo%a^4%A%%4H`WE zib*lL-Thz9+JotDY*lO_*r$ALue@@;`lrU;$^GR2EU#hs06!_i^y+t1XhGEMtdWPp z6OKDF`+g`_wJ|Xt2P`=K%JcU&lQ>_YXj6|gF)_3Jd>lEKej=T3z4HsKZ|#nTIZFYm z1$T=D{elLfiF)!%5G=M;SqS1Ay3DPVn@gwVVQFfR)6T)cxx{No->@2&Bh?ay$WM|v z*vqsr$i3+#GX5Y>+9DTOQ33GpC~5|@=@v$-XtP$UjN3j}V~U@}smK=agjy5_3x^ew zQ&*|k_W2tLR6ph8cy^j<*Bx0HEAsC$AWGv|ad?!7FBmg;KnBuO=1${QsbOm0I(te^ z9^cF4gf9ug=c=^G#paayPXuHI?__fg4L2OrO!Ce!bBsF(&+y0qrI-|RWT4D}lY)Op z5Hn`MQ=q*X?G%~Z=Y#H@x9L7A zX$>39?4(vK)YX^>^T+CC%baTUS?a&1+yB1{GkeTEs&zp;gqF?5`fB2`+CTZpU3ba`9eW%DA-ITgWP(70} z{Y&L^|8&Z}522HUY#DBad~9f!P7Zcj$L~7qsjtai=6eUF+C2nVfn=lsXKB>0k}u{M z^Rp}inO;$uhqBR1Ep0^gzfDad3KEU+T6R!5Cj*mNR9!&^-8s+%un;z`l>0|N?J5WZXBmwN z2YUXX2>Z(hl^XZc*UQDbBjDqUe&B2kQ^VP8=;60J;a<>Q(`HESk$Qnpor=XTdwlts zpJ+QW=nG3ciE&>QV3J8;=Q)z8aeyVvnucX)ojIhM0O2zEg^GjbwbDAmzBb;cAkan@ z5%5?Cl21K<@|;^sY{;|~pLX|i8ZT7r>0D_wszERGVNm0}aOfF-`|Y-1h$`)bXm^S= zcEDyWZ(x|ZI#kuM;h~PVY?S%4&A6pNCILJf@=RBylpS?8ryre^C_auw(yihTG$ zSTS?Panj8cK~(LP-uSf?fF2c7rHrl=hfkEenJFRN-81ajL*!`(I9Vxj>B-B%o%dep zDrs=Z3|*@(DX`_}MU}|?GBFg$5U!}=-Z!5J|KdI@ECml^pT^}<&qG&)A*hS6a-(rw zJ)PB6nzu_*oX~lXZuxglsi&T?9}3G-5&= zb(R*~((44sPD|dvsbdZ@$XVva2!KHn&!^n-8i%5+>?4LsgXJhQC-vjsT?{VG+W&3J z(CAZL-!n6NnbflM;Hbm@<0`uCe$Ct*Y`M_vA0E1qFy4mWL3qkY>n(Uv2d|Hmb*CZYIjtLdzXtQZ z+Q!bFh<&T|GX>$Hjch_smzadm`(qFB)5%MlYYpXnlpNP9yS=(66sc%^Y=O!IZ;$ZN zjzIj4jTMJ`{NMu|?F1IWcz13tLycLtC^PQ3{x_n-6r?Ba85iD(u-`SXn`_AzDmPLob0=F*=Va34p?`XcNp7)BpK6lj9 zQoYIMO;hQB`kw?^l`ie%pUKlj$9XDeGl>;8ye@ZyYZGATo=L&_-lip>Yw$-(Vo^zz4BDLaz!`U?7*kVr@UT z9-5v%v8pYqjfD}|uPk}sn`ol-4XUgHT4(Hpxjn35%6)pfF?95#py52JKqzAn`iEse=3_U4_k#luCQT;{uP)o*; z)yndBbkOB>&~J6ndUr6Ab)d*PBMUp2CFPjZI~h&o7#ut4yya*kJE_yn)EH*#%6O2b6aGYnHzolD}Q* zy55(+y6O50Rro{Oea@wDCeeNRRN>@#_mP9b;m7X%2!*}0?wt~aU(E_Xhq||x6gKy} zMWFu$bwq%+K`-w`ng4ZS{||6sD#}mU74n}Gdm(>-eE5A6Fnu1g(R<$nyq{dj$d!9C z>lRz@WIez)=dv24o3HM``ON-$54PZ@fCGN$0a=-Mi$D?3YY~}oA~}+M{ZW9{{@UWs zoV$NOIeUSEnF`#9f3&pkIOl6X8L#M@9~Bwas#irn;CjTqT>SD^^>*?3k#?QeZt4Y> z-W!WD?=_MaDSuDetKU=h;T}*`Js*gqcQk%ZEvP>%`N(i~={uKgCOk7bbN@p|Z;>8UrVsb`0iJ|4<}KD2)=ejuDElj!NLW>$wTzQ1paz1&QkuW@h=`|KsR z?N8%~W&C>g%_Hzjg+y$nV#LkgqYlg`;$OG2T~5th!>`+$Y%fT_Q)>>bLG>@(fzwIa z;y5(Z@f12`Y+14|aJAI}2E_P5xCEROXcpi+DMo^-I?xOai8IOxqkniF9nQr$ErY|J z54MVAYz@s-5jjfEjgjHaSBj;s6VU!Y-JNGtQ|p(96B0w{p@?)t4^4UpNdV~tl&W5p zCROPdQ4o^QA|M?^LMrARwJk1uXQAKmb9h6Yu@cnmaRV)_k7%d_JDD_I~$y zfBShNs9Gij6QN=p!~~!vC@D$W(+>c!-DEcf+$RF>8d$!21x~Z&s^K<@3|7rgvZe)N z=!_d7QOVp_ueTuq8Z4s8AhF_eDB+E6muy-GH-J2j@es}9=};UI7sglH{}Pz+OC*m1 zzkbR>t>7+}`Q&h=Ej8=LBe#N7=jSEB(A*oa=TCi0W=c?1);+C)HSaR+LT+$`xm6e; zfcPwZ|+9kG{`vq$n+W>nrcP_aKJY5ofUJ@A0f3%Et?@&>`;ents9_rI2L0*P@{Y|c0O)sYvu#p*~SI-SfUOCn*n^>EVym_e&s#YD4LCAx?&3l9SzmnMe?M% zI-vNB400l#$_CEG2p9ac$8SnO=bv)-6gl7&_lJ0&s6c24aq>GH-|*TZh8Gjnt)W?= zm&7TmR}=QtysHN2;(T)}rH4*2HzR2*pIKjCo#!P%lZ^rGWs@Q=JUeNYGw z=AEq*W#TGiz8!&GCMYCcPrxdiE@TtJm3oqLq7L0e(O5NiH=_hT+PUl$rOuUn0xrcZ zPeOcczA&etF){8j%i>z8TI$)YhR<02u`Yp>s5^T6D43bOyWj$ zk5bb;F1M~(i?nv@&k0c<vjq3rQH=ET` z3CZ9ocj!j*9!tbl18v3COYfHtUu;nr02>vcv$TfFwq>g33L=O0J#rY$owC2J= z&Ys_}iI#%@h`EHn|EMKXt^b%U-Jburm0ACvBQ~MDKgJ!xzWYwvMm-G}cB;Hp`^ghj z9`FTKZ~9=+d;00_mq*KI_a00uE;Fd~1vByOPDj>A2F{6I7*OfKYoT}Ml0r8E7vcJG zzdBRAJjsh$cgh~Fz#gF0-V?IX+bbo59*@?S3K);xmJObMU$3)~2-+MUA5eeYaOSzb z**3ivL@t5EYZSFhUtA*(+$jm(d#YsC@``lFY-Mk1+U@Z{pfl6E^e^$1iw8?yVj+hX zX@en2EAK0Xs@`;I9Z&9ydikFAWpfS!j)V9*2+YLg@0FM_^${@u9=UO~3_Gk22e;_I zHk0wj&3Z5cWmSsk`oqF_+b=@9MO>+#ZYEBjNWGwSS~mMWD3#>7|6)INP=&l!6oK z{cK-x?QH9jkL=^mAR@Z(!z#Q8tpLmWnh(N|j>qU=0mfGdg2*)=YyIY2+QOnMzE)*1 zhdlxu*DXtBJ7e(9^c-9x2Azo4iB~*=Uj-8oAJY)8;{q%>`IdD)YOck`gk+}ifgTFU zvJ6|^)evH(F78U;tWH#ZD=36==r9b(i%(m?3&|H7>iNng#UDHIv5FbJKpLtSndFPx zboW>{?x?oAVI7LInR#17*Vw57oLH!D{z zCJjY~X;xfUO%z%P7$)sQafT5?4ST*_+I*l}(6`S4yoD926Dr(`4}uC`EJ zQ_TGFqoEwgpRe?U*L0E}S>olais>J_TX2h86^YcASXd#f%iT%k&OZpZ7uS#<4y|xW zR%HN9kL#ck>)L(4A~K%Zys~5@qKhp@xuY1lqXtt<@XwLb?Bb!?ei9FO4y66H|T9mtdfR z8x&&pdZGtLhY@Zo+)L>b5zd1lw~p#6ZdLmX7UTy}`b6QwMcj#T!}cKY(b%Q}MSX12 zj{BvSW%5gKp*=~$x#Hx} zCC{(KlbyPkY7OLfAA&w!9tghYJNNvBas1&Q5BF9l60M_7)te4-KbJo^J40u=1a2;l z9EHaQ6bBu2jP+(eX*fALQk@^1u9Wi*qH)78&tRz7RqQCmvUM6Kw)o?s{HYAW-pogn zV>X;)+$k-BGr-`E8_y$zfU#<7LNXW@SL6_?lM^@_EhGM?L$vHTbU0Res>o4ab#rAt z9tja!NYG_>TSznzDPBl2QCeL{HrEqdOtG|fTTHceE?!LgBVcv$nO&sVQo2)`+tPE_ zg5sr&dv(8arJZ8Snf~K$%P#|$ikGv3_g9y*F%a<;LO8qoN)BG6WFH|If}Z$l zUW&E*YJR$N$!bAnz}jjdAyRy;C@;-@t+=S5WUZvEZf&i!s`E^Iy{vZJeZ9P4sbsyP zd4Fxak_eI5sA^~T*m&I~Qo2#yr?kFNL(-G@UOQ^-K_O;4mwvDN60rWgekM|4vtc34 zWAp7wLFs1WM&0^mlkAD#rq)iHu~*Cdw-~R6!%cPT_W){1%JtZVd)uv0(X#C}dgYDn z4={a6ayy&NJ#q(!OBuP7=fMW~BRooSr%UMBy}y!#J3SXIN-B|ns2|n6dyJ!%eFxSV zHU09AV>Nl|yFC7u%4TW`eOg*p3M57D+S*}#9WKRTi;JnXqox=4{IA{Ax}i9B-S6?6 zS9ij`S6+2Y=2gMmVN-De+(8}*Y0tK6oSgvn>Tm}$&`)X!<$a?{&=fjo^tXV5|pm{5z$tWx;J*s zOX^@0r&WINHCgN3ui@P6cZa0t_wVMvHeM`0{_c2o`S|njndH%r&(m6`Q*+a&;0ehS z)fmh<-I;3obR+;`j_q-P*T6YYv;xLBy1nVM+GkSq)+8)%?aXV9bV=qoQh0~J>^Vgh zB)bwU{FAml?Oheg^I5P+*}R;pd#;kao1`crMFIHT=cgw8)Ck`$H^-bhAt5wQijZD_ z*Jb|H5lCZ-=4_v%&R4l2vJ)NMx-)m-hZU_4Ru+HbOYUWWU1yN2;2k%~*%rQ5y^s!{ z2y6Q37Ne{B-mAR=_y6GG*_zPNW*<&49DR0~s=I?nVCPAEnS)>qN4HG$Rhwt+P9i>k zb_y?%gHv@K5t^#q5+S}JFPg2yt={(B_;c8%-2bkm%a0zBxTKVP@S@n6e#MPAa$4P& zMF_Q6ABajmy(3mYHb~X@`Y&Ibet%~L`yVEzBJ$Cay#-43-Tj`Ac3;fU7piy2m&IF9(j?a6{_o}d3=&jewEDZ`NdezZ4`mcOUwuncsPS&nR=L*|&9yRWFOjN5% z*Y)2NbsrV;J;c>Y$N*gW&Qs5vZkOjtt{@c zU%M-BV+PTDo?!>u^Sx0CIpc>@0WQWv)$g^=&Q1;OJ5>(e?x%Ur3l+`a=tXR2Je6qULr7f2PvCkUc{i#3nM~-b}~R38P*8TeJvKr5I7T_&G$t{5yI_+OaMkCWda~fLWCj+5YvK~I>+pd$zg!& zA^~2~TqqhQl^X_*^odG?AlUx9@OFcmmSbQkxN7F{>Vy2?v-Yvz%VDV7&k)vUW5?AQ_2TyvoC2(_1bXF$=B0y5v}FVNeqc2y%U%S_TGEpeKd`(_bKQ$cT^)XtbxUlR;lA zW0=AWAWyIr%<6y>OxT1&Nt3YJnRp%F*YMlzP}Ol%99Cf%o}^A(19-QH6qqJJR51)e zd0o08I|3cvk*JgcB1Pg02nF+^pzywoR-dcN+V$=m2L__zUK%bx>4C*)MhS`0idGQ?D*_ogbc zJYTi%HT`|b4;3A@&VUIbgdp6W!v_BP8Aif}u>rFsr6hfwZ`$5JbF$*pcaqclA`9AE8`Fd%-7B9i{~)Hc?^0C^S(k zf&_@CR>fR1<`P2qZVRTspxoj<;ZJInsBmRBLs+XBbV5>Nw%*{Wb0uKn4OoV|NJrgK z37GBegMx(n(uY*R%=^UzM?TB0M|3-OZ$yMDp7GinsJ=WbH&BF zOwokDp<BjW&(iZilIy}s(` zvlV@XdJvIY7X-&tAGVyQwT+q82pO2SR2Hy@m z7}(7^I$lOHHIkyxd%4^vD+Xqb!_Nlx3e-?(2LlK1j!w2POwBXYX8)V~ z{f;nSI97O!(3x?}4B-RA*|uyAFJ;7vgz^Xi5KtnoHh<6*Mdse{zGd_NU=X$zo*NV0 z0vmHW3`-B8g{X$?fH22cw)g0BuKB-ih`}toPWK*kC6j3d)T&fvc~_yxGmUTLxWGKY zsr%X?snT;#!zQLo*Do4sfZISkuE&f;4Vvg{p$Y29)&q;-VBmJJJ_=*09Reg#gUJt3 zD5FjALMj-gA{o_?)sBJEo9K|}TEXLb~u*YCye5o%sAoy1hLMsT-353`LLZS;H z1;tVBxn*5(^63c0B80RGPPiyc8IMp+N2nWwX(Gb40ud-YLI)pqr6^qA6=4{NFouSk zA|lLe5m%wYm7?rc6GEdTY6~RR5KDEY9BR`BLfBzYIgu7P&`;6xrw2h+*BHjOnL5(g zp0f)-uzd{s8D#U5rHB*-+>S!;F!~0vMRo}XLD^!u9{O65LuAOFcLXAZS|jhaVRF2& zg3KYMqOd~}{x%C!!NJ3D17>nnL=;{`g%rWb%v7O**}nkD#*368SjGrUcax%}$c$gA zL_Pv!V^~6*ixBy?qW}CS+dw&KUi?dR77YLea&r*=-r?j~F{RAf5Kg&p12RDucV6Ol zW;%IRFP8U02$)lDt}9YlDocoyBCm?Oq*@pI#8;$0gUf3!ugF5AJxlru)z|0VuI8zF zPclr_WQzy$(GhBQRjmZtN-pF$j77h(|5SFTJd*c?6`?ofoK5bc`=8~LPdz8arD&8d W*)%~wRR8hI_a#fUyIdXJ3 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 Po}a0hnBT9h7^|q&k6tGza=LS9FcQBD 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

  • c-+CIQNEPhIF{e$+=^!5)XhbM>towEBEVDv!HfYieOYsd-gq7hm%nz zQ8f5qFo4foUwS0p3FgcSG?GYs_>+aJ~&}~L1vz6#i&J2<~>$S@yc9z z5kg%>?uQC{$;Yp~1x+EAFub~kfLY94t$E#3u#B+`chwSDd7$ppX6a4u9ic_z}3=Ww9_MGnois=#325%vR{Q8y$RD1FVKbK zd4xrjZ75iEmf7~aS%j9DVPl*;aIi31ehx1#Kd6sC(+^z1r*8s$H<@1K2S5k`rWmk# zkoop9ICV+S;<|?im$n5W}UDW2>=cnh2M0~zCO_ScH6+~*Z;5dhN(e9Z#e zV;~Tg#LR=sR|q#i3I_>ab>OFVop|c$H=l@!FQA^{d?6?x)4ak#PJGBjZTe)q`vVD9 z{F88p2R$9eVGbt#2v!yn=iA^X^w=j?Kc!al9=NTlXxb@?0u--Sc&8xdqFG=QJH}g5 zV8L=Yq*Y9sWcPiveh~uR#WTk+27WB3mqdW{j@=yI6se-XS>YoM=UajSpWW5At%xV56|BCJ3yWD)AApwfze-hl z_%t_(CLUWF7OI&+f;F{J>sL{<9#b~KeTJo|`&}q|NG<*5Fb^~gc=0SF(WlCslG=l~ z9WGL@gkkD{re1Bp>a#M4ugN>L$|^fSG%oiBa>{6X%7!dsGze@gK{}`9_DFR3tM9%% zwOQFeviUBUeTo=lI3#4jX1Is)ARfcFGRjGLaYMVJ)_gS&A?ASHB&jtBfS_9YP|sum zaz~ZP{*cMqLf^@iDHG>(RCgh?L9 z1k-mEz1q}I&j#7mH1cdEpNH_)$SNw<-Tuh0+V7xRXyBpuI`kUQFv->&=FQLGsm8F& z|EU+o{HodfJAWa`^LcIf;Hr8qMQLu5#TS)`rWXF^Xn`gYWfQt(O6nPond&dWx;2pU z>Eg5DV~QvMRdH~739rp#&<%D!kt&(H&bk>)%dn~qkqTl4(N6* zZ6|&A)gaJoLmUDw@W3_0=damvj2!`EL2q}XL#4Ih<@QWt`7w3oiK`Hi`7ul^%uMVvfBs(6Us%FVbGs_o_*%3 zI1Z^~U`b#V1B;2b=UaobD80M6-05Lq!*u$!?`<+6Z)yZChLt_;!6{_Jx=*DAmvy>6l`*=vi{qqlzA8z{4r}P}i z%Y!#;vb(B)pxG+o*}!@u3HfYUUfi(WDVu03P==^1A@!eZsF`CD@2YAd+!e$!58Bo- z?}L%~wGx9gO$$trX_m&ps=nU93aK|n_$H6;jpHbx$o^T^s9&>^R!I!v|(b)a8_jF7*&}R zbr~84(Xl}~+fY^xj-k(#r^yToN=yWP-%%zmONARGK3DNMAsKlucXXQ zfY!dbj!&`frC5s~eI^F|Y-V zpSmU|b4m^)QyS6D*f39ye4%r-i2UE*E*mtS2Wpa;96z6rXha|P zn5X5_QaWvD4fsJO1a`9Ma{xsQn(1{q$*Hq|X#f+dSS z4Y9d2#Bp|kWF9o;|y!RcFpFArumKCb+mgB19bXn}EU(0^K+Hq82 zRPR@NWd8fzTB~23Y(E7qOJddDm+Pon??=E@!j6$4ZXxOmH?R9^F$iPie>GsT_1P7D zN~!nc0n))A`~tsb27cXdhDM?yrwYl711St-zK!sG{BbK~R{42J7Oar;G44CRtzfug zuxAbhyfL(OOD?cbP`~l9xZ0~jn+DtGrWQtweg!S|ttN%^g8l_{cEjO=D$EUhjoF+w zT-z&_EH?_GT!zG|{L*=KE2pWCmfIQX4eGIrKv#R26nl@ z8tlLOcID_z6NFi*I}it^phluyk^!!RpauxY{^14+A5X=`k33UZIsDjwLIrGe z2mj}G6NU39{|_l)fEDA>iYG&mvs7QDym+t&hB2eZv0IRI2C2wndo2P5^{To_0d|Iv zcWBgU}F?G?Y8f zMT?@}*dI^+5ky@WrgD0$4cBH2(xEq&JGox9w+_-}z8!L+OXpdDB1{}Fq6yS`Ede0T z`;fA+aS4(I7#`4XF^0%8S?ooa+kYS9Pu+2u5Pa%5IKiLm=$df7CEz;6)``S*i(4qA zPSUh3lMIm$(tru_R`ypsWQ_c*^L77bBYop(7C%2AaB@aX;i$QmQHh)dq%EjqKfG)~ zFH;E*L%P+Lk)zT8ywglWjdYrzot z&_UR{!>9l$foWSOM`4fgsh7UxJI4+ zI$<%3{O*xQ#NOJWlI(@MEwO3Mqwz4Q%W18-ad3lVkEKE(V1d`bSbSoh9xn0nR;QRG z1-+8P?i_&QN?EOib(jiLgQ}&{nuf}XiGEi(O4+NYwKr=z*IN0~jdE6PPTID|&iL(` zV>e&C4;TJw#CY)sk?_Wn@Z}z>2}$xL-Qg@2Oo4)nw+@4beZ{CbACT_%k~5g8K`7z@ zcq&x#Y-7P%-$vUMD(O;e!doHm!K`f5l=wW8P@vYLbmI{zubusp^s;^nuD9y`BqsE& zUssGSQcx<`U|i$FUwyt*xwhUz6oZVR*h=N1ir|yRRu!>VjIvWQV@Oxyt)UWJ;=w~k zu5)uu6qZTzq+H(wt^Z*A__4yfp|$1{n!C=Vf0Rv|q0 z;aZ-p$M%yTavm9AlT%0F}2da*@L0{oJE?2+wKISw=R;?=T0fVgRtv5H`~lFEG=EoBQZU=3TAYTT$K zT6JwnPmrs@N1gmn0f_sWSk%zr%P3$;;TW{iY;tyXum(2fAw9F8*jA z3b;-OJ?Mh50Fl!ty~47Y(8&3n*WjmZYCd zGgi)-X_fp!3qI;pGmB4}S*j(SVB~N9&~x5=tDb}h7%N4Z7ol44tkWp+khj>UAA-C3 zb!8XTNtSa@(_c~4=3z$r#a<$QJrkST>`v!}$#ZwyjTSC?G2Y$)BnH$+y} zf}tDrrTNc+iRBa^T7osVO9>wljD7{XC4FQkZNfvv6hy%SGIl6&xgvXEfPvcz- z@GUlNRf%Nhz)w+@1bjn!y8k;udT@(&!APx`2R*28gLZixoc2l@#7Z|cKQZ&GL&(c} z&~ZAYa`Rs_b~q>3WV?Hf8QLiHD)qL6S6Vgkaz$4*x47i#6_*@eq$$=*!1!3YN{cm) z-g;bHFgW{q1k1jz3sS77%_-P3|K!jyp^wkW5jj*B@}8KG-`f9akn*2+LXTA^&O}=jOU5g{8 zDPLW|3nOu#b(KWK#E2-iEO}Hyo6b1x6@%F(!g*xK>6o2dEO9X1e*fr>i?t!M_7pwt zDWXa7Zb5_3;v@NA9*kMZBOLFtT5AM%XK0A#APx7cbxn|>Zvw`{r=HE?HrJC^yGRpn z`al-FEi=$^epom$(aHREW1q$LY@b!4Od^9`c7(;G?mcS?kzgz$J zt80%oH?M9wo{02J)##bv6VA!FuGhWfGn=|qU0bANUN}LmG0h{d%&9#o(D7x>P?&fb z@P+}b$bth?Z5%+6R;;!qP?>dWMLiY!x;I>-}6 z$SMuf3&HA-7gC{0c|7Ad1eO~XnEFhVT02jNxK+oR4D>92R@0q*1DOiu>EJZTYmtjv{#sa6|=hpA5d~lt@t_`h)aV!nI`u3tC zl{w}SA2p$!pZrmC7qODv(MZ!*N8dz=vja0XF2wer@Gqc+ygr?LF&%YW#5JCNfv4%I zEB@o6e2(pHGmvI)#nL~Z`%P57rjcxI0E+ukzLVf2)>O^bT#Xxy^HUX+9I2BQRFyw6 z3kK^%;)SoyuIaw5ZR5ir*VdoJq3Ihs46-8=VnR*YbX7RPx-2Xu9J#R3OtYY~q;_-J z8o}n$#uub}wS}wAJl8Q9s!SEp?KhSkXHb)HeO1%0bwjy-VlX$O{?*YY{p1lVW3sH! zf#Dc*R8jfaaoIECZT1iBX)q;q4XQ$q9Yekec(+g5oA%La5X#UM&v|Wt4D5LSXLP-x zgWnM^eI`O{slUsI-g`$dCorkQ<#i1Rs^McLSoysvje~87KR_YUG@u5KPiDcU)U~4@6IX~0S zNJ$1CWVto<7m>8y4MU{rQwp3^lRCVB45Z-n@l0s7W}f6(a^ zV>zM3e4&+n;M@_65l%33A(`68n_|%htSNd9jCx0`A9++!FARBpYVrOj6{ONkeBU*X z1ALoI`K$%6K;#jdEaR6Xirb9q))!wU*Yp?Uh@=v`%IIFV(EOzASy8fTR?hetoc?7K zhwLt5E6Ds&L}v=jc>X#4gFQaIc(_EGZBV%=k{3?z|5Po~@>SW;c+m6|oAgBZ@=uhI zQ9|!8SL-PrY10?e+QF?&Q-(8e#(}~VvWBdMH1>|+oO#Yf$TJ=ruA)Vph^w{a)DZ*xQ=n7&gVr2jRAYR z-v}g`yYwRWXa$?qGpov;Rpo$%LFX!cMbaGPPOay{evan0Oa9C;yZNr;x98YRQG)yi zUSLBm)MTwh$-acB&r_~}j~TGS!VdgIGdCbs1`wn0cylP3DKXw-c%Ei=HSH|kGMpu? z8)6T2kStelC6P0du`Y_RE@_FIO%Ypt3+xRh3I!B3yB8kIrBFfe)Em?V@F>aFyoWz8lg4dI32umc=S^l1o@RqpwmEx{e3JBiG9X_nJ}$%TkHk+uo7Y zBY`%{>YmmEPaS5Q-rM8~`>oq0);t5HTN%w(cs3N>O~9CB;(CG(636m=Ljij z@`jxw)CIDECWXljSoZ0G2FQ!2z$XDPy7vQY?*D<{ zBw^_0cB$u5Ged>NRd2#2SHhpmkh%ZnN1Rpd;?D(o~IhsWQLGuv#x%l`7qrN~sdD z_8)+}Clw>TqE1`*-@b%#Tb8NFy0yf;r4J)=QJz=dB4py*R(5%G6G2?bBCl?|;~ZRa z@><_r-%%AfF z@8r{W9m-SnYlLFD6?^eD6FRuxj#fnD%x2(X1SV{c6ELWVl&BD!Ctxd?a0xK~)j2{{ zJn&P(^>$Idj1~!~V!`J27sMT$+8eaQryt%QYkckMhB* zqvI{n@usMgywFXKDzu~v$Os5hF2+T?O%;-$OYWP1BPXLL)3jxZm^ilnQ$Bp!+BFj^ zCE&GHwQgC`DSPx9;Ai<&^B>=yr4ZTOlB+?9&&Ey}DlzY*SG01e+CQ@?_cU_+5jI9> zHxJsXR6fWtPEer9Sv&+qkC*g21L5>#w)M zu#x99l|k$982PI^jT~rgOplGZaF?Y9ENa}l`7z|Z;TOBdU*6sO@|LsTCZ2(xhn=^s zP3UOF;5_h*OxIhHG80Okc}t&!YB!OJK&i(g307DUk70 z`MObUFzSBnLAo+3Ou(B=q@~qx?>PvhyYXws_*?X@oaxaqY6Dcb&$Kl8$YwJh|A?7> z)EiztW;st#B|-||`+xl!R>dIu1ve>!EtK{?h{iI zA+OT`8Uju$%)7U<*6LnV1H*(jGz%-P%(*UZO}?LneCG&*^GdjFlvAl5Y?GfzED-zl z-%jU#qea@XFNC+&ZMOXL+4;NiTsnc~5&-NuQQs{{?b_sh7+eSZ{dHy=u~`V~FAnG8sKRS935K&+pY9LpG-VxhF!!eqP+H=ww;5&QYu zzi(y~pUti()^R7ASKr5Cf4=DSHTagUGnHcPhRY(|eoZx2PY zEeXsN3g6$Fu9Nk?S*RX1ddenOW0bFBbtqTQD7;i{Y{9O3D`aOpk58AmDOASKrtwBA zensSk$YQZ^#iYrR<(HWk0k|uTbSfJ^+ic4{TT$Dz$09aa{mX$U%y9x0k~U6h+I0l_ z3Mu0_o`oZjPh=`HzDBdj?oc5#B(W_nKpeOVMl?-V0pI}5U`Uiul){&{o%gqAo1zrI zeHe%X(@8`tovbMd`WQ4v#|P6)7ple$ypISOU14*78Ox~}Mq|gkR$|xg z{nLk6UZF@n#~dRe2WQf1BmoQ5IC?-!eVtetbK0qN;#Q!O*L~ z+caV$fpwsUJK{&r-H%1AvppNdCVCO5qNq?qRBT+^8^P$mGZA}{zczoQOFr$u;mJ{f z0DNUS=dXSDQVbkZouJFi=ADTlcYx5R9g;xRPpfbFH4Kp74thSs-q6^-c*`$P#-s}w zGKn)^Cx0#7#rlw>k)#ziC+*!xE-WWCj40(NWJY;@cW8R?##Xc}epSRkyz67AYE{=? zobhJ&Zh3KY?@`;k=Du%39MAC=J{3kBJSHd{Im^DPmNy%AzR>&GJrRt@V^5+3`Lh_W z!@An)*YzXgtG8OOUa`2B1T~HcgyDiOJ{hfrjPr7=x4aMX{tV5Soqr{^a{Qn)?)&2B zuRZeHCGE4SKi;>`X@WUBA}=c4jXC(DZCQu21t{=?)Y?u3p7|$KZ+&1$z=@$A#Ll<=4NXVSN9f<7L+9^hf%qqo>>VHDz+BxM1P15s&7_J5 zS`mK!4boZ(Wz?}(5vSPNAVsc9(I+Z??2FgUWqK#86}is62W|O(L*KC*pd8*ccYW-!UQEU-Q$uCVN$C^h@Dj;nda>uuVp% zy+X3+MC(c!H;7O;7UFXJ2#>5>Rq}fE>%Xt}Y#P%B-+q#Q!_$_X%{C}(-!W?JCX-wA z-s5Ea#}y6IWYp!7U7$uK;nlBK8JRxDZr9DCal4^KTP6D)-Z~$tHP6=I{iSI}3UJbc z_i4F9NI~h;yCx40w3#@RJ}w#9h`_W+K|Z-p5xRUu4G)|1Ti**Ry6+CIF3_enir{7D2bwzzGIDD`7vnI;xboekcKV{|g)2aChz$i8 z7ISqh*KliH#O|SOI%QhoGul@I9=FEE)XQ(ynK+5^xNj)cG3OWQCJ;?L6+s@;jSZ3O zqIdp8R)@I^-m8y4eAjKjR<38>w!%d&#O_BOy-WQHX5;bMfY&_I zr)X}gEK)6oFdn_#E6sr1muIrB>3ctJ`#Pv%_4EC{qxEmjmK;3hw^xp9=hmvl?=>b! zM2+peKCo2y@4nMlxu_tk<1NLP7vkn zden%ntp)^uN&Yg0Q~sYqzid;jQXTrxM;g%{+fN0T=DQ~~j*JIO%-I!V6=py0X@Yxi z{oWtCE#R}CJ|wRkSSnlL%|w9gOwC5>m4oXM`^N4nOMrR`+RBI#Xs@_Te5;IF%lmyR zx}+)JD8Idwv^}yjt);fo7thu$I>*Rg)O)AO)<>-u!^KwpX^)T(Icq3cmQ>azuSO-6 zM^o*2@$-c|zvN$dT6s&-eF9WO_;F?Z_xV1dxND_F3~N~R%88=m?cpfRlcdY#QF&7- z>6WCf;d|erjvg|;9T0SyT7Ul#{9fVP!{aBMW8TqxYMZ4iNpL9Yor~tf=6>4l-j{55 zUCmgSe%dOHsY=W}@ZZ?n&p+t6G3z7oaseo$(CyNjm6;x;_DM#_OPY4$uIsbVH-a_c zP{?)e(~hj?2_KtI4G4+2;G;ADD{RiAbn^6f5rj4_ynp5sRROp9(XB2XHJ2z`Iw7V* z03ELLHm5%YwCv{XJF4#_*Qo9?|MssE=~<020TCIZdSe1qKmG~O<1ugnNvGewT0L^U z=W_r4HPN``BgeP1zjrG(EUWr9b;W*;dfx1$s70%DeLJ5!nxlK`B~Nza&N(=VDCh9U zeeW~X#hYQS@MFNyuNFPP(zDY4)a{sn2Bfo9u;!WO4+;_NfbW>P`fmq848Znfk+Zeo z+2S*exs6ufA+48Ox7~nW)xQTz5G>?3QR95-PP+x;Mbo>ze{SoWF=J(VOrM@<{#_%> zWGLo1|9t;+of8eXvLl_Xd<4*=I?-AqJa>A(JbP^TWaclo$fYyTXaho?tQx)sYWxV2 zS^1+3*mLD1!=uh`I5~O}$?L7>B22mBHz?aSG=0F?cb~yzTz+__SH0MvF}fmZD&=3? zAX2B;lR>dF*#O&37X&Tp0%Hri*g#9)0YK6G(L{t%*~e_KuS+_;gsUQu2M9%{-rQu# z`AA#K#q71I@Y4~H2Vkw=JgpnLZtCr}CSEpeB1cPA4M^PCn;i5xf5@=lEHEc%>xdKc zS}L1Mme9IZK z(JXo>;d&pF%1cs3aiskNY5g48f zccUs-m7$7i3`n(;4`bn`w&hOz2~vMufj-ADesV|S?c|T$HG>%#DLu3l*p!khFd4JL z!X7#zYpQaU+9~NmMjm>$tLoO3x_Fw?yB-FX_WF^PqY#2ziic6CE#~nKij812R2jym zZ5*0QGrDs#_O;34jzSQh>4nFggB{Z$OS69-7Qr^=lma|=!Dx0*E9UF@S`})o(#q1) z6ys^Fk{xfeYwNsh<0e3HQ@}1oKrLd|&Ns_8!}C_Jl|zxhd3@Eap(?3X&)X?I)O?}zokz8{8s-c#2zOc)qVndOO?#({}-4732U=o?}N z=yFOdfEpk@qWuH~rW;}Q)j0$}vGldW8fRNoULq_;zBRG+`65u6M!=qrZzUxb2m$9N z9u$Onoe)7qr7S=T-VN zzz^9w$GIHQ<>aLD*g7fuD?pc#h&14C-Z5D5av|X{N#6QUv&64=wg%AX*JlLN^dQs) z&V=dJ^XF;ja%B`O`Znd=-M|jFkYgk8!)NOR1@sVrx&aJ-+P^y7Vu}^PYOBwKx7onK z7emVPVD(coDFYKu|JUl_gMKDx8DXfJ!8EOyUo5oV&#{4hAh|QRp=%V}opMz9xB*Wb zcHt)_6p6%L`uoG0Y6kpcr-z~AkLTF|(q|2u0Dsc#Bnd=YVwA=*Pq_XgetuX}GC-vi zm@dixMYH8@100p}Y zJ);2O!SsKkD;eo47c^?rM~HrZb;jE38}l7Vl|HKn#2ZeN16qc%#yjt=O^)R)-)rb@ z%maLzUKG=u)~=h-Q$-QTk=Tvc!LG!H@_!)JRdUsN@R6XwHRBKJ|LyTD2@NsO*~13< zeS%Un>D(55(R}|={a1DDSNw)HUCHykQEkos^`9y{6`$^Jm^2*?QGO;*mo!KN)ZWWG zZXP+^?QQwu7r&Qxh8yX|P}{WlW%>8;fAceGz;857A2vY(#>E1$8?^T{7@I5q`Mfv< z%NSglA1Z)ye+~b0LmyfK)LDmpR;6f-+8)(R1Vl^KsUPlpv90oNDC-_m^jwrZaF<=VE+IZ89rB{5%7 zCv~QX5O)d(5{rxs<-0N99bdAuL2eN!Sama@Hxa-X9J}M)e7Gma@c@?v=HI!x@s(@P zxO_t6YzP4*wXpNC|Cms=#)5?(fXzsNYxoK^0J#s7DQS-mco4fm0-W7=Gt&M{0ec2C zfJyFqJ^XP!dVs|L;2h)9Bx=*-$zXE;ReJXX2*dKHAdz{zf=TeA*LR&i->!ZUwyPyT z$ppz&$HUlwZH=!06k7T8bKLQ;;j|VguNH8Ik+}pJopzkfib!_t9e>7-jNE!6=hyK0 z0XB=Etp6jL9?QM|HI7xTNP!dwknJMJvh0ni1HMJ)0F>el^)QFR!YvAF56jz5;!3{w zLBGYZ`X_x5oUY%W3779mln2fd$N|z=UNq~eUw(fJz#M?3@8ri`J;EP@WgM{vq8N?K z`>G^>aD%pt&pUeUP)&nSk-3oAV=!fi>0OidhEMGR&%bYcZZiibN&cC>(P<zS5VM!`fDqsaU-TkPON9knakXSG%mSr9#W|i_7`_M35wI9sRnsr+>R|^!A>< z2&V|%%ubnt7rmbkuoj6pKCn?GzKg)L(fOQ$q8Yvs{k^9 z!PnGiGXG(P=`M!Xzhm~g{*H!t_lf%C>Y4WW9`*vv`AmHqI`6lH&gEf8NWZQFJNfXi zq#Qt~ch`M0K;WNFmXCxthoRtA@7RzQTUlX_bA^y%@fh-}0qhv zm#_nB;UF+Ws0)ik5iOdPq`3X~^gKXh#WqhOwii?n%ET{`@TLPDLfVuRz54n@_+`oqhK#;psIuo zyZRB`8S%urEWj!(t!uKJ&}zFEfO+!}cdV>-TR1KESrm}~&O-C8YEc7PD?bFz27L30 z^WG3S6!;@X5t5P3qNL)1ZU_@LnL5qq)0PYwdJQG9oZH2QA?0og zwH+_8zB|t4UPB)C{o5pkkv_89_ad@>a414+nUg~(?qhcdQT@a0bkPyi(b)G&*pj~3 zYSp-wKCPF3F28^^t%qOde1j&-k--D%R5w{_@jUk5e3EdDf>7~~e)FNV*Tm8P*uPBP zj=&xd*9&&n^@&snMjSCmy+ZcQ)+!fMeV0*{#rkxofs>;yhq?R6VaR^`vVIknaP5UE zR_c!*5<5u_O*Tq{6Khnd8(3CDZTJ+Q3C92+!Fhno@+*C4-zZclIW)?6rEheFs{gg< zH^7B{ggNMdmZXq3EN0T-$BI|k(N}Q1!un8Qp^(nJXab^SGS~gka7r#p?%%du#7>ys z^{K2WC2lGjUfDZ(nApYiO>K_OtnKA!nL8DU0-dr1dUO0Mu2HF42)aBR6uYlo)~DAh znEaq?61>ziVnTY)oNV=Sl>Em;N}SYNju>1^3_$EY(exs2Cl*`k{p|tG@wU2HzuesG zwkOGwnk2vt%c(9<)7he0-<;bS=mi#s~`q7KccLfY5v z3?TkR{F!I9i6jNbhlVU!v}EZOB>^bVx=3fP`H$TfEJFM+%!!WqVim4)FzkWWruKA@ z6RJ$E$8rVP)A>9~uE55+7R}!^1zB*K&N!@iIsX@R{_E!-mOz)}zx7VZsOtmLEIVgWtn@XiQ)F3MVmJ}9)XE(bJ1r5&-HQK4Vn^`x38bE*x~qy0etB3RrO zO9G6pw7nSX7N;pEKB>8_@VqODWiEZ@@P#J^nS58U_g182;2SD|-+AQ^13*-+hsmiH6gN=D$Z>;hLm28~yS8Q(|QgE?K71ZJJ7w3AQ`IJgx zNqAc}77O+$M?a0eJQ%^1?x?Ul;kVnhSnwt9jgPWO%;runt6D?AOr z9jzEeyM!<5(qH*M)hBqQ_BTn}IcP1-ME_iW^6~RVhvM^-;I?+j;O`wBWxo5=M0_Hg zT5jO4++QI&q96*mohJXwtQyWZv?QFaD~JQse~+{mY(;I!VfEOwL~AH`WF87yGSn;8 zr0UNWYy%9?tQ*7xE|r!k2?PsJU_TH$CVr=wf*fS@VI`HGd45sXWb#CRT?i(H;)*#% zK<*-r3s5*R;^%z-2?(0x-?1XGNEX7;YXawOl}A5PV7GVq3e0FJ_Bp&zN1lu@>DL85 zabag|>GldHPREfV>dSOvGP>sz--l1?PUy_ZV#yhUlTMed>;xodc0AhJ9w3N<-(Z#{N{SnH(uyXbR z;99aV@CPtJA#ypxmE(LL(pp!;bkXI$g9hrFTZ}=e8op6wE{32Mg=Pq0W<2c zDbO;Hw!Fj*lZOau(l>gL%(btY2^tTb1ZCCbR~>rN)+1;1Yl3;}#=vB)Oaeqi~Li`>NP{UUAF*#78f6g0F}&Mfn0lr4B zvIEFS7Lu{3Z4gy~$+fyNvr2yEp5BFp=$#wdEH_8V+SA7GX6+7?B)8EX`fW15v^Q~= zkVq338(coD9I^!NK7=Wc4Wf8SCGbEVWQTj?@i^Q<`ZIKsaZhO?BA$lFgZo%?Pi3qw zJr~0enrJ=F4Mw#mWnI(Uw8s@iNv5HZfjK}XpQJNsIvpRB5VTesgN@IciYCx76chm* zQ5yVzw-adXNy1eTzq^ZtX#{}BDR?`d|TFCw7x$gM` zy{nrCl*1yqutr2iM17)Ne0?t9C$(gVHA+$7HG@|#lnZfwqFv#&&SI{^;uEusTO3Q=UU~C8KFZ-(Euk2{J5Ep)qM@tAs1`^Qhp8;k3F>lT(ApEC;u^C{cLD(QKoVrX?iVWtzkUAK&eC6 zR+{k0(E~s0hDdLvSXC3`lUVy5pF(@84%n^TLF1J zTVz|zerhui>OE;%W1jrxDb{r*=K#^-6lEX}J0Ce&>Qg;8P~*u; zc1fVizc<(Veu4MN#d6&TmYibb(YbcS@#&xe?Ba@tw8HxE&}g34dgkKO)2QUhJL!Wz zeYf|7`7xDeNKA#~xCUK>{0la?)Cpra}Cbn!`%Pe9qcZpySUWiSot7SijygJ zTC}KK3A*6*jlv(}_uq^*Z8*LfRs&US(M5p9vsU>Np09>po)KDQU`L*+AHlK~mi zyZjm<`Mp7s>+Fwj|M4%2G(I^}m@`xl%jQNc*%1Q@*l#iF2y&K`;$}iW>N5Hc%rr1} zl+j0%Pd@z^nuruOyKmOZLAIrz+J{V~Rpn!M9 zN}kbX-AtT|I~8H|!7xShuwJB`gLF99vzV`Vr2tN^IMZ;<=C1M`JU_o{ad!-|SPz2J z%a(_Rxi$tlH*lXo+g$c=u6>NkTO3$Diy55-2+N`n3dMgp9aIC06#Ehx2< z(Lzx?51TrqAed90@4*`8DWAis+NIRW11bBm_!G^khRvzRvZ$#tss4l0Xo9GxvS{AT z(|l|JESb|Lz-f=>X}`hg#ty0XvgpL!Xnw%qU<)`!>*mEg{N@%N%mTrZjQ|GG(FM^m zv?7GE=|!cfxDoVA=Jev(45|wZ2s#GY1uDf82IB=rGmAwn3&xr(MvDceI|$~deoWrd ze7B^T?;}_qEX4X`v-~w@i9@hn5u|ghTUiKm%n1m#Tnn~uRjg4btWOZ^6+vu|TG^Ps zu~i{B+7T>ut?aE|*vt8CIiJr-;0#tm89p3$>RMp z&nvsgr}@28Fqn^{fe*9DZx&pjCqr+MBXE21x3wj$@uGltj-ZV$zpLfCucc5}Fe!ju zDBVyn!csUXM>6{R{}i3~BUS$&$Io5vwePjZ<=$(PY(nDNmyBy9t6Y*K>Ly7-_gWVj z*B+&=8A{n9)wNfIC?j>vRO(|EB46J>;r-J&ujhC?<=-eMBswbQ@<}CcD7;iq%y(3J zJf`?4_-=8qQhkQPlQE@6yJK(oluyMTd&!sIF{b=3c(IQUaahZDd}d6#*YP-tc6>HN z1;?kdQ0KK=r}D=U`yZcbT$(E6hU&qF>ZZ9Wj9+~sU5&HemPb<^!;couRR7qej(e|B z;-Dd~X{)rUagtwD(@FE&h^A$xys@TMV~nPillFyCEqkX{7k(X&I_-0twm$E5Y=dunPCa-FyzW$G`e>zCC_7u4&& z$mD*`fAWOM$rdMr&XJRE>VPEJGo_KzE^)q|ZcF^PwrS`NGvYw#Qo{9?`I3XUqxCYI1n3vKH9AlatoZx#utB3>`EHMC?rs6PpJA? zhe~G&feuU`m1p2Z=$CSo)NgSiEI1E@4#1x^qp%;$N&4Yz-&mF>9HAzQxS=dWUMD7` zB9e^+)R+Tiw|*XmgAg_!BcKehn0F*Clqx|gZ(u}Ftt9s6B&GqYg+H9nK(~Z_FyTdr z*2lpyMdy8DsQiDZwdT<{r)y=KZhv!REzBS~N#ImGLIxky#;`f`#w_AOFVD$iC%Fxp zFr+y!dJ>jOfg1h+)Y{{bK9UwJAe2cx&4igy0Ie!ilrf9INN$`oY1z{7!-6{)4hP;6 zDgYHT3G>9V4eNqSVFbe}>Nyr?8wqT4i=2~%slo%ls$8B!AyR-q&X%(_1^T%MMrHwM zCP;xIQT3KE%}Z|3iV%&)j8Sg}Eg(GcclfUY(TP5P=R|yR!!=u;3E{1%X4b-uHix}u zB=IDTNmqof9>@&q@nTyX%LF^FQim+rvA&WY7{O^QPBOmPcQR{*dDvQt^uuPOfC~x? zQ(P>@x;@0QGC+e7njRLv?aeDi0SlypV=2&2kJD%7GEfYtH52^#lB-}ehSYxjc^*_O zPl#@YY2CfwdHccf8?@ZaYbDzESQkN#tgu56h6Ci$!EnhJiGkpE6L6x>s8J$YU}Zde z&Ts3dEi|xbGA|P*pd74?z24p;W}qXnbqlZ_unyY->xL^BxC07!ae^u4H4b*9Hr0}QF#@KWL9M@`q zXRg)`mHX}2Y}G0Zksa()pcM?|gZ1ok|>AT&BQHz1Q-l%|Ewh|?n-#{9Q zbOj|P5e#_9UDPArl3XE`T+tTCQh-k+ulFFtXA2MCml&Hn?vpNRm{#38dDaIXwDxd9 zGNj50c^yL>XIUwc8Ao*m|%%X*B_b5X%xY0BoY5I1$(1~Xp<|MtGj#khCzC6@{_F=M3gc^k7t zOCnk!(r@x800mBvJ-<$cO96@TO_*sMLIuz6IxtXc;8dvfc&DlLO!Sp7pp0F|l7x+T zNNB?`((h%RxxQr)kc~+-2EdWdmQ13$7UqLEmHm?QS4#2ZbP?;*o5YEdHxx75hOwW^ zBGVCCZD5HWeE57p`hNj_nxDYUVit!ISV&V*>aMqtPW}^`j~Vbd{zGbD&UEP>_4N-i z%MoWl_rBK?Zx9;W$FB_gD5DDaXEQkbr^2Z4E;zM=`pjVHbgI zIODZlH+4&L1XPRrgmFKo#pUDq#Vs8B0<+9KV|1oz_gs0}0$8c!%EhS(s_*B^*=`30 z@{lSgS$(Nzu@ITtF|-^^0|f|_xRoFF*jpRZj00yy`ep8R#YtNdNx<^iu_9&%PRsr} z$xAf)&4IWnB!Zc{kbbAgj2Ll;4Y*&@*|xh~rP@Y1S}J>y-FXa~sIDZ=g9j5o6)jUC z%FNlDuQ3eZ-5|(&11E7vX>tDgvRz&K2j|S}tu|}dn^5c5F7~E89g_LDzmvDDFdvRU zpAS!~TQ@AcDuH|6{$3dQMe5t3cQgOn=bzk$Z#D?1QO*V^iR)6OIP}87mV)yVkSawae;dx*7vt(q>ZgwQfp-rCUdSycit4W z>sk1E**G~^Reag>k2g~_i}Se8_)2Z%`^Ur*>q6_ss);AA^#QZ`f}dYLCv_%CoNjtL zRqy}4>fB&c^~?+MLi9v$I!s6@fA|l=e6zMxdj}~=F8o`WT~)-zg}-bM6eW& z=`^$eoQKDGZS#uHP|D*$t(}hPTdkZz@v4irNvd;q@2cvGe5(1<#*b2qRDH+W1>2U` ztws{z8}d8?hXWJJUwAoaYF#%o@Cf|zEN=MesV=%v83`L5wY#>-4HZJxpLg0_S?GtM z&}0f{N=-?6Gz-V)aMSwYxJTfD?+tS>6pFt7WNF5t)?|Sid!*9VTQqk!G}lod+r*&17d&-oi<7eUVR> zE1Y&h=I~HZEUN>xlYyt$Db+6W*=UTGk_>-%hHzV3=#M;p1nOGx^;&Heznm{{HgLUL z6pG;S^eSum6OcnAAyatIUaUhjKD%zp^5_CXz{I2EDc1*ONKpBY2CUx1?zrK zfmw5iJXjinC`Z`eM^a_>v_qyNZmPLkv+cUg+TRt@y(c_leDOwmp^K_>5{&o5Vd?P~ z!WI{KHNpaGm|%#O!GL;5_GAvo6CV+dHqU&}y zq2Y)x-KE*|VI}Eo_NJ{72}#}0x47C<*RL)^qBvUx#Kip=oG#54;9M=g{+H1OlM*gs zclf0QUbR$Bx+u_?PY4lIcg@nBPqQr}62|90TB9k<_%2^L!ah8mM=0$uYO({QNaX)3 zq$z{5TMZ|1m5Aj3G5DUpp6qW^vfU#hu5~&6&NsaM^AT7a=!*wCDsb?m>ori{LS6{mP z+-0iyO!cDBQ?4psZc#EjpA|eBv{kK|Wcu*haytk<@{^3(x6}{NBm8s5fgA68?lgbp zjbNEdb6g(MBauL|6-X)kYH?R{ZVJSc5nVpV7R?hcEz!7Wa@XUFPpGANlym3NfBzXv zz)I>~V5amwfu^&9GS}JLd<0Zmi@qm}M2iX7T;W;?-3YETNIZOQgshm29#fAV%}cv} zTR$z6+t%456R;H)8QUH*|6X5^N44FEhWerj8WsUVyQZ=|LVuWAOU>I0ICb?gYD0 z*f)TfRfo$x_Eg|!Rqt(omfc@+g~^FQx4S%B3w+Cn>c9S}eQ1C=t0$ZsIZ1>ZTG?|d}QVL|Ch^(QBZ<3)bqOx`E1 zQ2)7BgZid;?FraZ(tLde3_w9JyaUvJ)cBZ_Q*;@tR-EcPO6<%%I5$kW@#0fzTX4*(z}Q=?+LeemN! z_M`>g8-=a2Yzd(z7{llF0EdBG`&Z=IuL4IC0v}wW z6l9qt&en=KCKP)%z}$Ato0G?t^pc)`2pi+l1@E0nP)T5{( zj@W*PcA#Lf6t-O=Cf7_kf4Fvr3S?cm^N+Ov;ye15ZapyM^bb_L9sRjDNf*2tG;~{e z?R*-=ckKQZ-AAc-@Lt<7asElq9(mS{r&6fsASZ(UuP16Lym;V)*;#j7@;e=k);h#hf|XMT$=F6sAG=_|v+>|n%03@NSSgIFViH)VCdQ4lDm zD2NPr;jd>l+&z6mPM#(I_M?#w)b7)!@HIvhhzOd$bWK(YIFGbG?g-;JLNV6|*wg@# z^ME6nyPI)kv6T0ix@(oTDPG51=)2qVWml#B54jq^mAJ7rp~lX<=XJRN@owgH~6 zYS-+q^RgJ+|EZ~+D2qQc$Lq5q;8D-J$lzv?!yJovS!>+WbocnMumnWnDvP)!;A3l? z@Q=*%b?uPH6%@~zPU>{wonGVq%JLG4j{irIz9N-mXB_Xh5@!p#SK54i6*x>MJc{E1{VE~R(Uen2{5oRAQDJ?w*mY_z|6 z03pStPTMm?P$?6jtC{sQr@lfYckZPA=bF5#o5sCPxGj^qm6x{HEO_D%Y6dBmmhEyo+f_8nR59CARKqzxnFIcf|vanU&t^oBJB&&A#T2)5CLT$QF>-2_*acn zIGw9u*Zwby{p<)rXI(LY=w~4Mz;^2XYsGx#?fk0zWDlo86SkAACcb;`Nof}a4N!-m z2Ts}ZB1__CaxHlIMB<1K8;d55)Hj zj#ftG6eCp;sUhbe+sTV|zWL+?vfR|J`KTze24gWE#^>EVhvY(^QU5l=c9Ol!XS}%9 zOoVqDmV!T*5zWIx0@>%4U|UKIlyVKH^OR7fAzzQ1g}XR57pe6WJV`WFD&lny5U$rN z5`C{~5N2{)35O0Y_is%PXf3}qRW5viL9|Z&+nyBOnJ|%LK#<@lXD9m7MLf1 zx)NS~ue`7D^u4ZNoxZ((huIh7D$aTF&z%~51r-7<70CnHsT`?`M6OpzE*9`a(wlc; zgtLLpwS|9Hew}BL81$FH-Ob|sTbfws%3YaPxlQD5pg-G(3jST=em%n3Lrz53@_q$) zRKmGgc%E)ed)5f&++Jy?Bkv~pfkao$SNy%gooAaNyo+R>a7f)RlGrqndl8!gI$86Y zQUv_veuaOo?fp3K4~pBvRjaj@6IJ_~@r);~hPC!wqL!CMBN&F4{Ld!4r1 ziv7j$e8c*=iMY7+45#6}ny$Uzo?5dobwzi$mpXQV@;3C` z@c1jr#e&vz?}R~KB9lCA_RzX4x;kVdviUBh?6&CFL z$c?|19w!<@HyuGc8lbXbyF&_Z5EBQ%LOpxs5hJ&r z+nE+KTLDwUW{CtkSOG5`yxMmCd%KBf$D%=p%a~lY40v%o@ft(zDx2gZGX+)e)&NdD z+Di#Be0W^E^fx91wmuyFAy{Ws{MCqypkM0_GkQ8+`i~kXibMc^;C&){ZVQk4OW{$V z17b+S*c~_;dpfS0*C-pXuHn8n$2-l0)rI&+nEq9Cuv*Dh6dLiqyOC9ryzEoi`|0JhD#$O0qYg1LsIaou_yc3cX(Ay!o)oDh7_KH_g#N+p8F#w?wfIlQybD zkD`Rdcvy$ZHY+AtMJ7|k%h{d+4NVefZHE-Ei>Y4t^tzqb`vBi*re{(YFjO`qpLB~IP~f$=^-0G8&St}Im^+uYFUkPwUJRfaBPkhoXS$0 zx?L~vgAQ77Oa&JnZ{4uQs-u8h4>+!5VpfEZ?k`8rUL z^qH~)l`kY{({a7YaVI65x6nvC>$*8V9aW_bdU~I9fSeVq)g3CrK33-p>=aNbtUBT8 z@N%Yy4+{$F4B^D~d4=&P{7urZFrAf_>}^8s5qTAqCQ3~wKHUNSoIS=IofLAuRIR?? zCw91SNMAWu1L1}fQ6}og&QvyoJ{K7yZM{w9!j;)A+YZyDL{S`rMn-oGRDctINR)e zJhB&4t;phR*4k5pPne+-$bc@zvyYAQ-N{b@!$@fQOte$=h0I5@uO#0X0JnG~U)2OI z&dw#Y#vgQHdB8ZS;~+u4>I3}zpU8ftQW!g3uEhivGe9`rb{bOy0DK8wg73fG(RB=z zEE(ZUGX5y=Yw+X0VZ+9sceYWmdWV8|blh>pZ%1-{ozyOJB(H{7QN8Km#*c!i!&WW3 z)$XgS$w{j-VO)3Pr;1x=Lm|sc>;K((`W^GpXjTAp0F(4WgS_;90MI~GfNT#&xEZM_v*fq_<9Cpms{C1#mhcZ!x~{@ z$FGo8mV|>flRq!a3_7R@0&dSv?5VA68VrnH72CtAfNCJ^0M22&*fI+Dr5Sni+?;LH z_R7)u{fK+QCn7^*!L3t{-w~HC#VWiIuHe{_pSx^i^PCj{Vz~9t0Lu< zDe&^Of9J?htH%swyZhS@grlo7dth+0 ztijy0NAmG(^8ZfufT*oB#Au|*+A%MK*!>3R8ef{9+1-EEZaaC`yxv4EKN%KY*O z0JCxFMt_qudw8%&CI+u9x?Dwa>Bg>H`oty)OZO3~}68&VNwE7ve(T*lHLZX)LjK35l>y2~cvzU4nwX8XvZ z(0x1L!`kOp@e&@t1E(8T z`!3_HT=C9uzkrXGd%!mjXJaqFPk4%AW12nM*s1NNa@p)%Duob$_45uD3#M>-%Ml?=u1m*k;?A zFQ9F#KYpYkrJ&Xj;kc)y__JA4qie0FMDfuJE>>+z?CTZ)Osu$^*H=PI9;W9tQJPwWn)m2*a zj5V{1Uno0o$;Hi^zr)gmLs5)#hm82b-#_Qe-e zCe>wfNg0>r??d~(^+ZBjuwD^ibXI?6Lh$2U6*QRxl)vF^!vmg~O|seXDa>|n9iR3y zIw4DWzla=7WJR~>FTe|7QvRhLez%i*F_FKSI(7X@kZ&3x8Z*kyWx0N>mme24jXPC7 zE^iHZq6*u-Jdx_%@}-Y)AYU5Qk%G@Cmev37kiu;v1A#n<(4* zsJjh;%9HEkec!(wjdrV-M0NeJdOB|@kDx%BvIno_8c)S+fzs~S#3~fB9_5&gVN9Eo z{qDIkOzlik0mtr3AKlR=8?`(+L7g#l&clzfawpPIS%Ib!dvq58M?QMwVHCgPmB26dAYE zH^&)-2(&>HKi8mFG(6@wa2rg#&HiIKcm$8{J5ggOUbsL7H9#~y?VK?7v2$O0EIlo@ z)NKBek+sWMMoyQP%!`av-n<_tr;tn(Z(W+B83p{k<`Z9yuiT6FAk%j}#tbYq`N zLlD>=8@@b1I-y4COCFpuCI#ZGP}Mlt>4LqMs+qeOmvcx-1(MUtYeg?$#-%v8RMb=+ zuB8BnQ*-{X(F^A}~~^qq^ZDrFkUen3O<#oR}& zS`8rGK$+OmveJ3W&T|%hMbJ1F4S^ib%v5XRli#u;f%5t$YM9r-NAy~`?qIyj@Ak|P zLSMeO)mX5L5(3oBDr5)Eq3p~BB)b~!-$5Srl4MXJ{-g)rzMG|3FXls2H81)rvaw<5 z&!gIm^DjT`S4IPeREoortZQ|mkPsc{Tdd?@AEE5=6m%CHXWh8`(^C6;$m6@K7bMkO zFWw$;FeT6T9g}{qX-`L{lG7jPs$(Efw2!N?VmY@he>riu)1*Fp%2U16{?LWcnonMVhUx)>#02f>M?0!<}0 zj^!Aj=`b&oR`{2VO_>Gui5Z7?O_RtqsBrUVUJHs1mklAJd;sK!0!0%3uxI@YmWLvl|^09BQfJN zRiO)zO%z}!KPCeY#4B<9HlulnzcxwdP1lMP=GyssFQ|E(WN_3R4^{H=5%$R3>b_Q& zZR>on*MRxg$7b`;B$^$`Z1UsRGMZ${gPbYQ?9tc#8k)`6pWWgLn$ z(F>Lp(o;i#WRMrY@qscvH>E%x|3WRba>{Q*amFe;>-F{RpvO-uz|bQpGHZ?AvUB0c z|0WP6LW7N=r^>)Q2qu(;Jvw8B3Nvr=Xe>z)xTaa6AZa4CmMSRX3S=+m~vH@E?7_PXfpYC!CW6b|}1s9E*L=_qk@5HJn3jdF=~~h1f8Z8{tv>T*dTR+QN}-!&pF?z`IGBWrTG4 ztH7QUQBgw{O1djpkoNnpoNo{_U4afUY$xKNDgI6;t`P2Bvfc&wU9X!h*Crs*Bx$e$ zRp#nAzupzMp_9)cO0!F80lM42k0Rp9$3pzfn%kZmr6%jN)=-j1dSQ8oAJ1z~*HFv- z+m!m$I^Nu$2a|WC7VCe|j)U>w*?V%wA6$!qeRfKKVn2m_A@El9dvYa8y?KYC?P93sYn7++Q6;W~WPP`;%qPKL?*Acd$m1lQM?nNQ)kKJjyJ6Uq9 z3r_Zjqa$$rELs$n7Elpi#mPQPHHp|^3&O$+MVcOBIr`Ul_z$HxqITFWjC3ePpigae zA0Z_4@>Cm^-i{H=+u2{FpV=W-Z9aeGF3ksA6tRnsesp3#>42MH?0%S zsmBK-)GC!CQeF zu~Jw>>CI1tqu319NizZ%ZEeMXFe@6sy%d2yssa0T<=z;xzG+>{Xy3m0z|xp}q1o$w ziFt6z1c~&5zT|Pjjz(YXR$r`VUy49~dZ0jpXM5sdR+owuT$-*xY?jN2?avE*l)B$n zfbOMd^*F0wa(i$u-AIMVboD21;$X3mW>%0}UQH4^*K0?-&fkFBW{{ z2OxN@pXme7wg#d@25QU*75f8q0tD(>Of|YcP$5QoCt9DtX0T{oUpiRoYhBwlSS&Tz zx;WT1b0l^4z80{lY#VITvau0++vWVW+xKmcXF-R-+rH9AuR`7qG`t<`vZ;@?>0f+X zRrK~PbZA6iXjGEd9&W3 z8aTY(Fu0;+Us5o9D-R~8+j#W`)gp}9+7NfF#_)InOu~xomyLDAO0+aUtJv|c&RtstG;Fa0W=P=;1HmC={Z681y)UwUu9 z5!h?hHr!=%v@d4Q7Fp1Mtbg~uLuV^iOpKD~;ZTS!mTjlW<|#$2j+C0gSteSE&cefq z1J_)kXG9zYBH;u|?8Xf{;l{BqGELFqz<~nqT?$Q)P66qT)vbUx0`3qXs3tznvW73v?tD(aM&l1-hbs7J<?^->qh}&d z`k!%H5dAQ>P(Y0Ay;6OIay#QE_-^jUM1Vxj_t=DUK@)Fm&iK!Ee|K~MJ*~X&@W^0m zLa_R5@IjC5lJnG-bGaVdQq6dQLi~*@iQ!nlHT3YN((qj$@o_2^H!IZ z+rcWWy4y8$k|SM~#-Y!C2TQv#;zq8B_Z68QTcc%{!Q2zvT~Kah3Jk#jj=*vS)$b#B z*u4CwvQDw5pMu}?o!QS!h{P5#WN9W^uCcQmNAGzk$Q_}^mR9XCQZrc=>8UCU4_o27 zgZRXlm^?yVybxsGBGAq=G>FY?WGsBpTs%{I_D9HcQ=|uU_T%R>eLjQnYUVDt^5F!L zIHx%n&%v|A69l?^&6LyYt@(qb9zzk6X1o_7X zyyWF$LRGrt9q0fXJD_n=L&ua|7o3>#gZ4G$b4uQM72gau5o&owo2tl{s{`>O{%Wuy zfUun$(n*C4BZSGU*fn^_2>4rT8aExf_%fL@9{f{+LLkuC{GA>;yVU)7Vf}=cZ7c4L zW0KoQ-5wS|HFu_T(vFnmtq#=1@4``eG?QjvZ!&>nE#~@5JFEp1YIPDU0-V6l*Q$d! zN%TEt*;U^RI|^vuwd(h&2OEum9{@+YQuarR4yvPf!(K^{k;YEgimL1=*JuPj>3kv0 zdPidKkjRAJF|VzFeyife0W?*_3BV!g0?`YGqE^k&v64P8bsw2!+A%snU+}5dE5D70 zE?-Fkuz*HA+EQ-*p1#kYAVTE!x#881W%+Q^*_n}1nq^!0jW`$=`N7qB>hf%}xkxn! zc~CkJc#LQ;PkG9XrP61p(iOm7vzA`IuXGhf$Zh%QxSII}r?7$|8hNz%hrYxXZ72rd zh<@Uoh`+WEqrSn<#{*vfz$BsN&UV_h^AwJ?Xw^yT#B(N(af?X^f1( z9d-)Y$)|C76vN7eL45o_cZReAwdK9TQfumZrvGDPG?2ia8_e@m789lr^W`ud5MGPs zqgQ}{Q%N;&V{BW7Vf3{-9K^h&*gP74SVd+SzwmToh%0DDiK@C5UBnM?kfh!bXrg^w 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 E7yo$oa{vGU literal 0 HcmV?d00001 diff --git a/frontend/resources/images/on-handoff.gif b/frontend/resources/images/on-handoff.gif new file mode 100644 index 0000000000000000000000000000000000000000..e5feb0af9c2a222b44eb32344e512138c209e895 GIT binary patch literal 647073 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%0Ac32 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�p~OdmBRDU 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
    =HJepwZGor8nIt~1-c3%q)skmg_> zWiOA2GDMv{LYv{g0}+wFO)7N6Ck)7&#R%RM&nA?kalh zdVx91VZkEJu@9s!Gd+Cg{bMJo#KUWd5vUSE5`;D;(Su_xJV4Cx}W|w*G_;Bw?)9*w=tdyBI%H$GjV)Y}+|1zR}@m`=Vk7K%z?VCN}$$I*mjG*$gHzm)4Y>Ms@5+cq{cqxXz&N4%dw$j@x8F4u!*oV4j zFG9|1BWz6Rq92dsZL+hp4hxPyc6xr*kGGa#`Xpnaqw^-+d5p4zb?D6ryt+DTNM5#LO9)t>hmh~Y|C>d`Ps zM99EpM9yolUpQHkN2!oIO=C%3H-^h2CBI&)kEXqGOxp)vlNuEcoGlF0F2hu`cb8eKyCfUN^|{4-J%X?)Tu*%i7F~!Ds5+*L)BL0NK4Yii>_Q!h%^=!kJ1Qc& zOmhYf&ZmfcM$KALH`yL)rw&L)g0b{ESiVh@i(%4-=}QP(p2)u>dGV+YhVE>(bDn%D zGjC*$xyfE|NcTy5_c8^sPvXr~6IYp*SbuGNtc3ac`OMxy&a9p>_|>pXmert;|$mtE>as)>60PG9_fEzG;<(zU)(c zqt85l`ZYs?cHSFS;1Kys0z^5U6(Wds_#6E8xE0OUx2i}$j?Ambdy!1I2`+PZVz)DVNRw}TfT%X%%`xToWLdrYtzkn}0!6d)z>xl$bpiNSY_CxSj|I*w}71+mG+LK^EK0-RjJT5gF zrV3SdYavv46zLwzi89{J1G~nmOxuVSvoo1S|MHE`d}>gz8IIX56&1^1L*{PpBAsEH zy}2(mYvKM5O8zF(bG?M`rSDBCi|#Gr?{+ zBWk!ZdZFY*z|?m+X3ys_sgM~A2w4W=W2N2b`b&xn2`tY4@KRFv68$dk4a`4tOf%~1 zv8dEb%qX$Xrlv53TT<<9n+)c^ihKw#gdeqQKzee>2quY2y4^8ut6c+QejVCDh^C{< zbrSb6ATMZ^Roh&Z%j6N-b=A z-2y$2^S&>Ol&FtntL!;u^J)M0jV?TB5iWMdk2zA!(Gt4htul71bgT`Mhpjh%8+m*N zed@ayhc=$ivg1$D9Pg+TKpm2bZyx6cJE$1PXucX4GJQG=b3}wwXHEAsLYY!7I!)XQwNm6W4Qg3&p71_V%;R*wT_{fI7UQZKzM z<^Y1%JSJ+z@u;%7DBI{JVg^S?Db>WooOS}QUQc=7tc^3bJDN-k5_yd4Mc`btPb)Xi zC})<4qEP&zi8#Dt7^$auMo6dNxs0#@iU%Re&#{Yo z;Rjp~>Yk-2JU7|@Ad6}>p%Rh9?LtbOt|gvjr7GHb^mW`F)2}yzn_LMS3Ip0T1-QK{ z5frkWU$2ywd}LsODqd-->m3cEH9%v#!(Z3d>-wVtJoPmR!+|9$0ykq_fl<3ipNn(t zIM7qlz`*f~ZX{DfhQ@o7wOC3^tG>JwFaqiI2^s;0F^)l(T&2Hi{6Yd7wntH23%Kxz zYQ9bg^3Cw=BSs!}cTDsKuAhdCfo6#%)hqlmk=)?b7vdvF6YDL%lW4QbuG%EP?X1zg zp`RjiJc+@~2~rFM`$Ci$=ss`u`NW5UZ0)P5tMFrxWXHS%5*c-tb}>)6_NV1^^t!x$ z<;MG-)YA%Wkoot^jD1)XLF3Ldp#(g?s7sm>ZR@}`ofhApyKE*ZHuaRWz9)j}>IHo> z_E>ZaloVN85Q-L%etagSkweQ5mM80Gw+yc4I9fuada+MkZShK!HHZ%~;Tk9u-U~-6 zVN!{oOvbjskEFA zNk`Ab%TG0V(qsS+t7Bsb*%XNkt?9!GiIJjr&J?uQ%(ES!PFQ%n5(utFrktr1QqumC z=?MEw6g3z=`hZh{_1V#i3JJ)E?F_Uotf~AK1$}|x_%xK_83r@7pD-+vlbMMA|*7+hh0j3W#31(_oiE<zAXZFb){8Df*|`k457Ftryc9$=t1+zp&flDx6jm>6vxc zbO6@oJf(iLhbj)^_@uM&Y_uQM_S&ut@B17rSrSY)m9H~-?ZsSw$& zB$$-H28cKvEd9D1YvyS$N?KF6Cc#x{ZJVVdK5`Ykd#IAPNJm->bLDHKhLwEMGeVHO zrh10JfyZg4;G7k8(@Qibwq@yA`v6w;J+jh}5ST+GoZ=<#)O+m3ap ztT$Kof{@dKYO{;Ya5aaU_2FtI`PrsI`%K8TaAST?FN*0|r$tvdKDN)$_oxTx7(zx? z$_cJbHVzSJUbm(9F^PZQ0k!=@@?s~kW$O9Z9jH)OP$6y3a*WRv2c`4tYxV6IBOWLd z!?!H1-y$Ealt-$F@o?&uNEUXl5Vc9X2FFM`-5a(#>5}x?ID=1UO_V9daT))D@Jh99 zK-Mzy&3k~@MA3ezo@Zd{7+r$T3)HwZfJxtA*c;~y$ellX_QQ*=UT%7dkNiy#;Mk)Q z5sWsOW7?H0wVCcm5t#aZvHiQlHvF4e)bWbwaFZ8CNdgOKtUbOVc`^*#c7}#QcIqG% zbWp(#S0D&=FZq)q)4e^jEqd+RSiJZtk{!_|N<`OoMZ%8j%aU=j*DhpTy|_v zt$NZG%SJ6ToW-*$~k9Q=Or(4kYtOlyD4yzsuRQhgqk6|`EH%U ziIh)s$JJnF=7=YMUwUv3!4b2O3Dp*=>IjtjNxOOpCF%PFNI!9Ro8DlA){>?F{b**0 ztL`auUd(Vp@cwkmIB;93D`RN(> zYA1m~X~(?{qiTyo42^ELxdxVYO712^HbfL*)`n+sTizsv$U7E9tQ#w0q@^Z^zK^6& zt~JUI^mt1kq)Sq#D0A`0@lpo~ijJ&qehNu)FW~iOPKM22u>Pe(#9F(-3|4!pJRSD{ zw{0vs;uxfe$+DYLJdsSe*LXu&DB^733x#)&xk@{E`3+STfBr?UeTQt_JFo7<@ff<0 zI&{_dwXNE92M|>EFT^-lRBc->q-3#tkL0Q&xu@BM zrvSQ38`f$|__i_=S5%Iwz{@PSX$}{Faw-q8>6K4l0hS0!V33XnPtLpk{_%9@B zLmw+l!{)-Y1_H^vGp{SWa;9!EV3_M8ecWpmV&XCY!Y=d#ak3mVR)Av<{QZu9O3r(* zR=H-s`o~F5Qi{@L6tu^oV5ZSFHxJ2TD{zR{RBt|F?ntz$q$k%&Fo)x9>X;b1GBW^H z`a7o2qUqplWh7ofZ3k5iky4tIzJ`Ktclvevy_Yw>yT6SY z*bt*yk5Dj53Np;&d*2JEhx0tJjQ%>rbajCGIKg4AMAKo7r3F=rkg1NT_BH|d{dj{f~^{E(+2;Cpo}zMf-s|P^zNOHmLsGQ(NX!+m4WB zy&Bi)OzWt;4Fvs9%n@Nhy5IDG#7y=-m=}LR2N{URZdisO$)Bh@Ah4N!+$mJzsHlq; zp_zhLEQ1UIig>kyPTK5d%Jd<|2;!3j|5Al}1lP%YI1<1N?G)Gr@PyE zUZHoTnaZjyriy=EI+o3lC=c5INTiH3yE46Oa$qY(WjKyY;x7w8#Qp5TEMN z2>hrxBC!O&QHEcgrn|&8JQ#E7%3Pi5cJdxLk(C;r`9lQh$HU8sy1C-wt5o)erKEAT z(BC&cNN07rO)@FUiac(TZDLj+IBd!MgiIOitP=tFv^5PoAc zc3-8iN{>3F^J8{s-^$?4xA*;(#DGZhb9aX>qI$`@{z}!0x0<%c-xTQ98e}r^7NxX6 zL)xgc%R;dHk7`ir+T}qvqo84+(gA52;WMT*0PHoM$V;Q@!wR#~6Gq5k5hMRTI22M- z7M>ol7kWx0vgrf;6mFi;kK-Phhp7u4Cj!qrcG6;RsqH-(c!m@qUbZzta*na=uBWe< ztX1Xd!#?$|`+QGhpJXt8fKV8&(aB+#yIVfGqrv9G5{9|bScKp#;jATPoBV!n@~CJm zxWSqd@UH`I5uG(h2ndS^-#l82U#g1*V@@l7L2~$0IVpYWvzJJp!YV*YC6e(hZA75I zr~M$Wss*&TC)nzc1O^g$S02MqS_3x@-Y}Ml^jWKqY6Epg(W}3Po7*;peHWHlaOrV& z4wI_UF~Vn@SJRx&9_7xvA+Dn{i*8QseQ;Gf-ikO%+-NdQv-9tR-uQa$p*<;D&M)V6 z#H;ljf$toF({H~Ve9xT^8_;cWAa2_#;e|nzLH})y`n3!UA;XrtJRnkjx14@y!~LO9 z!${t^2%Y9(?>!wY;qXkg3~rFlb-6TTLU$wn&5K?NYTZ?Tv2L3yLLask(|(fHEd)cE zX})Lr-1$0&z;1H2hix@m1q8N$?;Kwlc7H^&2-$9lZEi&$ zZ6`G*mo!XwTXAa@rcc+JQ&*keH9WZ7)A^;$aD+8pG;|rk;_$OT_y?LF9YUKHuGzm2 z_yqsZAH2rxs&B5BCpzRPTHSJJBBdGMdU4)4_GIf?9tZVG>6@`w!YpAEMSoX-#dno< zJ(j`8@`dZJx&Gy2$EK^F(dcc9AuPbA*hP_-IiC<|FjG+CeEa4l(uet*4zJq$Q8?2y z+ST}KhgWY>(_sv$J<0o;G3x?RF9@-47u`cq9nPP)^Fe3C?K?mZKzH@I8a`9CYE1d( z^et39Q4iBc9m`^!o}_n17lCdXHw%txz1D~At!@^;zHoPHo{B6&mm+SzDMe+ny<*A2 zN;e_!##%n-w-uqSf-qYrotFpk7fC4TA(8OV8{7MwH3AwWZ9m7IjCOGNaND)%ajHtre?L3u$rKyGvnVU=XXlSx4DNI_?f8D=ERi?6mL4yzcj{Um zS5AXS=r~(ju4B;t={`07ALFdHrQ(zkUG>k)W{G!9uG}$sF=WOxFuQ7CJ_j{#OfYNw zW=b z9h}aMMbF2|wL9*&K1Io@!gZU^kP-=(4N3gnBxv^q?y&fS(#7Cm(We30Ht=tda3nFt z^{~$SSKQ@t1$LUwKP9y$pZMIP@3>!mL%M3@hyGzmg0h6TJ3b6gsdtUOU*gAf5_Z30 zKXX~>^!&%|iJO!5R$vSNAG_MH_;jO-CEdY?j7<|{SX1ye`7d4%K>tpCc5)e27ylOT zdiN`|LBW$OY^>XEEBK64G+(@ALP%-@-0>c*6|T;$&hIC5_L$yXSb3zd9Hj z7dGeY#c$)0@w37hKY50zv=g&@PTWYxuFlw}?8wi%ORlJQ5(j?KLw;Uz4As}A8b}S9 zNJ5R2Xy#mq;`BFr3p-VSeL0}(Lg;hw^7(T)Fh#R4s~~&YyBh+(4C%|Irh}n+AB>`) zCW$tC@Xhd#EdN%WL*HyCf2Fsp+3e6PNkb+RL)JTXHs6P=EA1Q}eJgfP&c1JOC7OHm zoGv5VfgMLl@nFP4OcDt2sL|xB%VAjeBnibtvM0Z&=uNhSslrnjEo!$=@p|z$JEcmf z)r6hRq@5MpuKFst^h$!}_K@{=nk5O)uT3el0>ShDOs9hWf&UQzT^UtiIFCNoMAxKT;&9xfsoIhi1-( z7GJzme1TdY(q})E5N%YHh6G<}MNz~J|E z-O=2$E~AYH4BhHxCH_f~sJhc(@z3oEJH1o`n{Aq&rG*jfzPTy%&M4J^{~xJ9vy#t4 zQl=J0fyqjw)Q+c6$NNclKXae)!F}d-ydIQ>2Qw0C&u0*f$kysnlF2@y?2GDJe1*id zpIx`04Ne~{B+Sii+Dy%xpf+OAp^M*&4?vj-X7x9EiiE9<)XeKuhfI|0iY)G1I-1>< z{KqhMG;{nJw?THJ2!p1++g7*Zn9p1kxyJGSi-FD9h zryKX-LH!e2z3`=(LzhgTRz_k&4y{AhY`X!S)S*2)8@B1}Q>bF%o#Ll<5`n#UKJS^R zAXMTnTs*O=G{E-u)&)TTSTh>*f=)>NxH#%^D}o4m{OgY^=Xc);`|xB68|FXv`2Cx2 zRu{GVEJ2s2`5%~wK3w7dC(Gnt>%cyT!zuc>%X&)vmWS_`e6!P!t=O=LFF^hJs{y}R zb$RQpPXdCoHL77ZR_&U4@79Zl{ol^F8;pMHc@UAbID9le=+2|hA;DH^DPO(Jabkzl zKLrk4`r9O)-R*w;ns2B6mW%Po0w?9)ht-Nnc@+;XhoEZiFPuG5LRIys(i|b;GBH}} z2$oslhAT`=X*!h60YTtKl&LxeGV+PE0cFy6<|_jv;zn~QcDCiXG%5!9Du2Q6MICE5 zYS--5zvK8EqZe|7%uAy%+Rv_x6kC*@Ie!1bTTi>uvp0gyA^59a-E-%WFQ*F2ZK%4p zTVB5YU1EFT>dZ*~KN^j558?;;QF<%RI1ahXm5(ptze#m+dQOE)lajiOQs$hva>?Vm zs0+4FF!!z-zs|iE{jr&wuX^lZW%4(+%x}*RV=Rxc{!7jCh4+rXvA+7xhMvThPPsu8 zJXdh)0bpr!4q{Xrn9MPpn%BoK6Jj5!K%doKs%WN{XF)WWas?4FDovH>D9$o$vkm`N zrfqrFm%h+8j4he&kgM!Cd4Y{N{s%X>faAg6!T0dj6$9 z_|dXm?~|dRaQu|-L`u;qM~Co3 zMnLJ1PK6`MUOFyKdk%)Z>#MqqvTcwHO&KsM4_b1Y;Je`yi}UJya`dHVWSgq;M4Dx! zViDmz|82n`ag*27%3!5?eR*|P4dKpq?0T)}_jo=yoVBv}s^>9@@6yw~zws|=m?MP_ z*w2B-3`BloI)gJ_oKq=T6GE^&!P9-lEte=V6j-WWW$>iIF|652vEP}z)zaacjyKLq zq?;W-r5pSS6dI{9z!M4GDQ}R(iSnTTX)5iyA_C4VMXsH`EWK(Zk}E^3JS;1CQ_Jd; zSu4qLmj^v^L;L0S9lfrK)szQ57J=FIL%k0xR=TIDR2 zPc@Wpt!-=ub$lrQBNX^`TwVC_&P459(*W8t@1tq*;k*Z5XPh$7-=3*gsYvL0pUyLk8{doDd@Ke4cR(is__?frNQbXC9=AUoXN00w5{Jzu=#HjCKE!^IkoTAhh@6Rk^wVCs9oczgsEr>4CB&qxDsE)beO{M5E6>Ak&-u))7euFuOi6?0HFYvE z1EvBIyV^mM9Mg69Zf19BJ9-%#2BDixb*hjnL&t)oCr)3olP*r>V)BW6=9~dEODY5& zw)(id2d8o#fszmVEpDe$ST3~$*N)b=BaYQEjm4CYE4-L&5_7-yI`qgdg}C8z4oQV= zDD)w<)LPCVEbdL>JBw#s=ub!4IbJb(j3Z+pT zbT3fjs#f$+A(3HiG|pB>S9s)(D2rtz5q_=xX8wa@=f-eV&3%gKN+5h$5GI1pD61=X zs!Qbu)E=FH5kpQRmc5rW?r%d>(t@yboEdyy616^Z&{G218^$1R3JM_0YaK$B-@ zg%8;9M{?VT6>&O(Ncl5|{!gq0)CQurMit+L_H(~UytnYk^HK5aSRuIo7O%Zq+`jV) zt7OR}oVY8brmpcJ=)S`J(?5$lmo!hh2aL~p{7lfk8nYdCZ5%ICaZY9A_gn8R1;5F> zqXnKl5GjHaUpvIUt8iU2aLLJk(Rl_VQ zm&@8FCH+cJS?_F*oR<0Y?EuY$&H#T>!N574TxaJm7017fhzPV@gt^3BRQ&qoJK)UB2Iz(Z}~*q-fvBz2<-J;OUCg8f{KnYe#;JB=@M7oL6wi@SeqNVdW0SWxt}*#_+SuH&!8iKjbN zK7{{jxE_^t_QT8hH$iIsaPsGijVW!<_?+c!XZk$~-eN*K?8wnKKOaN$L?24^lwDZp z>%k9-m6nCeyW%rG2`Y&3Ue<&^s>ycmGJhpG`pr;ML-bSmsSEAb8#wCPqQ&%mzm0nSsy8{Ybt7SRdy2)DysWn`Ns9w9jn~_5h3S& zVR`Ae?DO~MWNA7W^s7@MS*#Bw(6GHNGZPCB3Ng4_QtAfkM zgzJ7{`v!s%B4GSFYVfjKKj3;C5hVF)%1t?Y(3xL@;^Er@uEJF`R;)Ro9>l!%Mp2L6d zeV==eamMovp0|0mMv~vU=DgNi*Mb_V9O>J=D1mEVYt=&4+*qWzJ?1W=f*%!CxZ)en z-uBBxiBns2JRF+ULV5e}^332S5a2ZXaHhQNo3D>t>~*AN_e6M=j90wE|Ova`Bb4nTw>^zXgFhlFH!;{XeySK>!3 z_5;=-uBHK~W*r#(u>*DHMC+9`4J+6!D?~6m68nhlV-+^oF^Mi=SN~AFX$OH5H;Vw4 zm*p6#9M&Wnf-rE+p9J(YpwI>xaK8V+9#!-_p0K@tC;$n0`7`I_*JLQycK{~l0p)Ki z%4=3EsaWtVcQD)z+=9R!4nb>GtwWp;#;xeSeNB=JJejv|?B~Rig?fBf#r}@K4r9dX z4szT)p_MBo9n7ER#t% zQwB=Rq0#+EKRUU%pLM+ncHEBwo5R}G<@*TO5@9grYpxs_05bwbs|-w4`e!tX9}U1_ zvNjk*RO7Zw8vVX8wM-R_o+Y`u>ho4KZ8lZuoAyokd;tn=y+dbH+#e+e@1_v8qBk5p zrSnSTI4vxIsngantOy7_=lXa(ht-^v1#4877V^-cal5~w{{uVnL(63G5H>MYp?`H! z0GRl!e%1<|`s_7B4TntJoBR{}aOfkqW1Tf7Cb)*jq!c90(=KFYF8uy+kU)c& z4$tPL9&z&@;4swhg_$F-%n;fb2fueIzx4#K_r!|_T(sdqfQO@i%)m2FdfvqNAAa26 zEVa^>80>xA|;? z9D*qcPIl)x74)|66yNwu0Ga*NdcmOvbV&s7zWR)ZIo@W7TSu=Q+M$;(fud)CF-fS0BTLW7Ks;&y4xq;*w*Y@o z1Z=O1KP0+@{UT>vrOGt;MENl(;ui%li69gDiM$RRRAZ#jLteB>#h8tA$jedd=lt5cd(!q0T9~kQ5Ezq{i>as|k+j zcYYy5YBWO;$3Q`84mKinrJ1IfT%{85clrI%EtsF;>81;{AvhK49;`_dCr(1`Z-Y+n zkzenGmg6R92p%_hS}r=JnJ4lcsd}DkxhA+D;nkSzmSRX^8GzN@CAjEn!e;0iFHR$s z4Q_zz9$kHbf}%b zIck){%Z7$uL{}6i_gTV6gmKymc0h8HLVn`=8~08ZqaOySS{ksE zfI`!?FeKv~1(f`GggcId3zi-fC;&@gmm;ZKdsw1+&?(=?ANkK}Q-@RBT{77=XY z3dT;(-&!NnaxXL?OURV~cHkDCxmRObTb_CxERDccHIuGn^U)wDvE zB68IND?&Sq6;PfdZVlTF@vh<6IWy17;3Zr0KlUU@OjpOM>x}E+STKa6@kG^84vDE@ zwi%-hPj--5P8BZ|SA}dw^y+iHRU;+_qEUFY`--lD4i}LMSY`FO5x|Y-;%2p}97T-ot&RPm2bQX$x;#7TC+g!NX9p$tLheDkBO8j}&O#j1F5!YO!;Z|LJy3xFPNzsCA-A z(#!&-I!cR)L3jZfpT2?dD(r6!Y`P~+H=IEW-c}AcPOyvPnAYC31pR6Ui`Uw zHepLsrYcIKGQ}Vn2JbTf;LxizSErOPu4u%Mv_l0Pbd@adD3$JNKyA}S74}nmiYBTAeZ3EU1+!a~|PM8VPv;i9p#ld`JA5Hwa$aKMf zP`K37roPmZ-xi}Ow*C~?1wV?j<%v(41YjOwbAHhU-=lDSG$iSOf|058BK&8wp{N+M z;lRO9^Zo&N1s>G_$MaR*U;>7)t71$j6nKBSuo{463Ba7VUdZypN=g^3d4(BKjciIk+M{NS_Z7U~`LubfQ#^Ygd zCWLS4=u_q)oy{>}`~DA~t$3dkFOrBVcP!H{}6L5sca^ejy+hZaT~_2^faakVj187zvP^aqK(V&@9N#f!z|? zw%|@?JV+5>5+igPVw|LH+h>xj=Ys|I5`eIvpwp?)Llbu*ZS&6%w550I9@&3+wURYa-Wku6rDmyB0lrpb8?^NEps(bz>2(67# zkgcKzf@AZuSZTEE=d@mUc`oR!FcMm~H1M^3)Yh}K9f)te-%y;WVAp|dhJE}CM-2BQm#A{ju8UOPdJAJlBf`Fi z))%XT>CQ*dp-()jvZ@CBW3W2V^t*_|z?+d4+J2OY2*=@_*DB@1kS*MreldLA>R^${o6_pA6%0 zT5!;37w>mm&fuJJJEAEEik{)QRdsaJxUCkH*to3~F;=*(!`>XaZN&HxoX^MU)3W?E z{W2^Fk8uSFWjKGO_1H1IeUEI~DRE@2{ae~@%REcnsdN{6J{=_-8`zxbc?4QI^gJd2 zzVbRbC;aMldU#Ob1uumh)uQu-ro>%T&jXsgMKX3Y5FdryTaE{mqGWM$R9-AKmY zyxG=lh1}`+WVPODG*>aLo_>|{eK-=M3B5mfrMMy-efP8Qtuv;bpFSHLxnKCxog>Cy z*8zS(J1drR@+IKZy~iVu0igABi<0qYPpk+FfS?WI+pfPfXOZbI99nLRhZT6BUPvYv zOQZX>qy1SKx5v^S0WR8e!@h7&i(CtLlrVg4kgATA1^(Zpfk^oBP&FZJo&=bVsO~5;M7RBu~Dbhw=43PKua9*S?nk}*g6)ky} z^6jVSr8qv*(F8i6C`Ocx04g$!s(5Lw4)~;~tU7Y`TeS#-P?uywSu{-CIn}!8grd-W zgIqDsehT%I*KhR&o{7u1=g(j5mk7+AVH08_u&VCaRLmOQRCn}bZ4;V$p1Nlym28EE z=^82zoz40bV9gQH!sn{0 zCu*ew4)jf|6y~2{)!8{0^k|nZFz9~NFnTz!4s2eSEFq0Adk*K%#98!|b#0nVtca@^ zka?j|-!zLnr~uR{=pGr7wM;yJMb~GwxPLlEb?#T;xs0=X-S66VUjD=TD17;T*R}or z;D;{~X9cizMa$}@Mg@vk@f>BM#j%wUrfgX`{$5XW>1QWGOO20}oZLa$UHQFyU=>H_ zy7OvOCgk=0>Z$e&5vFZbxIXSW`G8yZ+ls2luMz9idu}}Q5lIjL>IMX|4KsTD1I6xtcb4 zD2l5Sbsu>vguS=)u5M;J(90@u-di)GQ<>E()m7g#ZUx@X&qZ4C)s~7LSWykn&o8;u zHRB1`1`7XKrsZGivN?227G89a*NzFMlEK0i3}y%Jtg zM-}*m133<4A6miIck7^ny!|dIvW7oX?%FE4ud(-KoqFrb%F`>mQQ_3h8^dn-GEt|| zn(6-3BTwP|C}-Fvd)t1{ydCP?@n_xbq?LBP8CA zrwLbkfVn*(EP$d2_#z~LHza`i+Tq=dhc#Lt1DQXsRsc7B5QiVWW2KZl+oqaVKkXxaFSICgfSX90k zg=-ZYMAx$%7%E#LekhCMrE2h=Q!t0CW6ZV0Ej?Z*xAY=+nBWRpL9d_aw%>YzyL=qR zrD4eT275Iq+A_JUL;bf(^T_RB34vtL;xXtb1_V~ekvNWooO`Wf@?I8-K(E5LPCzsC z!7=>O*HE-$Sv0Ve)A{w=OSfoJBBg6Yw4;{uj-O*9AX>se!qGftN-Ijd-u}nO81ecj zpdY^TD7tbUe(H5tg_*6@7XBrDu+w$;4%}I5DsD0)c4gW@yvOg&R_r3Zc6)C;tw2OA zNqCkPgKxdPG?x2fWyH*Alni--M2ao-mD5~4{wq!AeBOBGLZ9E;$ZxwB()^8~WS^oV z-CPe;6Q93HRK`jqFw^@I7(*=c<||fm_wPhUxd=&%WJOrA4O6lw#cS`KWPDVZe=&EU z91QIXESQx$v>5i#0gH5h6^)g0!I%<{^(xUKBSwA~iph zvoJJuIw!T1g0p-lbp)7JWx-J+m)2#JR^Q0pSe(|_k=7c@){d24z?j~d!us1HJvkt~ z?-T1lUwX`1`p6E;7;8p^M8=dL%S>p7e@@22&CA7|3};~Gs^H6YxlDVb%qwaNwf1vbC6GSqD*ty zO?7KZ^$1J#(oXeZOZB@=3FuD=N=^B0nGzzD5{8`;F%OF>fyH>h;^biol(3}TWLQ&j zYHD)2WpbuaG8{WON60=8+rD7luBgPW#KW#k-mZcYX;-=XwYur+&#neTEa&Ad|MXid zXK#)6J@QtV7TXsP{DnWrg0ikdkXN#Qtj+!vypP@WI$%B){ zO4+4#1msH{AmKmz<&u7Mt#|aya<;0!4Xt-y$nqSh2kh4S3d8-`8=lEGd`p7|hd1Ds zG=$&5BljAJup47_vf~vR$t@d`o3m3&8)^F+GpKU1aGIFensPmJ@~xT_6&wo|(u;(f zN(T5V!=01{nmiPmYZvP4!<+p|o129jTKAg2Tv)aDhPU4|x7-c15AU@jsajDukcdeI1iDu%Mg(HM6oK=n6>lH0g7b?|q>Whd z*YQB|;X)(%pxgF9E4B4k+Voa>FLy@kR_6UA%Cbh5!LMMERt^ylHm^qRKfG@v;z+EU zNvVJFwImAdBSb#?zENz1Dnd0+X+fy`3H^}XtR8{* zI2a=Tr{(i~fc9sEL0Phv$Zu1xZu9$QBMyY|y|>bSgKZg)LrapSV!I12v(uopT}y+9 zm$jQ$kDph2fJkppS^Iad-jF}-VJ*E8xQM9x-WU-?oJe1SH6qEY50;KdZRtxNL}cFg z!S4|{BK>(BzY4tii$4D?;so-z>fwtg-1A~J@`-3C6Lt`966Z?Y~^!Ssb168czlTf_L{h?*t;nlLi-oc@{ z{nTw0+&+%sy}{vwvcb)k)ZYX+hl(Q?ibKZ{soe&+mxCh@ErZveQ-4>EJSvW!iZe8f@sNTwG)jm!3>r!y7#i;O15L(Y?RtUwsBun5v6d@|dO5~M6vt95#`ZYy z??&;5q2n~V_;(1(2L%4^=-7*c!Iw5Eta!tdD){$^@mRZwEht`@;lyj*iHPH;wT(TN zO~m(2EJuJ&5%_(h_*PKlxY`hY1_E=^4^(A9Ew4L7_%InmF*O+h+C|_`(&Il=j_sCB z4-??@ea1B`ACz9ivRr)n5I@5YtB+%1xN>YO2Dkh52(j+Kg8THu{lxAHt_|npfa27h z-7I@KD8+6Dsyh*@GJC%=u0KQxvje?;KZhMT>(V?shC7{5K9zAi4tYOuhQPn!#{ZK( z_dqb$H%N&U3A#`jj4+see=uaS2rI@LVn4w3eLwZpd&Z`9<^hhs?*~HFoxEFlHdr>j z9WnTZb7B{P+2K7B8ky0(I0)ec#QG7O+AU%E5AKfQpK_1pWuR}g;P2Ya_A5@E($8{Q)n96CcJocTbNWY_syhVgZF~ zX-aNoKxFC^y2f6fueL7Y_r;7&i9VZcohFY2EoMxvhzs z%kg8OcspL8vawa`Mf~N_A!+X^>VuWv@Qn<>w9do$^5A;V&N}1pr1sFCt;%tY2fS}X zGn7k|yNJ0r2lLvT_+0Pju?UAh(ZX~N2h}1M20uTo?aw_ozMayfhAv(O!)(+0x!??3 zsP}T`!|J%)*6L^ci{nA*^5tCbLCxV2hr{GZ+F?cAC34%F~$&(!=3ayqzM@-XQB<4QLlVW7nl`K>%-G(0i}%X6l#iK2l`AyKxBM zvyU4&h+N#uZo<_h#PDc#&LDJt^u-y_2eiI&yxI74;I{>)G1l2} z$lS3d)d{NFNx0yNndix4^+{C9iSfe8J<)0G&55D#>7~QzQ+j}2+Ud#oX>#MK&fV$J zo3m7kGcBF7ow&0M_cM*=v#rxJ_}tkCs`J$k=edIC%AV)T)#n8%=dugub3_-#H|Ju) z$cq_=i?UA_tW6i}^B0`A7q2KUUkhFGXkYSrT=J)03N~E|&tHn(UW!p(i3?pxYF|lv zT*;(f$u(Um%wN5~y;7#URu#Hd)4ta5xYkU){?v4>Gk>jnd#z7-V<>dNk5xjCHQJB09*^~@kBv=_&GV0~w~y_V$X`OpPHp6G4`fd&vabm_fKBiPiu5B; z8C?+%!g|hSJUhB78AA9%DNk!`O*(>t*LGueEcdq$5X*=8)A)v50;@)a@f?v!uRoW` zaNehh&G+eoR2|gC6I;q~@oylTzW8m`Jh?rC%|sxcm`Fj=@P)~>hzJKTzue5l*vE;c{4Fmt3I?1h34{-bGU*cG}!`|;20 ziDq~73*{)vlv9&INlvrPKXaR=BiYi0XrlAyJ5`LTKTK_^ovdc72-}i$n|W;(8sD!^ zFE;ahUH-+2N~YKH+J3zci%E0oPo?G7m>^HG-Xf>--rR`M%n}WU>(OdW0GU2gkInsT zCpkxRIg`cn>ZDO3SznC9>+Z&EZD!f`g)b856bV7WQOAa&5)WdEqf_ODh+{B$VM<`J ztA|M7@Ni&C;&Eo6<4L`iM$t4L6C=}~eD#jvAh+t>jcwPMD2=Q7 z4;i{4)Hkvx-p_?EmW_NXOHZBqp(`HG0y+0eUel0wGC5^ z;@q$lF(2=Yart|G)j*!%Ma(>&--1WDoXVoUH8mrk8#EFgaSWP6Wl469w_`n|Cg%cD zbT*@^a)h}*$Nw_^{)tfFe<)Q`&I)Ipl;eHj{7y}|_O*tFqj9YUt^T(Q8RRFk=hYu| z!n=4inO*-n%jx?%ztJ+xWv-2p~(FF{wF~Dv*f%unv zhTl3(8VnuizF&V1efhEeWjIc^z?UHYO*g}6F&6>jSSE0zahUSEo3%u7TR}b*{YPBg zl(VqL%?I=Dl!`Q0E_t)8^<6>p#P8tS7w~Ak0rPwXqo$qKxbID6g@v0%mZiKMLRJxV zo0QDO?MwYuRWBKv_d|x?d3IFJ6v*4uQv?Vf;w%(Ul{6kfSiZLM|7<=&L)E~+{ND#W z7XX34mjJmZzYqyP$D|fG&H@BJ!(#jA^=pJL0TZp0Y?V=0I3~NLdPvoJcQl5u5nAzy zk!&)u*8ZmOhli_^a7kKg!EAkGhw zW~<3l%9PI6`#nFo_OU{hN-3Z6@~>vK304$mYT~N)Pr0egZ)umDi)qwbOXX}(I*E3% zE0=>(WjLh$+gM40djt1shflG`H}eMjzuf_`dc#|~3_`~kkXOE+OnLBlJ(Z^rdfK-DhJA`*qmZuvH z*@7?2+J?pf2FpY%({Fg-i~Bwu>bf zgWLLQA*|trY)m+CNZ?CkQSp^-6ftKPQv@xHAU949$chN3-)+c+RJ9guB+8j$p*qr5 zJl(aENu}R}8K+jhu(`gFR)v|=g$8=_SCHvSTGxFt1sxHDFlDHlviPMKbr5XBjpk!= zJnCON<-xh(2H@PN4*Fs&H%3hzpLdrxjM#B}mf*s;cWmbQ_C`V`iNL1}HtdXmezu}S z7o_Pzdf{!KWg+*UejucHOwhQX2pfQk!?6Mff&@uQB{-kI=-1D}#rEUC<*QT)eakir z2qX@kI_bRz8u`uD!(L2LapWq5`RIsw>cUK*!(;()Vc$kpb6PBBDZN#I%Y$# zolK7<3vP6urPqvnEVcznac`xF3T_xkf_7XAX+1km8sSh zc@qfoO=|VHrlevpsb^^0L!xK@f|H}n54{3xRZ^Zbkdmg0yuH##vt7=OV>!=F$R1PZ8cC!3BGtUU2rRi&+|V~KdJ{<% zXw|WZjTGXDt@sis#_|<2m>iY5u-=+0XF+sG-wP2Jet?T85OGp!u)WXF$aoA&nc7vT z;LiXLHCD6t7QgJYe4h4kTf5vQy6qq|DR-_>=S#_No%%K1HsgyX^glD}dL8a~_@)Eg zC&Qikbac--$WAoc^?tYI%et?AN=Q2}Ex>{0YbPs)a*-U6?ras(h(*)1&i@>(DyDIz zEjqn0j*STp_)bIh!)opK&FQrF*y-Pf;q1%|Q5yE&k?$$gG&r0s&i2w@?IMY}eOg?j zZpTYs`nKiVUj1F*4^q~LNM79B|6Mrx+Ugy!bMVs7=kD+NvhT)DJU#@t6NnFaM$1Cy zgUfeK4|&MH%JR6LWf~Q}y>?vnyhMjZ2Ls&BYl%WpjUQ52J?OX6xiN2yV~yDazN9;jTl~%V6oyuq4knN{&)^^pDU`D#-7Uh1 z?f|UC*t8YD3=b}yQ)%J0VXno{^dw6l$R&(*y9fx=wgepsAd4-Z;>cr)%QKcr zit(&AWf?un=CM(+Gq4pnaC=h$dxZpCmW1gn^upGKV~n0<q+`(;aF+v0q!#9;Ck4C!6COSW+YWz!QU&b*ApB%C=%!p?SlJxMbwF6v>>_Jj~uxP;L zMob`{;B2mPxS;8*zN{Ly-8nCCMGYs=nmnVE4VXS_?eX{%ci)Hm>K|y!X7NU!pgr#w zX>Ng!12+gS`(76EqZ4{b!qs?#?C+jJVkHYFhJ=su)(tr&j%nWI_~$m$g#lX}@qS;o z)G$J%-YNwJiUXCJ(St1GuI;igr!En1lDu#IvTqD-TUE15a0+{v6PcBx{0 z61uZOoDX@rp;H^$W=d|yzX>(RKi9XSFlsrvxDuJ4VToG(J)r-?(4Ap8((&}fqEGJ@ zi><+6yK(~ihuDKjFC+lD8ME3ROhC++E=!p6 zI}n4_Qr+zzp+pt-Kx-V!5szi&{kKqtGpIIgG<-1bNJ^nx~R3 zWK*Y@^7LLs0k0?oeNKI6JWf?rNh3w0RI!Y|+~{7rs&uv#H1y=|RhGvNkuP80fP{!P7n54r+T#Y+=|_6RI7KI-#>PoXi-J70J-!XYTP-E2wy zn%Qj=S$N;Mgqoa9iZfLUK^gP4+cWXv1DW0)9G?rnIqwZTsj9ti5n)_+xnP|=%I`BQ z#lxv>`K{}M^#Lv&mgBynGZQ3T15MN6Zaq);bnr+f!gaJ}eedykx$XKPx*NCaC~ez1 zJkfOC?f^^OA7lT%bIG@>YI@FZ|JO?>`t#3-<$xY)vq&n z*V+CIQRH-iz26EnBxy+nR{b%WLKy5@S%c>!csI9Dq9jv~qacs4-Y=H)=&UgqD(`ks za5w!5j3bx@i?b3`Kin97SG3G~kpPa7D@eYb{qiS{&f?Q%8Z82=GgjD$73_bL0^iE? zO6A_N(9CoxbaTJ7U;$}Nvu;b-Qd*jWjuJ4}b8s860yC3uLw7Rys8cq4tH(kLp~)S7 z0a^K(*qtR{DE79m3lJ$-0$?e#EXk^^DA~=gFd}Dnx!Gwd!LHksx2~vomz-V}ge_H8 z&Mh(kgglP+f@}CX5I`J(B0ovcpAr=u>1-qR)q3t(gv5*SA_G)hrSy*j?B^W;xNnb& z8q2~CypuZXIf7nO6C(ddK|6L}>vYlZ6n2$gN-FFKHuM>kRKc6>nnka>Q>*B9K?3_c zr+*U}v7Z(Cnz4t)pQyqs5^y~kM?=N7RT&1j5utYM%AwReYq*u=QA}J+NDm}t36$R% z4Dv~msl|EaHBTbtgoii$A(+)N2q>4V#DCNhALUt#Ip$0b-w}2m6URS)y5O~Trj&S1 z;Iqm{cxXfRX6j}&us-!5pGo(HEzWA@A0sk6ht2?BOgf0O(`#IF+JQe{|Hs+*uaMQb z_+c;99iH1iJoqnZi(dQ8MhYV5c!bMhMp7QlmsEO(SFNA01VT)ory!7oIHskOl6vq!~~>(1zO# zREX+Kq66k zP%~M6&T-QZcl3>N7y5wd7fB^IcYKhDeK_=)@*fIFHz>P{cfc#MX1q2Lp2giav zM)4qDpYfUrxp=HFX9_XS5v)>Czm(uWe@_ucMZocVWuWHC!ZLe{mNX93zO<)9lJ_?)OGZo~uQ? z!tv@5E|xy2MgT!0pYY?BhIS+9`V2g!m615}(u+1vm;ZUJ!v&L3!aIB!N90b$M^hNg%gKSB##(&c{~aST^+zOMrRsi$`>b*ZynT*kV)(W zNstuOGGEkjAx1J;=H21kmzkg67YguZF#VJ{fz_{FL8V3R8+oLBgQMw&&1Fv_JUEND zC@5fG-+tti@g*6!VaPD8MJ#|$SmsOqVw{=1ya2G{bT%x!^I1Ebpe*=gc`Um};#bRBW!D-j~_dl36g=YZWeI%axc#8mTldhH292e!7qH0 z;lOMDi&MA8e0(#6aEHhDn1+FSQ223|5OVGZKm!2%MhSq7Os{|s02k^T zK+=D00pci|k60>h|CG`gXL$EAstl4LA zK$}|3{6BWdz_tLHm~iLFmLwyHRK)9K8a{3*&=88m-gRvGerk;rmYuY>O! zJgMzAiI(mM>xO}4k<_k-$H)46uNFl)9*(+y)lb_sr4(ekWXu(=Sh!dHUUWzB78wNY zP1qQ*zOCfJefp20u4+D?^q-ZxQ758QCYxN-)=C%u zO9n#yOOJ+&wo{{Ojs8h$l#K^m&?6PgiuD)j);qHfkjoCv<%?cA7m zO@*-ub;Tq3Fl+U~l|F;G`Lp zwLD}dRstk7L`ZNqPxm<0h;^)AcUMTXR4LOC^Qx;#`BQV25hCB(f8h26NLt;7DE^Rt zl?Fc>78&s>9^yh$9jl6vmGgioauupa`za2bKu2ArCqtC2xPil(X)(^z;MrsDivEJP zCsW*TIPaWkC%g_z1sP#AK>t1>VBW+^w0_<~f6-;=Ycw)qY}TZ-9JuI;@8i1gV>flI zD{ul&a-CykJz5gk(JC+j{PjO&NO~ziOVY51)2Sh=^M5xbdkfAVlOUY%quF@&DFR(9 zV^CHNL3g_pAWM=TQ+HzMbO*-7S)2OZ_y?d{n4u9+O0FMVu(?5tU!9)@suXSCf=XEt z&BaTC_%@(zKevEsCGRI{#E2oapL@D*1@b2*V1XR8fi1~_HLOsA%x|5O(gHC9YrfQraR=!0AQ#Hj9-3rFx{WdxTpq33d zRt@Hgk)m5p)7LQn8@(%gqJJqXQ~fNClGW#%IslcbvU(QJaiyQuc|WZSO{-BUKP(Ej z8cIhg0_dZWgitiKtwF z;{V!~{{PD4|E)}xN7~zwNWe3e6+bjm^A&$gaM4NtF5mV_Ai+D9)u-;jeDxc-Y0>I; zYM1TRVEVPfXaG|bc@~7FKz7ZOwNA^(ldBt(DeRxEAo8)Ofj066(_lUFW*bHud5xKe z54lET&2wknRLhH%U5jT5+s+S(76rEEMvJM|xzR>zVXycLGS9~wN2({u7{mVY2|{Jp zV5Y7g+n7|IIu+<Q)D}V3BafvZjwxoOLT}$Cee%j8x!;?akxi>jT>+)!!IkXekhQ4#xfI0#!2OR|KwpDh%S`=7G6GwL=fBJXmg&>} z@qd{GU572BsZ5(HJUE6b@t(!NWPcUd@% zG{in0=2clg1EpLOsEQD3F&5wMCVUUYKkw2@QHo9^d4-mwy4BVg&k|SOI`8r?hc8Bp z|7l!!FIrUPq<*ptIwR?6Jod>Qn7U)p6+U#CkLC7%XO?dA zD&_|FN53VU=LmW8QYMMe^Y+h;D$DyEe)~2lZKn-YI9KF%<5YE4*%I*#rEl|UmeOS} zYc0`qrgo*OP1Gtjv};WUYpf^2OhP_ZJf(a8?TFl-KKv8pelZ?-r}|2=5No}YKOv}`>Xxsnl+F} zo!Y;%HgaDdIMl8Vdw6~@2HWVo`PRpkZsoH#Xw9*-lq*MO?>`#_Q z^m8F7$cN-i2pTEoiaR=(+`t{1ub1BcAFzWS$pvVGZZPRrgKo6QX@mX^w$paDEBYpJ zP6+dw8iW7J^Zx;x6MRkc{p~+s1LoC?g19X)jH3Sm+mHE!ma)>Ce}fI!2$5{tCJy<4 z4K;ZJTg@@dj9FtJrH!m8{> zvXx?$5cO{7ux~vYUs%`c9qtx4gfa} z*T)6RipT$T?cbJ3aFVDh9Omju;0EGxs53@l^C4Ey{A*i`-f;9n&p<`@j7}TAg3v(; zayueIN6;ds!7%UQd3uzf1d;p7Z#EbA8e;Sx4vsW{)EWm7!Mc5iO71OaP$b3tzjWSU zq>wY|li_c2oUV(1aUEi9{f_~-L3|$mbd<%JenbAg>WS+%RAc^+TPsr2FXZ2!M-XaGyWGp{_dUgD;&1I03aqkt~8!kMM;tv z8=6>iteGF^vn=$#kS+x1puGSX{y#{=jq?_v0mM8{mV;`pOaL{f&!85e zaZfC+LMlmUb#{N^E1eD!a-y8U6nevX>pmi*_bH;@-#3b@H~XT+6&|Iuf3AOsl#8rp zo^#q(3)3hEWsqy^jeXP2_i?sRE1OODl)vkQ$yYvCPPN!ZL*;U)p6YPWT~_M)QmIDk z;q+o5=>YM|d!0=bhkRW>HfDs4v}v}YBM)r$=;YO~BcA~uYfIW~?UV^ZT=bT6El zN`IBS_*sZ=uDh~WyPK-UZn>(>muk8^;jM8r8J^Iyh;f&_b$&IrX!6#ki@n*eyTp~= zo|i$l9pT8WM_u^!*7O~K6;Is$4gK%`Q0j`(PsS(@`ZuKrh5$OQ**IS=Y`~W% zN_q6d=sm6oqh1}(GWkH~1@a&_B3gMEFKFd*!z4`K=0H_U`*MRwrW@9zG%dG(!Hhe& zzr^XkApxg6O&Wva^gcF@rqaT=3o@MBilaquS&PB(O4tTlaA#8Nz#z3}tg0~Z+oyg5 zOif9f>OhNW{yoO@$*VW(7Tn4QTBKTlj_$Wv-Qd{RlDVbt`b%>8?2sur-!Q*5vf;8w zd016&pIZWppOTde-HUTZ*(+ix7ubK40)_up)~(H#V)w8qlvg7*Wei}Gv^bLW94rk* zIZ1pe4F4m)@Cxi&twv6`U>(l?QYz(E+rr5GFG{n{Qk!)_2h{}6;-$FL|6>u57k-Hf zrjL`cju({Q4{9it{fyzdNlmT%4b8!Ir$dl{Vb%LTHhqm*fcS7BK`ijkzf8eXIx4<@ znSypLa537Meq#tj&p$T3-R%28K>_g^KTd`6N`N~w@^$y>)7jemC;^^J>IWv+y7#{w z0;pCvfmLw$*s5P*(!%+ZMc~K{IkF4EC-fplG4wMG&tQOjKf5syy3**VCm>+Nt)IOP zDtx^`-~2C|zH_l35{OkKc1exvHn9`r1K-c;p;<1&3HTE!2%JA_uJq3p(vMlCiFV`H z(vPnX_?;`X>bCga+_t}=uu#=wzFCBKpz&2xk=PmMthdV_nIV<`=Cc40i3SE}{7>Qi ze~5Y$f2jWO?|)Xt*v{Aq*^PbI$kH(Ob;gz~8M~xHDqA&}8Dnf?O)8CjtRae0jeRXk zDoGlWrBq0zK9!&E@4g@R_xuU(bFTBa-p|){yq#m z{7O^8cEw0Ozf;)&tw4S}P2NvEMN+?VBGnKz)N|cq&7sKr@?%&-`|4zlrSeOqsPi>X zYvi(|-q!1#a$qUdXb*mzQg>?6?sSEldTjbM@ID$+;=Q}^`fkucecpJvxlrZ$W)a?a z@s4%w#qDKJ6Q7pprmMXB-;*V_ydJ~|e{@;j)_B{VXE2%b(5HT_?zD-A*hkOE;OV1I zekz&|h#Ng=qE06t{x)12Epzdh&0zeTEl!mA_*^w+@7TMXz$4PGJ(zPV$=3|dxh`}C zZuEcqH9mZ~_Tw1;0i_pjy_IYMetNK;MbkO_czJK$?b4s(;FOdfTpu5P%`+L!l=Kn_ zG~1TgJ)r6fN8Y(W`1b^?WlPh`%|D+yBApHyh?q>>_vC<0*9V6Ku5NT1GED$4d@o$+ z%W?V4Bd2J=8R}(3*Q*M?KFf9jJGH?%LMnU96!d6mWrpm$#4^JaNpmw3{P!MQ;87OC zWGD)C6Y|`XI3KR*c9be+`&o=GU5iWtR1!m?PTjuVlXxoaW?aibX|Cq~QYq?rx>3h{ zwJ(O5b;7tFxTd0XzynkeNBwV5+qu_{WqTi#X0ZMSP+6j1)^Cc58UreIm3*VBYSp9q zixspJ)~jp!_DNP%ZO@SX%_=FsBa@Sa29%Na$L7(k_vd{ZTF5`<<(k?T8?0IfES#EJ zKK%NretX~SkS5=JJ1OtjJ<+=NR{sAF+OId@ojiEE)z$8O>igf@vfhFQ=n3S15MFv+ z=VRBh{s#xLw={}(ZR+W z+H)-bZ+)Iu9bT4S5AT~>OnG{2uP5!K%>UGCRv0 zFV%^pWPZc9Sc3%->uP@f=>WUm?d}`ckX)0uA_t{;DkFBG_vBUb<{Q(g>OZ+A8-NRJ z(R%Ki;JdRrS#Cvp_J!@{u#4%F$BGfDmr}D$9XPRXiB&t9n?S&U_AUL>buvfCkHaa7 zka%ZWf{S?e(c;>#P_v(-vTlQ`JrR>ebL$H~SwFvjNjmz9?|sUVublILYPT=*D;rDM z>0JI~WARIAd?v*HZ}Qh15#WDWJ?P-c2PeV*@0`hj=6wL_W?m;>`X5jSC_3IeVD*Dp z5(ZHVBW+c~d2%>g=M4UL52F-38vIAwYsRnXhKwzgYQHt5E`)zv7`i4@F&sp+AAwRvDgueQa@gLF;4uz-nhkshUJSY3`^frtki-|4`SsW?6+xaTz z&6$~;VyD}#V(&V8-c~#Cmfv{r^Q-4J|Nh;?7=yiU>&f&r+ud8MX)mZ1QtPGHK_@o8 zefo+1xA8Ecvs85|7E*Nau)(*_b(}Qe7bVYdT*ih@$`G%#g9atMRNi7Q=J~v>2qbL; zOUq_0Wv(rSOkR*L#stfvht>nkezl^pN5q#d;bm2jpsH-_ml9Wth3I0TY;&&q(CDw6 z=l;0PNV2_blHBqLEf>?iQc_;?zB+@%gK;iuMBrMJ~GN7pCv!F5^oJ2IPV4- z0MSaahP>*P&btk=cZ5!Bc@JGI^mBo~5UL>o0rOFfuSzstn&N^C(0BXzk50=#7*10P zvqBwN=!d0^I__8FglpQRH)1nnAB%M$%F9-6w1UQHcfa-D;=JM%!777{7q= zE8CYN-zfj7v z9dxM`MaACIi5otQN&Y=3W<4&kH)>!OwCC`eA@a`@)BRXkVCMtzL@!PXw zlL8L8HNWv%BhsE7xab6zskdB4T3Cr_JWgUpl`;9N<+9p;d2Mq9y)^t+(RNxvE>el~ zpUH|KOk`y1qYB9e z4AhSnIq=GY!v5@5h7FUS(w6jY45T8R9v>nq+{8E?jj=M?l24S(eudTDd!l(%DbZD! zw2!Gfs?@%5CStVMU%68Ifj$bG8%MM zuizqo(>pY?vySgKAx}!lUKSoqP1{-$Oew7f=_8yqthB{Xn<8|6ggeTqP5D41hcsBj zw&`<7(Yrnrbf_`PrD#X)(%j0^qbw?p^!3ICr&aBP-BpQ-0-29e2+iftYOp-+^nE|+ zp4yoGaaziGg@oN238RrG?UX(_TWKah@WU(0JOX3Wd}g!O=!-o0 z`s*`v=*9=Efa9$0MZ8?*)_b+zoDR!9Pf!I0W*XLT1K#HWY6ZAdwO{2&c?HQyf3`Zt z8|;}=B%jyd!NRe|oGhXnDj>kHoNEQ&B~XZ@f6l?4ennqDk6iiBSo^;Z)JUC3(rs?b zbkG>+byg_h!sUcUF}c3}Qn3}0Zjh`NBugsHMx<<~XHLpMfgYI{d-t0HO$>v4L)&+@ z8dIDM}k{O&Yv%F0Ck(v+^s%y`+6bj}`+s|OzpSQX9 zG28{S885OJ7x=Q&QO8eP0o*`Q%&pDG6%`1cc{!r6l7y5MRGJnVJuW>(JlLbW-s?LT zCM}X=ZJuXStof!M+o}o@5{6j{plp<_+lEsmI!{@DhI+kT$hT$&0g--cCl!V07$2W@ zq!?QVI~{JvOA;^svFjBY)X?8sXuesg;^@B$AUD3sIp156p8{>rVMkD-B3OkuXNEQG zp?n91e7VpCIBMs;5F0sPT^t~Ka=mF%N+s7O*BNCPo&1uk?Skzyb$}T8YkJ|wcWbsh z@N4x2z2{y-J~dH+43F+N`w2xBRaD($cFM8iqh7G zhYel1C2*Z`A%_sf{BihH^72dA>%Q>xTSszLl>?h)>_?VN1fz8cpcc+gONONZ*pP8t z|2bq3-U_#V@@>z^euP4h+>CJ7U|IU7Hq+mA7!~|}S98*4&ff!y_vO`&0*SvdTfA0^|?~rk)qrssvtKeSBf$yDgrh1J*6JFHDgQ1@}+7=mN|Oi1^kEABZRy?Ah2De5*Jr zlbz1r=9Ju@1Yrgr^)|lnlWKwn^%|Y?DHY1zFVsz+Rg2XZ*_D?jmZ;~)sGz51?%)IX z<@pPAky8B^imxG3THRgbE)V?x;AqFqBHpSOm(LEllax_ZHXMkJb!kn-T#JY$WmV77 zH1v|Wmdx83$q-Av7)8)1@q!-9XglA>(1(XWM!aS_h7l8IGQ6lHS~Ck}>tmdJK2}8a zcn3!pc$L$GrZ795Aa+1KDE1QqCB2){w})E1%Ug%PaJ7!-L#uBeF#*zReUljMG7Gfp zhMRZ*zV}mI*DfC{w1fA|1z z)&YV91$hDKuUo*am*x}(EEAECR$hM+t#Ig?!}V0p4I!Ry?y{GV`5=dH9HcfH5XW7G zRWPp37UyE+NBX(_wqR#B3gOcwe!ADxUobGIQJ;gw*!A_xaA9)u9Pm|F!8yxoeLmqfWRsv(SPZ!@8y@>P(1 z5I21u7FJRkL9YrX8-sqkM>O!1JqQv+@o>lMjRMM#B1+tqA{oNQCqq2#*kquBmC39_ zS@PCy@jd|YaR3&KfJpYq5&`olj=;?Z;3>aYvL?V6UErl0V1cRSuF%yHEiFx|cMbu( zJa~g?LPlinKGb2tj0{oDX1`8ZNF4~Ib9uJHf7oz4w>DTLBB`fSmQe?;C7R-*s}~ly}X+)}(G>*bs&P+J*;FCz9^$ zC9%#)q(JjK1@d)*qmDp(okQ8KCrMB{Cd+I7_H*^Dn1p(ly9k%_2t$nM2VJ!p3io3J zWQhsT&b%rz?d0Fu@WKHas16(~=R-(PzeW-Sd_%GqzN6dgLmgd zx4+!+bVuMMr?S$a8;ZJiFgx)tr1sQBuQwq;`8rmx0wLlEys9zdwuD01&~WXY`DhXMviaoN`neabnuOVxSjFcaQWKa{lP9s{ynZ#=)k8(68D=_*4<%2 z2TqsFG~u(SX~p-dngiKfkHu|-2RdMS@?1;A7>#a749wRFh-YMQ2VJZ`jd*5?qL0DC zx$nc|Z+Eb}??tf<5BZ`???@JM=iR|QkL=GLuiCbe?x^xeEI)CKSR$S{50fCXUwWAaQ4 zcccSw6zT~{g_?p6-X27o{mgt1$ZAAg)&v=XpbE(Y{B1ChDR4nLFuP&o&=Fxn=H#w% zTD-ob6V{qS=f`3CV^EVb@%fT)x5wRRK-HVqvkov#_=oTrNO25%Eji zf7upJQwNQM1T3*YEVHg_6Bxc(nG}UMiG^oNCF>{`LoXmoel5W z6@9D68_h&i;dwAU$xXZ3gGYh%0N|1qDC7*};U-Y$GVd1vxcVbHVt9HS0SDrYKbGs& zrK~D`)age>ISu%I>Eu`y#}lH+JW}h~)s_f)Vq!^jgMnawt55E5(0=;O*fK`-pKQt- zV03`Hw**nK|L8f_5=4cBvSiFdd%IfB0KlaI7tX+RGW;F?$h{t+o$gn=#!ve{ANxX| zl_rrBV2HC>6qkP_GyR_{v{9#GnHF{RG0Sm+?H>-3J3R3bA4K0 zf$sO_!?#yL|DxLV-pW26w&u z@|*t%5c;NX)^LS0J*7Ah%dH{Ht0=2usB2pvxO+F{iGTqx==^T8>GN<>)HcMDD}L)G zKbWue{>0Dkp93EG`BD?bBkLQ=b-qX;k>69yM0jkjX?*?yd!Qd~YlQC52KMUAR^g|d zIdGMylR+)JvR7c;pTV+BFhmdP$K2}X8+^9--9Qe|#&WeuzykK)bt^ymevr|s4g3%d zny`Jv-Sa*C!W9bSM$liGOyEv))_)Ph{53yZ7|#QMNy*q zt9lPx(Tgs-oeH-t#WlQ>2OY3VCXg-Z5B;?qbxMKyThxCs6$673;x3+%wj`;CvgfEV z(*_}Sg7Ot4;v>aWZ1sWF(0lzr$bO6TMnVT5ofpdSPkU`&@tjgo z;1m1E>sQ?B(_6bpB5^aHrbqjpK;|Txs@HR+ zC|}K0JWGAbGzpO3ynBkrGJFf7sDKp!>ScwReiT~FEwkjRl^ytk*2xtbW;w;D4pha& zJMh%h5Yb_dY6D) z1+`4sRE0o*5yqvjEV@VVd#VNKYf~~W4)XS_IhsAz> z6(|+k_LR?H&AImhd;`&nq8hX@0bLmO4CWRL4XctZ@af}S7L!WLeI?ewuddIoM&2~h z75btC*526i0`t{(I#UdVI5ie`295nzqs?|Ts#0cS?W)8sM`0h95=M$2tt8mU>-FIy z`8+%NzP7o*(TFPbjW_z1VExhxm^iUn4(44a70aPC**{gR+cHDCunOevRlB8pM|6dx z`XRDsL>jzEA<570g%-NC*w@m#WJ3LIpjw906!rIXbMRK&5uxKzC>$uk1XU^2Z2L>m zGp{{WjZL>gTY>f+6hKrP0`ZBDGjer3xP2k-ES#dej|}!L<3r$Aonwp z4H0dq;L;RqQ9pa*9xRQn5nLQ~hT_O98Hk9e>KDS6C_y09M$}kY`J8Ty^s2 zB3&#$w5VZhD((D#a2Anks-6xN((e)@@t$Om6)`qQ{HekiVmp)`q=ewjPa7z;%A&+a z!XKZOa(0Xne!VcZpKur!V6!(JyZT{OOk8XdISs#zS( zy0*Mhe=Mk)H|-niU9fB|asbXM;u6}FA9u%XNfXc%lkB#ni1<~~co$%86faD47Tes|V zYo9eREYaRwjAKFWsp7B+$6jmnwk`VZ<_e3vvh+;8OIcLKa0xNlgwUKw&$mwr%8q_dF@X}rPcJMMA#)ga}~Od%E}c3Bl=R?&)h9)&Yaw}m-ZGCmGegk zczcc<3eq2<>^gy*T_Qby79m%HtW~S#$^6#0PQP8&;yiZaB7@xgP>}NNF7n_WOK} zQ_x6@4~EEY^4;9_v|44$G+s473ynUex8sWrU5KsA=0(L$K4Haazmp1>AGhe_Vjl4@ z2%lCv!x!raBBMZZ%U;L9rKu@MH7R?=jrx5NYrz6E4XyOth2q(FIeZEtRo==F-(+@( zUQbtx+R2>TbF?DV2cR!+XBINtLyf#fke=@~2GpxNVwh@8tdYtS4jM z3`->GBY7{ukm~_f_ueg)-dSe6S?~_ceDd91X}(`}dAU)c%#S9ybr)_FZ&|Y}44R=D z>XfpAc#%ntG&WXfHN1^K+{8jjpE<_{{d*?*$-9FbH+$ zd>oj*MGWm6sSe@DrlL7}h(XC-+BwnXgOmqiMhGh%q@C%{N->Bltgp8FN2ID(@G6!+ zXtkmq74|R_Q?WlI;83)gFTqy^iPjh;jL5Cj`D-2Nncn_OOe1;7938t>jvRieKfN9# zO5o#yr{DF>ck-N696ez#DJGwFj^!jDTrw7$Q5vOOd|sVJJ1?jjg2~QiDLnQ@B*&_Q zA`*Ka*@3sL(8N>V&@H%2d5#tJ5kq3)rOK2T2vijpiS#7GO1XX#9OrJWJQADD1P!tr z9x*J3M7Tw#(|qKLWo61mRYVBsI9vLF(UFRNcZc*_CSLjbpi}Y!azAKMk+E3Jo|I5; zgQ`pCBjJW3Vs=Bf6<&8IQxXb(^QOGFP+Z}LEjvgc>?lN{hZ%Q;`sRad{ph8U<*KGA zZo_t)qIVOYiJy5$0;0KU-UCdkeUsfY$XttEc+hRFrV|>J0h-im$^eV8Ar2wo91S%n zwvpcI!~y&E+YoAq%$pUN%w288M+_ck8>DxN;@!Y6ai@7XZkKp%D2p>kx)En>ON*Q9 zHTu#^XXGX!>#*4j&*L^Jsr;^Zr5j%Xxf;<|aupw~NPo0MKWc}HohQH!TYdKudm+Q; zCT8LZY>8xkNSlU8#M_V<~c-UT@R;@jtc0$3f0l zZU^$(gehL3jvk^wVHKdN^3ni=&>n`OB8?zA!Frs++;>-eqqyro=xGWpe%$wLkK>?Mf1WoPNp9))_Eyj-s6ElWSi(Oz9GtH%uUVcGg8;z zezOGcJvsfKu{_`7(*GWYoxm!lkUi~>w3c>LT5sS%0yt*6cmtwNJ)1y!K-q&NEU{O+ z(l6n(?EuPdl@cN5K?Xu~eO?5$OY2l4e^=~i1gV2{L1xuyCUX*&)*W<^VFU9C9W?N+ z5Ck5{5uZbB%J=?6E8vP6oJiQ~U9cHw7QWy1p)hD_$`sT@<9%JA=1;TVGt2#rUfqNK zX7TlXN>iCbyCl%#JQ3jxcz6u?81{)a17U24GiJ*&(;rz@+2l!J!I8=@+H|IoraD{2 zVG=_p{Sa+!GIE+t%FlE5>(B$4J}~;;k;rWI;%^8$XEsF_7M(Is#XgqD(v&JdP6P>v zKTmUN&^-xN%O(khGpKbwFbmp|vd}|vXe~KuEv`iHYnFsiD<~UF+7qs6Ah8XvBf%3R z^j4$1?1PBhoL8-fP8ZrzKom7zqehl&U`1LnUn2#O()Xa*Po)=@Ri{p+rE)AvOXU^E z5E)oZ6F~W=E4bExFu;&|{@D1Y!Z0lJy=7b;y4kz$m}0EY&~*^%9Ct=Zb!^$cbR>Yzc}fqIe|%a)QBic4`99 zXFus5@|T-@Wj|VvNh@ASw?u(X#N2dbJu|&QHzZDWFQio`Bd;aVA1`ZVGsrdxwjfk* zS7H@328F?Bf_>@wP@*D>ng)bWaOX6z9G<``43Levki#~dCa4-bE(yS20QC!g5PQr zr78Oi3PG-yW$Iqx1FoGYoR=KvCDV`HMA}WI7qru*@Dic+mddF{0)t}sQs}}%*gmo{ z-3ramv7bHzgZpkxs8z{LZJ}_H1o7q)Ow8l{Mz|}3;w3@xBBuY8s2jzTmu9b3hq$ri z23Y_+MTDeiqW5jj?BgMLqIHY3mVyy>kca8M%6uZA=3@QO1|eipLC)3gayBrM)#ub7 zxqv;TNtj|jH&M>IqYfjdAbW+)z$AEI0=#qAt)YviYj$+hr&4A_OIe8b#1!l-C*7r2 z5b#HY`tT8A?z&r7I@So5hvvUEbOnvYn-}FRik%ay$O;e2lE2Vpx z>%kw5JD!^z(pGdiT)}+s=6O}jW8&o(ozZ-Rgr{p|e0|Au`|mWPe(n8iPO2)$O*U>+ z(2o|5c}kCTiHlPza&Rp5f%H1j9EsU+1=O2OT=AAS*XF<}PhXi|7cQT-y`Jh(7~eG0 zWJ}Q{Kk!5F^h;RCNlR$uRbRe&!rpSfv`vvIgF-s8Tn_SNDBYb^BYZt zb^C57lAK!B3(K`Dg)WZV8PXCM-WeP6^3P6yas7QA5kwICn>(}hyvp8^)8IN$48=n%_zK-PcxLZJ$8`JN-${?cqIW#jiX?p@|1Kmkj3$bpNDV_>gBPbcGT+Z&5{icKr>(dw=B{U+$fc_-fK!IT-tgqx`EcP8`9(g@hsWT# zdSp8^xz&?~B>1=Z-+z^e+#gqN(-S5U5|*p5Fo^B#hAGG`49tp6(?19z2CpqlL{iv( z;*!+KZ*S}D*UCIOQ_V1W38+zmpg2afp49e%_2CMYCx8jhSkOB<*p#ORJ1XIFG{EBy zY}HPelGir06w+EJp|pvj99o9;=?dBq=LvG0n19|4b1jd9XMZTe`lg$k*YgnGh_goh zDkECXFAE8XuxyN3Y0OQ-#+w8t_=)|K+SjT27RcCa`t8-56WD0xy%8!`xG&HA9qCnn z-KgsIN7}fc58!a~nsg$CK>yKm@dU+w&yNyGg)Gv|vI4A%lsG;E!&c+!-8@2ZwMHK5ba4kFwaw1tH$i>SeT{fLy7v;9A4 zdAI2Li)+0COes=o%|^uP0Adp_#${u%6Te>PN+15=xZMT6#$_r!b##6; zM{R%OB(qoeq%MD|)E0-!_%HXE@Gc7-79H8f63xHK}iVqB-wp) zcyig)%pme8MGo?ib^G@=^jH^yCR1cFf;410pV<+y*vonhpDJv>tK9`PkAdC4M?W$5 z_D8gy@%o6~Vhq@AvA&6hG_}30{k|Mi>|r8d@a}A23co#*!mE~Zr{~-JcD|L**H*K2 zN&?vl8%|-SwH8!hx}dQw!4%?rozF&t<_^1guMBLcPG#ZNs9j9}EB4cd2C zbc;c|l`0+d-APVaGKF8_=LwGexzdsM5vZOY<%!u{i0ENN;!O%jd-?A_|56{DY})7WNUkRS zqhKsF;kH6-v`m9p!MZQmCE&Z`(;oBQ^vNuk9Y(>334WLPMGpPG!;4W~TBC?b12D%w zY;C>R{vLSg2T*^fcoZ%udd~cNl~mq(=XSA^^|P$9A3s}Ob{4_kJ&s8q5!lZc;LsVg z!wvM3;ZN9ORN>@bEKX{N&9{#4zed^Oe=uu27N1sIc}bh6UM>oyiEpviwkXFDq>kS! zXUcepARhG9=}XFCuPDmZ(BFry&z9*2s=+8Hub)vm=ey@f{$iOocNfl$&`#O2E>Oni zqY1@IJdtxiG05|ww0ksbXz8#~in{lL`?iCf3*=(W(#Q&8nC_Ch6)B-qLz03dj8rGY zD%vv4V#i0}q8k21xXBOuu~791 zmO<>Jz{>|3ozPLub}Y zhJ5=qZAyD%C(kvlSeSGa`m~6170oIieZ#0aLnRl}L6gc_=)DdyEv|q|@jtp(W~Uyz zZA}Rtv?EYvOhjOUmVYj~+vo#F7QM}wv!47~pH*;} zKk*1S%R#-n+WP^fh!;)q->JCFoKpqqhFrFv7D$(|6cOJSkg1*1M0hDNNf4SlT`Je8 znkS7r&Uiju?a@#nNC!Cu6U6Wh<{ySIQQTg4jXW#QrXsN;an@;i|m8j0I8O6-a7gPF>6|3=+$7^A9e@Lla ze!0kBrO^;w6K_d%=$A^O&9RMX$tW?SP%6mpCiQcLi*9cfsE)rAE=B%h)evh>C_+eW zqbj9|_rR|kyj{C}aM__Jk|?0#F}-jp|CF+&a<%O#A>kJ$p0^mL2ooGae#%sD@O`Qx zsVLOHzzG)vg4f{KzP}pr$Bc`D&=C7H51W1HQP0kfzw} znO}sKVd-hKCsXEGhjkvK{ehaD($N7*woVT||B1AvUUU~O@eTPlrc{$XhkQtk1lKNwL`dxsPe_T=fvpGm^6NRarA7WF&$Osa>( zqVb>bk^%m#^LXbjcE2Nk>^2%7ov|e}t14*Tk#p>c7F!5WR}{l<-ul-HLET~B0R@Q_ z1WC8xdKbiIew`pVS^26~4MeAZKe~Ia@NTx6yVVRsweVd7=H8PJ~&=RMYVKpT$UXd`cKniYT$MVHM z>|ZPY5h@bj4gxF>&NyKhZf+hV)+xbz$jl>OUupV6Fv?w+R><`oujIT}(8~p5-=pr5 zPT^@dcF_=u*BEw8VA|!%h!9y)+C}3y5%OexO8!{(vs6+A0=4>raZUz_5s2+|?|6TU zs>=Z>n1v=-Y-ie~9E^1V>}J^tUQ+}}U|YUlu^NxaP0UkRe&fVH-gncUK)!T*tB(j% zEVAjDL=|{kcexmszyG!i#1&E~;h`RvIqlM{aQqGXMb|n|TO)vW{4W>}DHUqW98}Aa zdbMTo;-MSr1OBQM{hvFxy>(pS$-FJN(ugj1C#D)jK}-EuWtczV33Fm9o$#4rj8XBu zya$62;#2jGxk?&(qWNT3Yei5A57RI}Vq7>usX9$L%qC_IVo^8rB>FYgTD?y}EKoO1 zsD}vEmmu=oi>#-|tD~j0dZQi3L^XClh2nzJV7zNs)Q4D=!T3`AaX zk!HCQns@h!h-V^L-SjxP#+F7h)}c|R?)gEwSTC21vZ6>S5n4GXr#YKi1_SUY+)hVZ z5O{c~1k9~(R-nyj4f3;)*T@J}Lsu|uBHk*1d{-1igTbYs_MHM{d@7$OZQWZgq4vAO zvT6d6f%{m^m9zQ7YLC}Z;K~3@VlPvDaptg1_4Q`zZeC!_Eb6Pf6(#WtmCu{CDLUd% z!nbVKeKpD#e>75QxZs**sZs@Qqyp)&5-dsCBjY&0Guw%!q|JEyl(WhfBGeKE=SPa- z?K2GJtz16;EpheE(*>-WfiV8e0fpcn+*~G+iXi~$T<1>n8iHhp0Ue@I`_c{N?#l1u z_avW}FqYjPd*2HSsuyp;yOmbw^Xh(QTx_WK`O3e!}k8Q z^olgP$#O8_r7KtLnHVzvfjQh`E>+2wdd{T>HgTpfemrZ63C9;)>ZPWMRP3i8M$3rk z4D|Mq%XWtwQS|EQUT?!m|a&@+)`+8ceg zC9nO$r4BdWyq5XO;(hM{UT!gL*nh=iCxx9r^_t$=>F)9t_O43bZb%<~0Q%faLtKqy z7lNp@pKbmw1zdao!$4G2%{`ELz=Id3D zTM8X91%+#jk3}mVIUHga2DZiXaE>8%Ep}v(qX5#(x~SpFPE^y=e&3z!Ka>nx7Ak;5 z)F9Y+h-;?vt|u2Eo+^0N{ulNznF~o+xv$m>?!Cu^%haU;uTOe@*jIyGVy^qIr~gP~ z!+?0S$RpskBaRwPOrp=p9qT`&@ql|=)S@6qK?Ljm;{0TO*jBm117;^E&MVZurzT$@ z_0HATJbW=LmA}x=2V$>&K*oTN?!V<7r8*i}drR{R^tsyj=YqCisIhl;ny;cTWJ9g}lkaOR4;R6t7+H4A)Wchr z%urc;&-j(8R8aZJX|F}5AsO{&@?{F0Ey0m=6i#^U=ka+YGa4!QhY5ccgooYChriQb zhxGSSv`J|)#?~bgUL_!Cvh_`nuBc23?M#t~=-k_d*IZs0@gEKWf}3)7t^7Hg#2PkP zD$-IirSiRe5Pl1G4Kai`Tu$JS1(+bcOu>!M&V!W|BKWGhvyy2qW@k z5)@r(g>kp$iL%-Kdo8-nyR6r`F2yq{pb{UwKaC(Uq@RU&cph5ygh`q8uDs5(iyR+y zUOa|$#BXv}5C*QShz>DITN$z%QpD*G3LDe6dyL+GGGd-U*$^MSIZzY(NYaKSN;bqQ z6C;>Xf?z=aL}>!-w_?-MLn)56F7fB%9b<4iyz=g`c90q5i=K9srHJVX+nHF$A(W4o zBJ5a!Hl?X*NY>#~aDiDi zw>{~2X|==2JT<(~g6DwrT&k=U1Vaw6!Hgb`8yK7e1}`Ii`vePNI3yF;?-*+f2s~%O z6^F;hDGi7AiN4uo^Lf%=NQXsT*yq6$ohX=-UUAkU?l6%`OA3r54(CLD;oh+E*fN|F zO9>5XTY@B&o$!Xm@!0r})i`jimQ-BhvTz7oT~eKr;%pwr8{WjVa+*5`HVN-^|1y+~ z2YAt8Ha_8a{Ay@i9j=u?h+6a3T#R%bfj#n9;W2FSFW&SY z;{+oDpN)lUd$_07`LGvOyqxZNh9!mDe+tcFuiJga<4fm8X61y5CNj|6>531Tj?q#M zVl01!KwNYti2N3T+y^Od95TBtbCBS( z+D53o)Cc1!jWi2D2)7S;(wG0;oaiZDs_MvP!vw{pZ)N@+FP|e2=IWrCNF&J-nw}*; ziN)}hlR%gD5y*wcFu(O69I3xSD?QMCpr%p=2@dobVN2x?3W4%7j#^(Vp~Ndh`81IZ zFnTG3l4E2o*`zYjYkivLbv{zc9&^i%>hMW)Fq40<4(4t6I`XUGu#wE^0|D11ydPxxpNICw5-LzK@lDnQlw4;~nC5{#*j zD6wfQ+lM#C*$C~j7wc7QE5q;k-?*1ZW{NrIngnE*E!Eu&KU+?Cv_Xw~bgIK5+6H)? z&jY{js(zo|KNuc`Nx@-4hs>xZSY`zK7wH;efY`qifQv>UxH&flF!%Glk zsl3<-YHg}pkvNUmjQhTM%KD@c!J3O-@XBtK4PUc2R%76qyh#8gCFqnRUL8Y**8M)7 z{{ixCd+bXaw?EMvV4jZRDIJBtAGU7>IYu-Vfp{X}Ib^k*xu&NAy#n)^;)ICY&zYX; zO?9J-sNc~~p52JYayzdy_)ykq#?6f2roaa{9Q#_K3i`zrXdOM>)KfFUi;Ri!vko^^t{_Ihz$uke9}1(8BR7PpP$#*<-ZF=+B-O>(k z_~;O}))P1VXr_gaeHO>o{*PJ*>NH-`JT*i;_E|Kq`!m-u|Ur3bH@9MC{^7T zgDwZQ&UP`UF`?=vK3dNHUyDr+J9~}@kHPz_`B{M zmtRGu*IJ)g*8KS*i`zVWw{)wa&pLQ{)3s99y-WumKeo4IH>IA#zn|TV{3=sS=q0%t zZBUOplVCuc{Eg5NZ|jAGPxb=YlA1QhmKeqLMcdY zN^qYSZb0K#u<9E|gkwEf*l1X6oqEsEk}A>2J~}+gqI%%5{)=(TtNZO=^fsi)5M9hE zxZ8=#Y6Ut<(lrloM*1zLWT=VmSrOq~>6A2CV@Q9e_}UlbJ#V$-Ea(m4ud~qq)=z2dh_6$_fV|UHndXozolT*r)n6uRv@;fk8YK)LW^+ri@0q@ zUK((}=IuD+NDNkccX}gkz&17F;K&>^LYaN-i|tF8yGzq}l{ikk>y6OwhG}XkX)+VN z%Jyoy>r1MJyZX*~+Pj9v-k%Ds(zKn8zv}H;Xw2xR^w$UN8}0TD7P0LTTc`Go$l_%6 zxA`{p?lM2mQfvo5A;^Y*xNHu|^k!KvI=$DC?e6%L4T_sHJU4tkaIM@#eL?XHEPZXga`9I}z zz6+{8m3(Q(y;9KOnx0>V-J#5DCby|kU54+D4set3G0?Tp6RDU{aa~pa5FNFkz?Xfg zsfDseL%$7%yqmQd={kJ=vVHJVL7GLNtb}oRic)35@Y~dY^BdA%&Gj>r@^tN56ZEwd zo>ex^Ydb_e+4@)}>MWiuEc3=sA%^rk2=Bln-$yZ0-`_odq)+i?+2NxnVk7Q-_@P|m zY8;l1Gis5-q@=~-eziDfCS+YwP*LzX|Nj9~K&-z+^_ABP#4dOM5r+O?7^`Vq{`Xt6 z&3~V@?4A^i`5r!q+ix3`)8=JCd{9Mi3_kt%p<6bS(MSNJ$g zyujNEW%$BXWm3e{^?9@gRb4tbpo4-35?pfj<>gxLgfBIOL$LA^bU0KwqAN7x=7KK3 z$A`0!R~KNvgvk}8rRXjR(slF?LhJ1%Q_gyC$_kkH?m23g|M}4zC7n~m37fEZ#5R5TJ;GR2!MXFOoW8z?T!mMRdK&W_$!Gv4A zD@DZXSU?aRjC@$I_o}A2SGcp=12<##UHqo(&T}WN*Zki75XuIVM!|NAvyI>Xd`U`y z9oT`vEng!zIA1P3I9zVkI{ha!!W3Hrl~?(b{@$`L|26NK0%^^Ml`K-%msumq3%ZUq zTOUOUq_|B#in52+PC*h$z$gT951x?z2E~UBuI&K zSG6t_H>FB=Uxvdckb^ZOr!_+TswH)^XMWWdd0|f(uUN@seY^NWkR_h%*kk5BTBc%A z00N{+SlE-@aRtnpb)3uoSj1yCqws6QSKnM^xkl?@>1rZipk&xg*0V7^8lsJ)M zMT-|PX4JTmV?ry1KGC8j4jeFXCrK^~w@eqgaNxkLWT^|%r)4Nf<^+e*T{vCK=GgqC z>ya){mp~QrawSRABteo0I4GlHkBbN}Qn^CK|I5Y^11U)8h;T)TuL3EM5J2IB*s)Xu zToJHjpj-hmh6o(7*8;=614lRd(OFt1Sr8bu+S1fECd)J zhykpgV~C3@>>`LbhF%a%BL>*&P{xTq|5)of#JFNnfEPE(DVL#i$we1&M8gs$m`-|WOK^Po1hoO@Xao$&beW8^Ipm|I5Gj(7Vulzt===v@pI{hM&yoU;ch@c$Z$`P>^1xjKDht6^|$xlHI z^)MFQ149ZhK!Kx4)J$TDH2czQ$rsEfgRGG<3+$}3)ySD6C@Br`LJB%dC~E`?z8c{< z3iO;v0t7x3NC5*7P@qtX=z?pY7jKKGECE)yv7@h$3#?eZJWX#2?+l6|$gjkbzySsv zNLSQ*@y(YYAlgd`sZTC}#63vh{~L2MnOO1(90b83#}@=80|T|yYWidjU3`UP4k>7n zLW*!duwc0flw-?Mix7DBM1iU$$N&Mb>hMK@s8~X{xekT#TfN3QS)k~WT}V3g6ivuy zeUVN&=@nv-qP>AZ`lOI$X1b5+pMC;|>Rjgl!|Sev^%b(QYpU2+Q^5cth8Re&zySxW z4O9XND7ZF73Q~?4p+R9jk%2<(%($QUAq6-apd00RyXh=D<`b&Ez4 zQ|5c1YbSb2dBK0Y>u2%6{}sSI#7bBk)Y+`Ujq>feKQe|PfB-@YAifsZS2j&CACAn@ zq^wpp8!?3@Fd_q^Ov;8@rYKs(B*Xvl)y6gpxUC`#pq2uv6|+GhzyQC~NDl-zm4ui@ zAZ_U$M_$02p63-pv{aaK0$#@nrLAZ zmN3XQ1oN5|!1sa}jKG2#>74+KH?53BMJfWR&_IMH5VaibFo!c7q&%2KEp{(lmLmfg z$N-640D~6bV9X^N(;8Z^q%xB^Q~FQ?im{pE5+U(iF4X86ku=CPrtn|a;9!LS#$YTj zLt@{EHyvg%WI|Vz{|blBvcdFB2y#hE+!isJNr4POb98XhC#EE@Cq>B)jj%)cCc~yr zNa2)Uqlpye5X1YpW*I76hDdU;$D}|4jBo&h6$A+c!!!^p#zRrG5<($_kYEJUJ5mp{ zm!$D%lA4(W!VtjdKRA$~5M;1J!Qk^p_xO(t0K1wgY*Mz6K;jY0xMK-vkqc1dG8d_! z1sV-OFgTpj3gbJE5))z}f;dM8&7z<{BtS*=%%GB%lw>s_x;-gqt`Gqe*caUcpGySH ze~^G>sV*izblz|%D511u%ZGixmC>kEuvS zQr=@Kex2ucdRxm^s;42jR*xVQa9mLFnpf^!&I(Pr<`wAR9z$&O6Zy>N7k%jkICu;Q zkeG=JX%Z58sxXCOP2m{5ipNmMvk-Kc!+Xdu5Gkm~Ed`+~Lhh+BUW{`v{ zc!3Uym}e+n^9V=;Hn38FgRsJv&x(bl5c3?PSa*@!6rLg!z&HgkLXilso+4G`1cTC= zbuT7DGn%aRu3oP|2HMSb2~`}r=S@N!xR8iANH-CWz^x(ZFxdZH z0SLmfT#1)~8aj}$gvbTPf0g^(Q=B3d`*rRmkQ!LfCJmYRk`O`86&=7xn8;b&rYF4+ zhdA)z6nuz-fSHR&1UpGsaANF;K z&IlPP=@psIS-e6h4j}+K#9<)0D9B)So2iNVQvfqP?^6W=3IQZSAby_6C75f7fo${= zb>4`$9%^Y#-wPOz7>K7MA&^M;`4KNIgro&PhRelC0C66OzyyNog7AVMqus@(J0j#u z|Kgh0NgKo<5F%iKRJzgw5tgu+*lK~ybRd}%h!-TS6okmSv%~K7M4TfuXI`7z_i9E# z;y~+yFjcfpNrEs7g6>+!MYLUs6XudV5JSki+r~K;bpFz9eTRzH-%tiYx{{Et419cE zaCL~5NtWn!=q@u*_r3}86%K71;uT-dzXfvZNGLiEo{lb3e;Zl>IOTE%5y*}(%)9Ku^7K>HUg+@UULwLA!jh7oeZDil5Cajp(@78Ya}(P5o7DdK z+b&8-6yy=_VfVPlx3-L^o8suVf5ih1bcCo)m;gjOw(c(gjV}MVBj^fZ?50m`HsWIh zumQOZ2((Ecz<>Y=!g2;;sHo2({?7q9kj~_50-bImglUi#V(2>X1S>AQ|0wX>2nh(Z zW!cu|b_l`&P_PCqPQ2#e5xj-~;|+k;#v%0128B@Hz(7?tru2{yA!4xnhOi0iObWUJ zsh;lrqOa9%XCdm(3AM1!5X~ZfkZq`A3&oJmq#(4e3ycs?B7QJj1fVa1a17z_yAUtD zLQnx4B3wuy3*&GP^J)SG01U363hxki+J+AevEEkT15EG`88MU6kRVuXUl0cmbH@TE zzygk_5j8QQps>&?5Q=c;188s)Nl}XgvD_A}A@Xp5MzIuK(V8yM)dEO*28e)O@fNcv z1EGi(2M8B^5vcMoWNh&li7}H_KxA047?lx|+9nwlz<8E18joZl|Cr_?Sn+L)=WXUp z8o3cY9D)h2u^YwFdoluU-o^ojaU9h#JxE{?pHUmvF&@`L58Xy&20{^U(_EKobW$K711mGq^G*S&0&Xg)QXhTN6c_?2 zG%wN&p$I>rAl7d!*HR$DBrJ*XnsTneq{bAwZ_5gS(ExAJ|4sqK3~(YsM*yx;E~T;i zx{n|NOuguUb`pXgGm;>#awrV56yLBQNH5RuOz;wc4gzZ*-?AV^r!s%BNsKKOCNI|L z;N4`7WA-sjd|(!akNkBjQauF*sk09~_Hy$iLQ7{oYvmlyL6e*%NeNzIVr1ZpRARe#PVk8k4 z5kQd--B4{cE2$RKku8mqV3u+zO(8@Hq9&=&)#$`H|JZOsDHQcS;5mw>E6`0Cdyydw z5G)0NEPpZy3t|nWXi`?R0l%|HslyWC5h3j0NhqQyR}MM;^G5|RNN3P(inJi$051~) zKAMgw1Jg+lQ7!rc9nTSN7=kQQirA`CIc=0n;}BD35E~CEAzni{ar8z7AYcRn*3@)O zCBgv?pieVVBVaR650OI}k|3VZPb(r&1>m`U;p+xMsRVTlGe{!*^Z*p#^aMiKJP#qP zGg6z-0$8q6?-L=A%h4vHBt6vzC)7_JfCQF6ISazigiQcYGgWbsRoyJu60IWO(^dsA zASc37KOiF1j7>G-GJSOn4Zr~?;01ahv`{r!|G5!VjS5z!RUBX72r>s&q3T+tF$QE{ zqLh;sTn}6b(pwGjHmtx4Hnmo_g$|Yg4iX_M(X|o#NplK9^Ach_7qwm+F*Zaf1UIT8 zKw-W7^$@u!a~dpKB_bDgA@G3jV6||3Jf^{nbs}VqUnO=6O+}FM;uI<3K{wV3yGD>U z;&OCxWQEXIh9waZVpA*daJ=u`wp3*~kY#~D?^sgh5CTeVwgY`dkU|DCuTQodFDi1+ zXMeTq?uu>lvfdjBlpV1N-*a0oo0VH4o;L4FA z`1~wUIrhRKW+sD^k7Sf%XaxfZ|C$tpAx}yJvIOWPWl=bVNoF}t_=R~dT!d)k9&R>h znD<_whhxj}1mX&uZHG}02xNd!%oZW2fDX=;i1iIGj@bGLLcBhvyPP=djA}OGL@wlF zXUq1As}6SGjlq%t5CNBv>|}<)Sl?>n+$t$5l0f9_p!UXhjkzreghPu()-RYTZS7do zm|*1KO}0ocwB*7)vX(<;AP9Klk9n=HFvmxhLIPv2&@S^VhR$Z1s2!1LfgKsBWXrE0 zr>`395o6#oCx8M*QST0?Sv>iZgUYD->hb)?BJTEN%mbicS+$m+je+2U8SDzo7$b6Z zmnDn}YWIZG5G){{&zQf&g}hAX=mHiwdn}o%!1S01cQxwk}pGeF>W#&xN-+ z!W=;W&|nLmqG&F{oX`2Y_&}Pi7$Z12p6g5x{-6w);5IOVZ1Gvb^w|u!AP9P32@b`b z3qolFy2$Q84bb2S=0X4@dgShLpo|KL8`{zqfepM_aNt64teBxU+PfU#4$?rH5u!Gr zi6E#Bo=ZBfPMQz2fG!TDW`2Y=pfsFgnza;RpqoGd4rQo=wFIDoVS8GyDnSzdKn=Da zIC>z7PmXb$D5)h(6cpj1(O@^M8saKJ5juLEv*#jSxvTLCtC`viDB9|>%d91A6cj-c z9(oJ5!>zk*6e__H{}w?F%pj=WR*mi2yJTS$;93v(z)&C}MFc9ai)jPZ-pIs^{N&|0jr^zvwLl@^BS7d05F&dEtFTZscEo9!4V`uAew**bR$PT zz^7PywFY|>5J3_=8Zee4wxP?2yYQeKFTL9F0x#_IAWg)Kzf(rs! zFGiq_rJI_l`>UZjx(kB4yE~JpdlkT10J@;OnY+0?`=_D%so8tAm_Y#C8@(4nAmkfU z=X;B4!M>XtuL;7h`@6H7`xPP~ouj$HSIfO$;j6Ek!413?UIDKEKp>t#!t=_(Lroyc zpb5C3%``ls|CqtO-&-J(d&Ggt!7HI4xPU5lPsKe55db{E3xWw0TE@3%7@8XvW}(9i zqO5iNf=qlB1R%5pU^^rr#)q7PN}RgWTOhJq$eVn7Ok5VS`VPdq$}{Q7YXQqUI>osh zlZsp*?w|~k+;^CK%qPdo3nIgzLjcyC&6VaDOuQC=d<(Lh&N)aFP(c=$0T%vSAlP8b z`MiVNTmbT0t?OD|7yy0`U0+OG03tyT1R%NlS=K9 zfw~2vqlJ!M7=XV`-AF_s)ZKfqk^KEiJ=XC>6igfzBqG;!JydpK6jI&2M}Z-LJ=l-L z8jfKX|7QKmo14;aT-o)-TJN0NDaRVV4b-oFAf7-jHb6zOJv~a{(<_13-CF>%TCJae z33z(kKZVxaTM-083xb*nULe`w9WlUC6a)a>pR;r0K%T;E4||ZV{UwB?>piXOraFQ3e-vd6(~FsZe0K{V6zdwB1}OQ z>VEA9LeSA$4GLli4FB@S;w}G8=I#3xRsj#xKnn!G1`2}HNxvdEUlVrW6(GOD@xTnU z;Hj4Y17tt~4u1A6LK9Gd}_KANYzWx_RJ@pl#&=KO}qrV~=wc`Jr z!e2oV)SwL7oe7v{`!T{f31SwET=gGX3o_jNH(&&YAN>VD71Vzq23r7!Lp2r;6>i4-eZyofQQ#*G|1di)4-*+Nmf1fY5aOI9T|TC^18|3MI> z%$YQ6+PsM~r_P-pRVCb2QdGiKk<@4r$OIt*o=lrMeF`o?tWU-754k(*GjXE{cGvKWG^yT)K&{1*`vV0;ih*;IU zd;9)P(Pyb&u0N?NwM$dURjXtPh}5M@XdZbtNKgPgyY}sS911Yti8}7cBSNm3 zB0w|=b+eTK&Iu64QA8Y3Ll82s*JG4YzNd;$0{9aVED1f4!x22xAOHhXj!C9=??l82 zh6R-&fQ?PoAOVzR&PnHF+Duf-Dg{;1CQLPqKtY{?4hk5S1sTfFFh>?-xnsPs;Z8Khf4(o;VA_Opt@?Uw(6uv7zs6L z9RdT~3T&`9c^NAM1_+C6vK*lYW(_aQs%*5 zvbZHQLYxMSTW-6-ep^tw*|O_yy{WnsAVL%vYXAWD{u}J90}Sjhzy_--F2VF3%rKn; zsyncV3pY%$lrc$Qz`6=o%<+_9A{6n!9giI45C|y{^28*sY+}kRzkH%&F2hVSi5iPs zbI$E;fY8k<>kPDM))jQXuRaHjv}zwLG{DVCKRuZY0t8BH(;BY}b=H4<%uvPyAFFlP zd@aq8)lG|yHd+z{dUo4h|D1N*Q#DOD&T`*xNjzdm4NR1O-dFB(e_eE;_N?vvki_6kHFJ^0j1f4~G3j4;9k6F7jq^HJ}9^ef=i zs%Je1FyMdw`@jfDz`qE--~}U?-~?r0!3J=)$#)-~$qHApa&nK+c8CXUgkg4>PvC27X|O6ByzQZAgM5e!zbgaDe}mSi~nr z(1teTp9&+0#Ve|ig${I}6Qk%v2|V!w6d)rFhbVz`|M{9#KS3E*wTBiQqj z=fn3QuYBOE-u0%}z4HZ9fPKuE9-n8m@3HTGc08o>ti}KePymMnRDdMYr^pG^kcdv) z-ucew#y3h%k=zsF5U)7G3WD$jCbXakS@}Q`fKZkXTmcD2Xv-C>l9eT-AO%aX!UqcT z0~Q!!F_)-BBIZzUK5V8l<97fjmJyl9JmM)!06{E9umo7NAq69t%@@vaoG|2KFh{^m z8m^InPaLBXr>Rb4P5_gkG$8QCCxCzGbD#X|r$7G*(0~ebpadmjx3N{dd{{re;pbLkYO)S_Zv( zt71Ky5Yj@#j-u6BpdbROgIvUTp=~Y8xXBbl2G6#hi(YMc`!X7$Gq8&Vl;z?G+>z-6 zA!O4_8W&hYkN9@C$$i;DWP99xQMbAr|JwosP&*UxaW`}6bAa8(`?%~)fMDo_+ydvd z-Sz@*p6l(Md==Li39$FRhFhC{PsiV|z4yEU?i+OXTj0LQ55Wn>8v`E9;0DW$s}YuP z-1s*l3**hS1lF+F(pbh0dpK;8q=1M=oVEO(7{yRq;EGv{v;o@}##%e@jA`8Bc~%(5 zLHq8!cwA!zz8J_f`zm~i{4^i$7|Apfzpiim4dOS!Ng`mM+PwzP%yk1kmI+Q9lpCAQ6NTm7RJ;12hy{vnNWn>$tixQ4pdEvkQ{-uc$|p#Fi6e*3#l|ImlP2Red*4^Elcfarb>Qukg-_soUXdRx+iC5O* z!`%2}J-*A4N7m%CTzO$#p30dI*5;wy`Kk{d?1i`0=b0RO!;hZqVF%dhk(_$duO98K z|JUn@9Q#_`9>}?0)$V!RdsY1&$H7n4@M&E9Q5_$~$rsh~S={_kJs-uVL1 z-^1CL)b=&peL{WT!r>p(_$6F^L7l(B>95oJ6Wo3}y}!WmpVRyUT>moNpTGGh)Bf+< ze`E50@)dwnGJx$>|A10*fasNgQL=#J)qp+nfZP>?(}VEwgSQie z?=gh4Q-tnugs_u@?XiTf(}djdgsc;V+cAZ!Q-#`bg{YH-*|CMA(}lqCg`yLNzcGfN zQ-;2AhMtp#y|IRx(}uk9hM5zGsxgO^Q-`T>hm@0tsIiBT(}$<=hmRA8rZI?%Q;3vt zh>DYlld*_~(}aW2UC(Bagqj;k{z*<0Mn8j@sj@%lN&LU z_EM7?ag&r)d-k%E?vj%k@ssTmlo&CTa5t4v zHwM&D{||hZbwO7QUMY4##|UESdO?>3E3C6zl~3t=eo1#(*>!r!dVnc>f{Ay8X?BVUc#Nrbj){1X>2{LIc$6u3mI-;7X?L1Q zd7P3qHkd%#(n!ugoQDSgI?d&sGI&dGbw>3Px#eAFp=$~l?LX?@m7eAuaa+IgAW zseRsweBdd2;<=gR>3!zOeCP?4>iL=MDSqw=eefBW@_Cx{X@2%eefXJ}`uUptseb;6 z|9t@3ngV*81nPbU%6$mhn+p1y3@U#P3Vsk;oDzDR6l#AKN`4sHoErL^9IAgFihdy4 zogzA&B%6~{&ph|k5Oe%p+3V=}Bpi=suRBC}%N`P2ep;~&NT&jUyihy9+p(80e=xdZ;g& zs4lpu9N4Hu`lvS=sWLdJAXuqQDs)qTm$tX5B-p7{dZ|B}sWv#OC|Igpda6g7|EfB; zsw~*5W%{a58mm4yt1wurZF;L$nyW&%t2EfFA~>u#Sga;^tUQ>kiu$Wx8mvaRtU%bT zlKQM?8m&q=twdO@ntH8onypT_tw`9ds`{;X8m>|}u1r|2vU;w4nyyy3u29&ny85n+ z8n0S7uT)sC!g{Ziny+5CuUOcx()zEQ8n9wGuv}QM+Iq00ny_ZLuwdA*;`*?x8nJ3P zv1C}W>Uy!Xnz3%Uv1r(_+hM20AP@Ess`j#{#!!|kTQ4p9vcxu{v>BbBO0zW^mtS|7 zHd~z^%c~(Pha<~|C9AJMORPd`heQj9Mk}yLi>ykkhfGU{POGp`%dArC|A$nIhgK`G zSWB&1D~MdnhhD3(V9TvyYlvhEh-NFYXiKhYtB7n%h;BQyaLcZ8>xguVh<3ZQcuTK( zD~Wu|h<-b@fXlCfYl(yliH5tih)b}FtBH(DiHxq<$iI%&zm`kymD~g=U ziJm*Rpv$qMYl@@`il)1_s7tb{tBR~kimt1Y^H2}yfDY%tyS?kXzYDyq`$)eFAiE56oS5B;FM=*qqA z5ewftzU}M2!@IlY3$E$Q9mc@E?~A|rdk*r8zI5Wf`U}AB%fHL(|G)Pezz0md1B|cq zyB+_Fzz;0F3JkCetQ`(4yy!p;v7ipg@C~sL3%*MY)X)j?@C}*Zy}N6@=MW3>&&JYV2tPWvZ3`yJ%>L8bV+z;sRy*kVfoxlh{jJ^B7#>bn#Q9Qo|e8I>I zy(oOf>JSUmu)~qyyYeu@jIg_XtjD`6bdJosU7QK?K*VJ1|G{AF3@>~R$&kDsJiJjn z#S2WyIeZS(;0!^W$$PxRFO11OoCW7l57gkwsk{&BkO`^m!yKFp{ICyutinBv3CLW_ zR{XnhY{PWS&A$7@=%5b$P!E4x5Be|<9_+o@%MW8C5Fwr zJnRqV3*Gww*(puYYYfCc-Nn$2$FI!A{16GOOvHKo!o_XXv;5nFoy!xv%kEnb_29$< z&AaU#yj_eAAMD;ve8or{y`-()rtQAE3*X`_|JteC4_%Gl?@Q7~ZPG{`!=D_+$Bn-Q zt>A^t;0?aj9u46L4gzvq+Td*A#e3fXEa4q~)E}PK2cEwYjIb1(9Vcw!A0EHwJK<7N z-!E?Bdx)|rQ zIOn5V=Vg26zL@8@xaX_e=WYAv!WihhIOwxm=yiMO#+c~9xaeTs=zaU>${6XyIO%9! z>4kgg&Y0=Qxan}->5cp8(irN@IO=#_|LT={>eiU*(75V=-s+wE>e?9V)Hv&iUhAcM z>)x2_*tqME-s`RV>*5&f+&Ju*UhK7d?B^SbYUhaB+?)I4O@VM^4-tL0_?)n(-^f>RxUhj&2@BWzY__*)T z-tUtB?@nIuntt#G8Swl#@YtU4qQ3A7+3*1Q@ZcWtsy^`!S@8sU@#voMvcB;W+3^VZ z@$eqPvzVjm4^BDQ_3}5%!e)lGs_Z+$R6yNva{`V>w_#ip>9AEhA ze)uk#_$0abB;WY*{`fK(`6xO0EMNKhe)%?;`7F8lG~f9G|M@x@`Y<{AJYV__fBHh1 z`ZT%vc;EUK|N2H5`#3rKfM5F_fBQGXB_K{z!TLsGt6N zzy1-?{?hXP;2;0S4-fzV{|F#h(BMIY2^B76*wEoah!G_o>^G*^zKIz%Zsgd}<42Go zMKb*NPvA(DDOGx`cyZ-Rm@#F}q?xef$(lKJZfuEh=TD$Pg{r(caOlyXJ&`VD+H`4A zr%_=lm0H#6Rgh4zZskao>sPR0wT30j&}&(=X^)OotM+VLxN&2$l^gbLUA%ca($$Og zZePHG7xEPx^>1Osfe9yGdYJKJxr-qSbv)T}S;?1oR@U4ZYi7?hIfo|Q6m;pS7JZ^- zE%kKkl%rwKuKAjFNZGe_ue80pV{YHUvzjz2TqSVh$uss=9uawS=na`iZ}^=0b%WEf zC$zr(x_0jdyN8Dk|DL>n@#mA9C!b!uaQ5NdzxN&A`+WK#OYZ02-~WFA0~ByT0{6oy zzlZQc(4ztybnrn4`#W$!vs9xns0cIEa6|jHQ}9BKI23Wj0Vf0zp$|`#h(s1!>=3&Y zRfNbz8bvfwMuK9*QMwv?jPOPrb=+|5C#(Dq$`hrW zvLGwFG_bfOwcJtwFTKPPL@~E4v&%CtOmoULt!$IRHs|E=(5O>e*z5*#(c3rFbi(h^rZyR_F``|-9IC(Uun3GJKYzcY8r^3X7+9CXh_ zf1LErOjjIr%~UU(^~+ob9CpiO-<$TyY_}VC$aIgJ_s4u^8+gWqKb!c(j29bu#FX!v z`NEvX8hXK`pPKr>taloFz_d@A`@Xy<8hpLP|C#)}%-0!xywtCm{kq(T8GgCsUzz^6 z>^B*IxbzR1|F-y#V*qqZ=RC(00;WZP7fT>o7AUa>mgRvBiy&Dhh_DLU#efGyN(RAl z!GU@3DxNayA+>fWl^!X%u@hD(aQ{C69ChWFU(+NIezOkV-=&pcJ{t zr>X0VlY=C|km#~URx)dnWFsXt*}+CCDwCfa+a+fWb5k4ZsgD&-bRNVU?HcY~#; zWI0Q|ak7q{#HGk;Nvd1+(r~|2RWOCQIAX$zm&asTGH3{ z2zR>?+qPD%T%A~NPxxDn1oyT8A}(ZTix%ZB*FVjD%yY{UUExj_xg|923b#8E>{|9+ z{h@Bhy8A-eHYL2`buE9&n;7eoWxb6ZZ%KNR+nb)3hToOQd>O0Vi@q%M9WXohn_i|MIIwxWFM}%?->^tH9|{ieULlELuxJ>s_FZsh7YX98Xn4aU?y!dq ziDInaZE86snRI2OtHm~Tj_f@41FSSm=? zhd$zgk1P9ly}F&8i=#|rAR1XANRCHILTZmCulFA}_VOL2>=YTt|HB^pv2vERoDUk? zHl8Ie6n^tIk9wd39p@l)p$&a#L?>F&i)M7A5nYdce07)(E--|Hg5-CUWt<)Up5~V7LGBDA#Qx<8`0%vcIupskT~aB-Rm|%uB{C3cw3g-GS_ z-5pXp_nNT__sz*w{&Q8ceA3;l-oFomaa-41=^Zz?0PGPD0mPf+9X2`2O)YF^eES^K zs7EKJ(TQ)wq7&3`#-PzbjaaB78DZBt&NY!*)BN;f_qXJJIL{sWo2pu6Mpy8{|>f^3=Co zbw;z=)&1B9BM6<;eNaOl^{B_}&F*S>$m1OHn5VZ9EojH<`|?zxxaMI_mb-hv1bAP* z@?o&)gFn^B_ce~s7yWp7MgpjexP3A(G5N`#{T%h+|HnMCes*>6Lmq=KH0>cie8^>9 zikmOUD+IuaVc>Q7`&WMdL;r3hGri=nzD1+Gvx_wDdpv$1J7WO9_KUsX+d6(w2d$gH zPH?q(N(N_e2HEQe4XmhhkUYv;H2C9^;+wzYLyH_J2@_~R7kohzzyX8XH5n7Y>SMn| z6SRs#z(M0ZXUIJRT(z@nJVK*}39LX@n+LF)hkjVUL31^9Fb3?41o3OM5`3(a0IDL` z!XijNp=v!Yj5KxN!Y&*tMj%5p+`=y$sx=fUquM8=lC-ZN0v3cpJH!F#gSw|8Ih}e# zKm0>L3`BjJyig>osHQmIvZDOY4EnMx>_ibaN!s5q>2FUxTc`ybXT(nly zC`>>AQG7*pTt{|vMOs9~W0a_qlS8hc!(D`d7Q{yr&_{hVfgH#~d*DN1JVt^nNP~o^ z?;AlzV@5)&hxXH{F+j9dO8lo zu*VFA0UKa}N{|K>umKowf+~9jPH0k2s0C;kwTl4Jo=eZ`d$eK$Dgj+J;Zx9|Yc>fb z3th~C3}t~Z2q_{U(;VoAe=rAWkOpYzhHfwiekg(|b+-@|x2sIGNUJD?j5sfiI|fZ3 z`a1}FR8uFw2Y>j7RZ!D9|ERWfFo$<|2arq58>~D=3rm&j(G#>H*G!8s%>g3VG%~S= z9LND1$N_t>GD^iVe6Up1!&F7n)Rf~?`SVnZ3koMF2~@p?f4~R((}y}Z)f`v_*J@Q6 zn<4^~)kAZ?pR?6LZJ$CVf`SMGUhPnQ7=~KNwQdmA91wz1wKHY4QcT^`S`Adpi`Mul zRDONR(1u7Yh+e{B{y^>zFXCzT>S|Zur)GC2WT({ zbLfULs|6vrS8I(vZA%VxAWeY9)MOjj_*2*V=~n^323z}wcW78jWruY5RU(*JBABx* zyIA8GH3Z$*lv6#A|NU4n-Oj3DgLl9OTf+xwz=o%@hj+jReE5e-m{=j0vsRrqk==}a zh)xImYEN5Cz&feJXqC26nIqf`})|O(ij6hkd{^!R1`po!zg+Q-jz|$1>V( z7=~eh2FI;C*M(iywOphC+^!`P+D%^N4JpMGT!JuKhkb{|W!}}zFTWiM<2B9Y-Co1J zhvo%a&m}!1|MOaRtKJ3!*|-2)S97e)QeTj&-0P)`>V04S-QM{{ z5A)Te);-?A>R$r}-?5F|^CXA>zA)nb+Wum{Fo*S+7{C0lby2L%>@ z-GzoEo8S*tV0?gvVW>;_JqY_j9RAuo z7=Ru|0A%pq=0yk^#$WX9p9>CKdq9937=R(JvUdOg52%HA=msGG08TLAc%Wh{{#sZV zfE<8^cNm5X0DyE@VidXHA(P>tXyEo$Od?=`R}kW_tpos|SMMFk9Oz#G$m2a`hp!ca z0VrX${{?_NsNIB+;}^?dp-^ApWn#tT1S{U-E7k`>ePyr{nfB`_}h9Ku~_KX*1h&rf%Rn-Sp2HQ$NfC0Dw z1OR|3XlSy<2NR%T1hD3@UFdkIvS99HeDG%k*ysVs1BXcH;icoB=m$x@hCf!!k@g40 z|I7n0zPWCwfVnhVa}Wq^E?a1rX^{p1L{`ikr~rB;h%>H(>X76d)8#q_XM`|;0eC?k zR=!^rfB~3-uf2y_AZoIeX#fBOv$blh27n7NfnRp!Uv6G`e$9e_>MwKYoiJ#G-~>I$ zgT1Z;A^?Ce&;xq4hi3*`w=UawsDN)BfNm(;O2~sci0nLY=P;-PdPN4YCI~-%2Zq3F z0ha2YVCjdb>D@eO!DRyg=;j1YYB`fOMjl*jzT(wnX557V1h`}--e4HUV7t}{&t?ct zw&{H~0ZxF1T9^U=AcC^RX?oR%q4w&+eQ3pWf_H{eSb%}DE@--TGtl0Q?JkIF{|4Jy zFo7e+gVzSzp@!xvLuFWqZcyG$MBrh8&;VGNs_$;A?%s*}?qIOZIFFv-uywbLLtTj2 z@5##VoUr7M0Pw@*2nBaygf{SmVDJR?h~MUIaaM~9S0xI!VP~@7Q!vR}N1vb+id}RBw(`Uv;o(byw#K zSdaD3Aaz>Tjak3-s>pR+j|yJzbxWdgV3!nIA9mLGbz^rJRZn)`8!k(`1fZu$6%bXM7G90*2Y!{&5T{qD6(XYB&jHCsb<5B zt+6H{`>uwpQH?EoNff2BC0j))Dt&xC*Ym^k2YjEO&vngj_qpai_xt^NeO`{Zbnw9$ z;mF~Zh|9gjp@%nT?IOb;Xop;iv_2adWxWx3FVgOIDBF zgTKl9qcc#-Dc--UsZqBj#vwhJ?;7vlwbsAyAN>7b-)}DJcip$G`Zrq- zpKdjjZ#CZ9YKq)y_TFl--fG>y^+;l?ZD+In^XB6hn@^fIpWfT##cy_8+U#`M>^i*J zt-9GG99aPX|Ibc;8y<~>LU!K+00M$UApSQG3Lt$5Maa?JpW1;S0WsXw~X5n7uI!a2%q;=GWu} zd>7M&u~rKs!-p4a;6nOue9}{l_%k!kr0z4u&K$1RcZ;`mdGf=-L_1WK;{g-Y<9Ha& z6Pd?is(tczUBY*HW5xFn)vZ_Md=C1kea zq=0y+G^s~#i50Qj9a8{HEm9|f3o3PW=L}c z!&*&iHPz@%wt1bYbDHHP3%Ns1mCx2ot_%}2BVV2E5xDMq>zUX+k8{UQ+6|pA1+?cs zBp-%fS1eZlqPdjJC#S-t6_|&SEWDF@u>M0#8f~`|Fy>z)5Z}m0m7{Y z^v|iri4(^XBgjErU&7zLLa+QFp1&>hs{t4fiXM9(dNw0+5-apy^9<}l^43SV=|SO- zNuqnBZ4!^AG(!?j$-SJ+(c6gle2Siu`mxB{>+0Kby^QGP6mzdf?<-yIx4!l**9Jc~ z-MnGE+H_>#@9JaGColR+Uvxd6tKXM-TJsJ;q#bez^}ia}|Bti3JM@rj_(kOZoqZV_ zZb1j*|IB_Lw-Dk`QxsNVK*^#8z_LBXxC4c~w{WD+ggutltsMM`Dv$p9(!tvVzkyua zhh@We4X-Ru^*=0sagXR-lpt9uqD~w39~L28%&G~futGj&Yo10$!KQ?|@w}z62R>a1 zvPYU~CLadAs`4B>xu8_tm@%N<+gMGlkbOswvD8gaq^lx}jH{ZtGhHlE4X>e=y18C{ zN8hCtU|h$4_*wsK5B73r;K{r4uO2yOjM?R%sP-Cu)VT77>-R8Mxp&!zma8b?F%Wg! z+bLYf?u%wy%lcejx`y}jsbc>kmR0g7o^Z-1PO4YdTrjbsY{q7v$WGS4`K*eIb2-)C zFP=R9ySe74Yi?B!pQ&|2W=X4>_`dIC{48Y?R|J&?B4AXBk95HUi_;A7K3|SS18(pWXkAB(y20y+;nPK=uiNoH^a^Fek>kY;k~2yAuLI|j56Ycz(7MiFa+I{R zmpPOG$GT-}n#Z;z(&1`~c2+RS=p^0ZwF782%*57{esp&6(`}zPwSXYo1XqgQ8*KNH z_>^SbJ83{&tH8yj&;YL_?JRsT^}u6y__>4H?Xo3;`>=tbGT{7J`hA_areF+t0f6=hXb#47{z3gTCvovpd7`_~gh?*6BhxmeZy zYkB2?;d8Q79QQzcfDMU!2gGIK=u!$XFxYCt*vZ|rYWK40U8l0W4b{XE3=@5_Xh)FTX^NYjE8m_%P%b$Sc5Y-skr@>`5CnyIC+0okkxR!I_D;1`rIr296P*aNG zxf@PCdTXqQBk4Cky$pLrO`Pl@bWYp<)Oav&IwW@I_Ve>{KTY2ks@zjou$4O^{Xz1& zNNc*L-CBmC!`1NG;fFIf5j>RD}^k%TbA(CVlbQgY4etcVj=&HJ{J;ipq>oD)$R}pgy_r2mf&ZFtqVz$f? z;BGS%*-0^y8e)udQJsQUQ_n{*tmGa^rp-qmL!6f6(|HssV?WYqW8vJBQ zi|>wDP?=E;41uM#BHX!p0ZmtB4^#aS?T}A3T|y;+SJgoEKMMOp@pBTKZI;UG13jo& z;hR~aeQ@FLC6{r6gm>_Hw%+(g4YcH)f^bPFnN{ zAq!AfjIS8<3(SdSw{pJN`zGS?W#&#JJIy}Jy3+L!getSHGa^s{AWTaMbb@@)K5Xpu zZ9h5WwB?N_KZ*osDnb%EcF?K9;u0rdMzFN2zQ93Ya^sfyjfO<~10@WkZ8_v58+)0y6?ZII>K-D(uA#n$QXA zoH-IQd01PIQ99gluAB-V*y+SEu8Efj&R83sScX0jT;FG?RL6p5Y998*#{Wn8lbDv- zAb-20=#oVJf!oWOWxV0qv#$Kf!h80}yT!&qiZ-!geTA|xpDv3!J9i`fj;39tBf635 zVPwF(SERDnNq(pAZrzjLyXn%Z}e6hVNWreG?&!rD3 z7nYjkGbI`euWLHXDt5WaFe5mbB_l_yAG^6rW6~Wd{w6R`O-=Oe`g)7 zi{B^%vJeT@&IcS)fF~+(bW%=8o+D~l0mVWhuNhOMQQZ{jrb&XII;Q0Ph@5~X0wOSV z<591xc;A!FFW?@|x2&fC-S1(Q$#;Wjet2jsWcFo};j8asUjnWENPR_L!_DzxHWWou zi0)YZmcGFqMJ>72mRQw6qmOs=R;b@sIkV{Qv?Z^;D>p}v6K{t(ByKT=B@W1~MQ{;jHHu9WD1gifmlHHb=9M{? zW7lwLr@GbFzC1P8l#{>h($}W=h2=S6vKD;DxZ2GWq@VR%E#EqHxYEI~^sSB%dNW^R z4Jsr}iNGmjTbMk8_Qnb@8?c``&-YHHIO1l1kH8SP?6-oquL%G2EN&%9<)r!L(oe#t zT6c)AWiy_!>D%Tf`m|?_IVY0FYl1;bwqyMUZS1dbm0NKzO(t2ziYUe1eG38wj0~!My8{K6Z(eo49q9FXvpE6;q{8 z6wyp=Kt=4;532PKVK-t7IF#OUld)I2m^YY~+fK3v1!vM@!9d#U&&*z@$S;lLNsiEH z$U%fJ`9%}6wFf2NA+R66CkJO_+;YJkib+19z}F$Lpg@FQMn#4Ie^k%u#a-gt(Ya}D z6Yq`nf64Ga2E_LN@RQrXYI5Ki)T2j3e7xde-V~IEBBbeH#2HnH>{(idvuVe{n6_tL z^2`|jrcn7en8pR&enpxxo=y3|FlAlbS9lZc8-H3}@0OCwnKR%4e3YjM9Vmc3y+OvX2C0k~F7} zWrAj&i_}Lhv=F9qevi{9pHKxHDsa=Q6|k}0Rgxowk8&tzrgvd72H8oc7m`{Kv0olztG6@N-z$Wv(NH#tFw-8o|wygXLRTsWI4N?vZblGhfzdqdbJDLB<(t+G)ew z)mWG?k^j*KW|As&VNU?=HvBQ@wlX4AK|SMe=g1mSaA|~glLGIu&F$gef5Jzc0^UpP z=PO@R8je0$PT2qJb$sN=@k7>m0wfommfN4%B7;5l!#z68#lyLzv^iC9jw2xF2HI5c zJuT&>53Q4YpD1^bB2KV<_!H z54|vOR{h*kT_7wK9TWmwv}GLJX%;XE%9f|yG|?%8%ilK}yneGFJA&o1d-ISt@++x2 zXD03sqoRz~BHleDnS3HiZg5xK>5kzs21eJM;~PB$g8uz(l+rgnB~T{~N9tZpjxKdE zMxdLkQp<_eh?%o@8U!kRz~*J_FlAq9NMKxZNelrkYJ|x`p#2R1^EQz`@eL^&_X(l3 z=GA=u?zKVG>;$6|dImRRMoO<4G|Fz6WVV>T(F6U$0@$H!@$i(u^SOoU*xh3msw41f zqkyt_8Z)~N#>rcLhKjTW^LxP+0&o$TFace%tX z`RsxVbGK{o{o>`I5+g*gl?c?(d5@$;m@3$E4jLaF7()PTuC?>mH4nUfjOjpmLRyKA zX-01!ml}i9Z7!MxC!!UN%l}HQtQ37o)G4Xrd+-i=ZVeSc1o4NCD;r>L`+&oH(NP8f zkFfuu0U*zZfrWH2&D&8O-931S4!R9iz(dQ|9L(*`;h>XIfzd17sMPo%AHGSOEZHgK zxVoq^yCL;&>0ea?CqDyMxascC!qZZL*#m>2r)s(CX5yT@Qyw^-3`sc6Gi#<=YTC{bN0k*&ckeIeGJ&b%i7CJPoiA zSA+0LO`!rPwI@QJ8Kt)N zRt&l#nl=RW9%~j?9tC5Fd7YXNeDuI`LvRj)X~2P=Bh?c_VzVHcO#m4Mb!~?_PM0Pt z)j@b3JwG)@VuwIa%0S!7@cu1<=wHt%f-ej^ULKaNH_HXTY`@r)d8Pa1alj6T&l7^A z;A-(-2JDl-CYa#8?S9Fjq;ifxAQ7|?98qK^z4JZ!`6$RNU@6O0y%(wHTc;CIHm_%`1DJ)zk``g3xIQAKN7AQ|bS+|9 z7wWP7knoq8E0)jUsS_~B94u9!fICfDMJQ{7CkXwmru{)wzG|%xFz%#texETdjb1wz zk^K>-0|bV&-!<(QOqVd0TU5z@a^?nj3QSwsdH?CdV=!9!@hhR1UB;lb*L%3{8~DpE zMBSv5IwV^g+~e`7``Y|sZv1}yJbeAV*U^Q!Gobb3H|6%95IVCrlRus+SUgBuY$E^{ zuD53;iFAz!c@~b+%~qe6yt(}N)0u+L&d*Wd+K{pjVEXnd0@~4isQ#ZK!c!GtLQZtkH?2)MHH35S}zR>$%qul%{%#XJh;uZh< zW<=v-cz}&&9R~%Mr=(H!|HbSH{SooN*&Y0~s`VL7<4bzheG4-gI{oRn87OfRJOiQ~ z4$mNbfztb%akmBJpD&m>fZ1O$gCkLuln)~sn5Vqoh;_tH{(R>)g8ko57-1{4;C(1> z!Fdg_)b?ihi72BTU`&4vz0n?=pBwq{@4<1Tp3-;W>+|9l<42z$`&?fO$s5H%hUX}N zP$)W#I(sc|mV5(Ey9Caz^(XCof}fN(%6TzKx-s@it48>rz&#UWQjgs=p-(E9$>2*H zn6F=pz9EiHBWlEc7#60AwSy2H8!E)?3?I5epZmIzQPC;Glysc6ND$ZZ>dtnYvr3UQ zy@A+!eBLHa**@Rm&hbxnSz4Y?nCI$_-41lzvyJ6c&51(KjI5E;7da5~Qw@TG;#dz0 zAMlv6RE4O*7%c`7jHNy+=BdL9xb?Pp@fL5?75jOlV=naw`0g1S&s6O$c17mSni~{} zwxMpJqh^)3>9kX0fDLm&Y|!Gm_OrSm=hI~9C?Um4i2|Iq ztgDLHrI54yOJ9VX6FuaaaDhej(P>gAd{AH)9$T=Taea2=maEle3oS#W&;6Ra!RoUX z5G~A#g3#+d{#+7jACo}lS1lowl5&dFAK`uUEFgb>30y3~e3J?-ddL@Kmm8Wzvoo`& znAjMWOp}WRTM)R51*H*K>nhgl^lZh0V0x!;;w)#r;0*62JB6|MZq^i<3z8Fm9M3s# z*BV8hv&yU>n?L&vdDn^GFHGKzs6qB3IW)QN)nud3B@Z1Aee2eHfs{zJ$;dGdIS$b| zG=Nk$#_*rn0oMpuVM5y&DRf=ZGi-T{jr=YpKtISGf@a+)EN!NtvFIXCG&FdCR)17n zp*F{GnO|$qr$zqn!AQX;PK}EKr6m8b8g{1z*%ES4cp2t~Y@^O%Oz*`Wa6eaG+Vu8S z6a#<2;T5i=LxB~}-htuNq#bb}5pY9?>gD7X5jAG0$0 zbm*9%Sk+Yt9HJ$)p!1;VTDyMtY5molr~(pdpw^KU2L1Yyb%Qp0OnY(qN5MB7J*j|| z&s*N9Pzn1Y&~13tQ?N?f&A{%-Q$c3MSvHsc;(o-joE6`cw=$(fH`FpY(ck&mp-Yc9 z7uqhRk!RAMT=jid`YvrC>~ET$%P?Ajrs%%fosTGBl=mXHl(E{Yo#<+dKd0wjTvSH! z-)AL?PJd_fu5E>m3oE!PaBX z#M9G$u7La_Eca-dsXJARwq8O@A8oNV`}OkH&32X=5UQQ#dJ%Ww+)fia`*Y;eF!r$-0kD@t8ppmo$mEjEMH5sjr7y^f z5sQwAYQJHIL)Xm;3Eda`t+A#6aZh7~jq(9ew(*b%=LIuBzm(l9(;XNE-zgNg&A|=P z`UYvoR|+k*{8>GSDt=;y&A+nFJhox~X_N`;)BVLNLkqOFz0d7}UtNbb_2nb#kCtk_ zRHKrGQZEZ{tF-l%^P7dz0$fskY_|14LySNA*dl%JS3~=hh_T{*nd#iqk(_su80F4- zNp=3&5_y%=66U!jDS}nlm|4|p74B9Ra#>L#SlCwzyT|@w< zu7ftIK-b(uUI?^2RsIkB?s0JtNeJ`Z!`Tp!Y^8SX$8PMaf^~H;~IDr$57z zJ)|ovdryp{=0G)MLL*YT4_`&|O{|~^of|3M`{>YVk=ql|$mcegY|3z2MWn*p;u?o* zNDED~njAx_jRWar?$${rTEZ=fD&NU`6YVR&nCQHP-HGyp&Qp6(*ps1kov1$!C7$?; z-_?6C( zDs$QW;**`Mqej^4m!wf<-i@5WW8A(}hwGfeE?;v}nFUw#&JQwU-EJW4L z9(=B&8?<#M0dw4!F438^U#cdXuO@)T{cbC+DO_S+AJFL$Q{7kVTbljMpJhSNXln&k zBKrTp>*ns{w(tW)uS|Jev4?wF*&3cB7U} z(KRn%khu?%05KIxrD7k+^KC9=4c5|^L9#KDG2G84Fzm9m1AKreiYQbPOjv}eRl%aJ z8glN`{GtLfKG2ACU}q0cN0QQI7-lZcgBmxO3w3vy%vUIm&@pvTt}A5uN*P67DUGOX z*a9QZ!uk&Zs|Co=0)}t~YfIe%YEy`xhGbQ@8*BhN12jdOwkrbn30*oD-<2@dQiF|w z69gvaWwpyxlZrG;yacw%#)^c=Sh-88rXs2y0hTs^K0JqotMh5l`+%{C#-^LrR@321`7~& zcnFTn-qLZW(x0A!(EaxpZL<^?P44ArDiqTdU12PcyyT}u(&%kIz2DuVgL|Yofm?#5 z9sDy5)8Wr3OJtpf^84C?i4*DxyGQ<*Ax@udLCMg7$sOmeAsLAE-4?oYh6IK8(8Ec> zgNfZgO?y7q>dNS&xx)4bCN>#rSSPa16vUQo>DU**edYUDTc%-iwD%jpj()-6G>Wb< z3;)fpspN!NMd&^byhjU9wn|_qbSH3+u+HP-!>IA@V62)WJdnrG9s=}SkN#Hyyi2#b zMT8Fezxb7r6`Kesn?OtSD_J(kpKlLA3!vBFX^T!GC;BR5{q3O>&}-6-0mZDcuxbt0 zZW^FBZ2}15jcqY7-zl(OD_)m5IG=1E7t=H0J<}x6rJ)Ls+*G?ex|`Dl0fU zHdTgop29rPYS2qM26dJDQ3Bi)fe2~wOH!etAukjRMvdH7fpI-> zs-eFf@DOV_vPOr^K~)Qzl7Pc^L5Lw$Kr#gSQ0ZZ5DzGDyJ;3JnvL~Q-gHH^clQqV5 zEEr+~{xS`5j90-YByft4t2!CP;iPG}w?!FkF^-m9!Qg6VA_Ns6js{fQBwV&YLw}m< ziyV_tho577m53)MKn=u6FMJfqdZ0YZ!WjbL0>d2_i zkV6ZiRAoD+Su)FL7%*sL9a?l?bC}HR#8;x!C57yp9Yt^4BpAtVBAI?wXg zUwz85VN8uw+^PgT|GZ>GO)w@VYLq9EU5|-MQklqi+;IM)Oh-M#Bo(}~M1@LIF~Fxx zan0%fKK zu=f-e_mI-I*lw+olX$F`hW0&vq&m-COi#)^>O_%YYYxImrou8tZA^p)JwD{7)Mqt4t%Ang2!CdG$mzf2^>zN*}AfW5cz zc6Qm%X^Loo?W<21 zlvMAA=DT`17Ld95vveTQIj zfny9jO6^zAQxDPl%+50CEb(*fvP(o>$H%=YS z0)qalCD(ee`=(ioLvKayeZPK+4SCH#Pk}sOW}2?F<#%@vwPnmdIO4W921>N_!o}`N z?y(AiLpGAgG$q9oigYxxYrl##{$XHsK0sesYz$bj^NBmfupJ@{F#xE7^M~Vu{!p9w z%GZ?eyUS%MfO`vb!LWfnvGg_#=AIYSSO(ll0a}rk2~=i7ajb`{@8!FIF1KfE8R{MP zjt0;b1nDgs^t{(g)6+^7X8!K>{ta?K1Qm7DG0(ZhAj5b>_c_beR#}ecveWeI%g6s% zO1lQ^Qr3hX>$)jRndsm1e96e3p8eYOFZ7Jr3QdK|P+0X5Wz8fLf}q?7aud*3+9_K_ z@PH%8U&hrtGcw;@ znx*S``GNu8SH80=OYVrnEsVvLY~P0oKPy%gr$5VP(~{!G_i|22WG_E`4w&=w#uwHE z1IG<3XwTyU68g^Vy@4Bl4v1WDK-IG{zg~Qi!oqnbJwQvI=;@~b#6On?$3eh`GO2!qs}uX2E{1ccyyML2Tp z;KyfN(O7A5s&62l|FVN7r2AlXPo6ec(Pkdg%mR1Uonfky>w)ED*0-#8Egnl!REE4A zO!gOG9QaCVtxZV&O?cVa&97yxH7qb>HAym@R~8x$LrHJ4Fii&^m>sp699Dri<~(|% zF05zU$RewTaR^rw46Z=8+zllnF4Tmurx{b6Sfvh_a%p*k{X5VF4TXx!`7Mho+~(}p)JG~|DQ~Fy zJK@5RAD*fk-n}fJeZMk#&1d2OTMFaf7TokBN8g4qZU2=~LBsH^WAY%K43HVU)|V9v9CCH~rd6xRQ>FiIJd&epMO9s6IOBvKQQ>QNoj4=`AHlh3O1& zFFtSAk7O#-hyxgNV3-HAy_}_>$lx6be5&a$diZWwE$~m?b8n}asbtrsLw(x*KEOrS z7{#2VWRo@F9oG6@ z%KDANEc6=WZ}}*Va6tkB`^EVfje)sskvQ6sL)8#QX-jXN zD}E+t8z56s??^0+Q$4>?p;K(dVq!@ATP34nchWVGVS8QA$v1~r^Br)LwB=DujZrz% z>;8#%O5yj!#@UScPEd~T#+pf~jwR(@$swOsx@T6=y|`$PNH z&F^1UHs_0y)A;!I@X&4Zirfqp8B{@KhagHz=ClmdJOBc9WT0j9Y+DMZ0NWYs zJfAcZC9zt2l=l(&mr^#O^E{j>o%12E3Y1|R+ditO^RrIF!KQQNTo-*78@!^{u+zXx zbL$`kA-d=cE}xd*QyEHTps=y74_;UNX<`d~MOEh*RyY#@sQ=HqpKeCaxcuk5CP70= zMd9fD>Mb~iknvUl%~VK#5Rdv-*hhBdp2n)*H2fa#AfEy5796J!;;5NM2!31GY6y6~ z)u`J&QFTdyc%=+-WmKGqpLZ7%5Ic>ufbISXS1TPR@yWitejJcAGW8!N@s*O}#m=@; zM@ZJW8R(#$!MvZnvaoF>$U#-L*g^$K?Xm7Xh5!#P2w(T1Upsq2o+@NH$+NgB{3(*- z@;kccBk@#WRGJ&VW)6gzYG)0uN-!4=GjXvAKy?(pB>KoWu|nGO#~c+ATDug!2x4KfWrS*fqt<;lA0+XrfcJS+MS^7(1RUSar~q(d)~5r zM_J1s0B7lmdz30m&!ELVA#6(^JmP6!?-y-&ugsx7C0>^Cr^+0zKq~$;pLoXFtht5t zS&H_%Sv*zVFgmnnG#?WoqFSBdd)Cp#Na=IFV_~d0&*H+yY{A?~O7p2(5$y**UjO^= z;56;&&sPd|T4Bj#8fjM>-B+M6sEKa<^6RB-JZ{!Kj^}Ir>I<5PJfAi>u2QK5}WY=A7uXtIhqUxGaebD?Z&_z}c>KPZBuKCpOgw#xNDf z@=6fZop*-_TWzs8F2Q*6m2F&F0|OT<|FJURYZ$EJHxCjc%}*PnXY(3yJjc({oZsq{ z?k$}%^f<)JHD5dqjHe9s@au^Y zJEFMCqT|+(Q@h+{xB)1su4MMLl63uOH-jsrbU0jbpSw?^#STJqImxkIS^G-mpr@S8 z9^=Z`e|!pPYo|~xc*!S{4f#+Liy%=^nGBKAdB6zkmLGU&D?9o9{%fP}p2CIHma8Mu zu_ctC=5+M<{d4UaGV*}ZWM?Z#W9iu{-n_i-D^!c8wxnLZ=U$QUmSDsw`E(^xppb|J z-P@RQ2uo{CpS_tCX3!CltoC-im0s1$WHi+tUP%$XQN$OJL>4)7*%yN9Oe$PN=)y_V zgxBMJZwi%dFM6=F&2;wDx*fG$vIX7I{aVn5^NvJWo3@mom$VI{idZlf=|a(nXPplg z##)Nc>q+__^;I;ecx8T63BsMl3E8vWk()-Cjd44T>HZ#z)q9MI_i-CZ*ivOL<)9<% z(1r&${%QF9Ez39@(;FK(kpfA$j5-kVQWZ9m=ZvHz_QeJ%E2(`T9(^fuXhck_&TpC+ z_A>QVH_=0chGau{-v^cK`;|u!ia*QGttR zBgJ5`-P$F)J2_cMX9Z+_c-_SR`0MY5M_3!7zAV~5?WisdFTQ`i*i2_Y`gvKLYK8n` zKZ|h%8CsR2zKXj0cA%d)c|fG)iu{uVS*5;_zT}wK@-rayfomH_qM;8b^qYChj+iEC z;?Hk=YT!!Nclrk#3stvN+re4kl~*}aCMuLT^{#$PLGzXdD8 zS{10v>dZ$IJ=&JCFg1Ub&~_^`-L&)}3BmA=Do=cuqXW5~`dhdMLs|*uyBw=|4pF56 zfyGwt#dzkHxt2S#J_m3Rgf6_I7o-cDMsNxL@QDE{SX1R3>=wrF=ifj55MrZCEYOX@ z-FNQ*_|g_jcU#4yhTkG;dgGE?3JkSd(w`on$3gNh)E)yQoe@;KcG` z?#lf>lhd58qItJhk6t&)v7U$=JPdU@dk=2(jTE4Bz-)~qbo%EfGBtTD)}x4rVv~e7 zj@rjMiFOF{+bhWY0I}LqsW8`_1=7jI`=J_2^47;$d9tv@x0%xwN+Z8QK|FOaSIIu^ z1faXo6So#Mj;OFGy?U~>{9EvhS}^}zSExR3Mcbq8NGSx#`F-5&-YrP;6T@eEauXT5 z1)ZV11|@~^I9-b@g20`g?Fi2@-3;GclpUg@fQbMr#{-mIokyej0dZl&_O~aoK>gHXSPu$8@MdGIX1q$XL zf9Tsc#?8~xU-;DGX+zyPn5JRlq(@g>Pi>dbrIotQSmg_Ef}KeVr6m+)F^5iZgiJ&F zhEJ^X!7xz$Cg`nj5!WY~^jdbbj21#B*E(Gb%_+(^HvPn}autn7Da;i)#rD8SuJ0sF zPCF0&!Cl+@j}-GC$iC*Xws83HpMxj!ZpitIJ$~IO>cB0;RLpp#MQvMcm4nxvKZA;q zcV$=m%x!2P#Ljk2xa3fW%n0nIDFT_=A!YP_QOyDtYy$-#sW@RtrHNNU78fc$SW$S7 zgm8}h;$RIA(eRGcPAr0o=UuQcmO;q%y|G=p`=o^k1oI!=mL8qr|Db6xwfKP)hC0b| zCibI+{ofK>ckJ9tUK|Yns8gC_?k@o;xhL)=zvrag9Sb?}nYY9~azzES5@9RhKTh;{ zLDI}8bH|7k9ryW(O-mMnhVMNn)bpM&a4O#+7(lHhG}y+9Z4fV*b|e10QO*582D(3F z^3X9Kt;S#n@$}<9cg)w`iDn!DR(-AqvrEURV@&E#tv5uF6gh93@6#hneSyKxDDOSt zZdi07(|gZz1+CY!H0l6pF=cO9hZq4PRsvPFvz*sNlt;~&XLri*ppt?`Sy~qGMoU48 zB%s|50f`@+iZ(*W!N1xgsd@>GE5WOElPfR3J~8A14&aI9AN|K$tYo!b%>}KGEpc&M7z64mI>opLVxFK>Ox=yh^2F} zRzQi>MSqW|K2qNtNi)TA0`k|>`N4arXl_3l=jBex7H1Y~Z=vhEy|Tg(sQex%K!tkD z8(iis1rMv@WLvsz&erzW7xjR^?91-rUM-6|Q=|^W$eu;g{nDh0e?GskZ^&`;PBP3N z|MO) zRzkzqeUz86=({7+JA6xl3TPW!1lABmlsZ63iz_3fM(lJuaK;@6u~ONAoc5oy;_~TT zWHz7sK%AgG*Z}xlsZK}Tt!;buO+&_~jwrj{vQuYP_9r~02%eJNJ@O`^d{>1^9MNr2a%bBwj2<0VrRWfq8%7LQ)u9X9k-9P!O!JtqU=FbEYIRc7$rSDwT9 zeBI3pR|JWHz;|UM4K{w7ow6DIy|^xdi3OqR^Kt*88u0cg-hxMTIm{jy zB2&CQ)TtgP=Oc}&VJRQXkB@miaSBT)=U~*ds%Xq@l2pM?;l}VjF^isvKHI$}9fYhY z^3aP3BW8$r+@7_L$f$l&F3x((MWmbe1=@ic%QCwBj3mf|;42UmNZ{8bGSw&hO!{jR zrvA(rky(t8?FL#FT2}W-Yvw0hkUe5%A<3n!5BIy_=gkpkFPmDBl1n#}d8i~_gnBo^ zqY5HcWZs8|EmpvWDjhroMD5G&nA|2gGLND(pY8Sf zNSx<55a9n^=)P}xQYM!vcC?rbQKzq07DZPXw0Azk%DTn^H#3j zH@E|v(Ltwjk5y?SJde+tFU*s+tIGn^J1=UziIdnieQmxC-Ba`Yav@EM>fe#atZ%j4 zr*9==)}8kp30sqw-5PMDD?XC3XvSC!A0IcLqA3K*)>qnUB*a5jrKQKnE_EHBINb%D zK2kQXV8~hJHIZc6ak*ARbi3b*x#L-ICdbW=hYGwvbNx~-XVDQ+yL|tmcikvygA`su z6Vl}C{tsCtXmv(t1!l^DxDszY+ci@{I*bvGh8Fkd>9?l7)D^@^)zm`tKTQR9%T9Ml z2qL7J_)A(B3XH67AW9&8l95}hwt-)O`uo50_j@ax#AwFuW!i<7WhQRb+<1%CHZ->8BjT90{<#6GAUJ5#=<3>EwGl=Pndyt zu4Rgs-(K!!C2{xO)3K(Pm`?;r{n|58&vi%|o|u1Qo52;mB~-;sm_*NbXo`X%Wn^3^ z&Eu_4l*b;$lM(>wscY$V$>WJ$Ip!_*&taHu##&O|x+;ECK2CI{Y0WAwv~+h-TV@I* zty{II`c?GW3Z_HEs>s`d_qQWUG;*7qFw# zsOpS5KPM_8q^`nE>MhqbFXTn2%2|WR2J08IqGQ_bx#L$V*GVk8?VEZ$5%c^*hh`1= zNrB5@^?WIOr9<|2P?z>K^M|$e?x#q7ucIWTwNtTyG^wq`5x$^-qz|te06mn_$zamOG_BHv8MtmUI!+K8@ z_aWZNM%ltatM9Yz)~)}c=sf(X{{A?AC-+_#*WO&$x<)qHF7CC*wO4eFgj9$!8uwo7 zUR2i%N!Q9Mo2<&tC<%Q-sv9X~L|IY!`TYy$^Ev179m~oURBg0&v%7WNV7bpoorT(EkKW`Zwt4RC z&}ZbvYK;_&OtSW+_Sn;Ve2=OMGh-X(w_VgJG54qWom1kqj=dr74~Bw=7(aC8 zE!~px+|6alGYRETg}6w0(a&5EGx>j4GTbg)XVl+wYu)6xmk*J-F4~j+i|0$(PXn_N`2bHdB`Q{cEFYHO?T(F|aai$= zSPu5x-tyxLHq^Vlr^nZ%DIkz)eHkD|J8E@fQjFfFM6?V^&6q1xwGE}(^FM4cS3hR; zKu(|TbgSOA4E=4%ROZCB#!JndYLw70Y`Skl8eWq2`|<4fPCD+Stnsb`$#c;RVfEP=zPrT^p-$9 z`{`Ya9+r7^S=0(?8~;i}%KgEmt`^h7%C#aa**XO~@uw2l?wd6XQmDj&^6s}v77LjM zC`x4pu&XZ%zitvS+OlvXI9DH;8FCMnmJ{5xDI(TymC}Dii6>Xh@0;`Aj#^nVkKx5z zboWUaJ-|B#@tBiBsiG@N>mkU+p<^bwc>uo1LT?Q;i>s~~%HU4EvkFN#I~06Ofl@c) z%-m>PP3A7t4bi^>+Z3V57`=S^hZ;GiTHKP7xjw)qg-UNT-|Pzvo|ghVDT$!yswLZm zg$jJ@n?-N$zz&di4VBPTEG-KVw`2a$oKFf*FTeA-6zbRz`2Gz*?=OnU)9n-L@)@&Z z;oAK2`I7}9YlHjRRSYC16jTcfkw8&JBcuUsDT3l=oCPB#o4+u{{nEvoK7*S>Z12u- z4~n_a0H=Oq8(R`Qj;OgulyrgbJ@@gO^!^Hm`Ry@uhC==_a*$^ehmtKd$6k5Q!hKTq z>5jTR-!jDY-^=I+%L{u?e|#jo-TS3qt|^FS%L+17NxHnK2mu*WIwV0piJMBt$7&ca zr)hB_#`c8U)?(+ulciG!hNDek#kmERY5Myz@zbV4DPxq2FliXlt4%#1MPG=M7T50T$nW@Hep z12N~{x8jr{fGi2Qa*+i^v@2sO*?N_vG$S4fI=@oPYb9X1KVndZWeuYnQa5L@s567L zj&%r9f6!5CGR;@vGJj*x3SNlsEWQFwp+MOE$A|L_?_BWfzOwb@P4}IPr=Q&bvI`m& zLVl^@`3v=yG- z+JEj$q^q4>J|PoXJ}V+U^>f48KzT^CMkW<2z12#V=X*?j@9cBoW(!EJ@yvKZ;*}pC z`_hC=ORmQM`ue)+hnUC%ygBIn(Q8E<=Q!We*S{`hm3_Fo0+U}1q|#^7muRv; z$M4lL6JxUt&4k%WDz`2q`?HQ)M9cYn+s$w)j&gm~4D;Pqsh+J0qiI$*m9H$_S6ba- z*U1ApB9W-=GpnzkOHq(6Bhqx0DQg*>8i>FP;vAF*xIG!n;~-w>1i1Gv4rEH1AqHif z=u(%Fqx@NlsD575ozY4w<0YBZVGxcL?+1g;<*ok`d;Xd<5vX>In!X%$ zQHG~)+1#bEfBw@$J7~v+dGYrKZ{A<|bkp-g{I^G*WzNxjau3{p$Jqloh2q`I46#S& z!ph#u8s)>qTLnn7dXvn42i^F6YbL;np2Ro<)r^7nv^wNiX2}$#vuC+}2Kv^n`0TVb$@)X-q=fZST$!ZFKVdHU6*BeK znbJ-7i}YJ0y|$K9D=IowrZP0d*eV#4 zlieXuX#-upk>?oL$+pp3@gQ|{QVBada1eN& z;_AUi)#0}ze0G8H;`T0Enuts=QgvEOYl4>=Xha)b@X}Pu4C7g!tX(oFo{96{q&8X) z297VzH+F2w0V6XxQtnC;A{x!2HHMrdrfvC_TuwCEBnNTwlUc-S0gBgFoC^PVOfyxy zO67ZMZ0nN5R)N)UM1a5xEXN@vux?r-IQ($5?*%?uOR{4`mhbnGm;?l*0#|ZogFbxE zf8|ZJn!fERUs}?Qjz*ooVaxixuI0EtjbhfFHEg!I;{pW$JH1G0SrBf3g&xJz)k_n2 z!z98klamHHQ*QA`l5zY@fU#;$;mepWS~C6g5*0;{?8$+1vH^1M8qGY-#M94?^@D|3 z_88UL4_k=7CT|2QUQ?K2c#=6dO_g1+3gMcdwp+31i><>)Fcb%~oN|es6)UZ@$@g2wI5D%~pcr8uXOums0YwT= zg-y_n6xb)eWdef#gNRpzRH;`};MWmVrIQp6=g<8fNBNPwA`#3a5b3+?X(E+VmWdXx zHgo^b>L#M%Br8j+MNXM(mPP`(e6jc+U&5M{qyNh;g!YX3hR{gdRYGQa9 zggC=ZO1_NGd7FW`DxBodPA;X7Y{MLxSpX95p1FfPmWZvxrDGZ8{$>CRlr3oAhb#^0 zYvK9EJWElBppliW=F$Vsd2-~@_(3NzVIY5no+?Hd#;$o{93f-=mWI`87}D8@$~spf zM*`fB@=liBP?t)b4K|%#wh$U--akbc)Y2}14HOR~-8!|7Z;Gu5%}0%Qoa$p6SvfZ# z+e}P9MQMr2VyUXF@Hks4VX~)e-zeE0IUo0dKwjrwAnoocs9HfE=ZB2J-2?ydp;Sx; zZO|da!Vj1kV4CnNQ}7SiF(6?$d_Qlbv6c<0y|Ny;A~zXU9ht(n84L9AQWJ)dQk18{pB?O zH(vX0G+yUh>rLO;n^KW?QY()%a#2=2Rc35=CJdY)ule-@%U>x2^l*LWvy95EEC<)< znXCGMje;EGd*{zzG;9!NMxjhBQ*KL`kwLI({O1|SQFUo(vxe6nYC*`y=qvbCUUfj5 zx=N}+1m?7_&Ex%fpiFWg<~q}&nU`W{Bv&`_#L+^!r*iIJxS*H)reNji*6})T?su-k zJde#Jqq9CTI(Z*hr@!z!Vb=657qnubEAtaYpZTF`&-lhS897bWO7=SQdk6HTtSQ(` zJR7Bk7loOnY2$biDYW3hHwh|XR?XUv68U#kyvo-?6F&Rx9lTXeqXghf0kgGcZOv0N zIqcFfvEYx=8|3?j+=L_hoT>T~=gTfKHhaF-YneM`l3*=iYlDtLv`Ki!5P{pu9b-k+~#KeTdl@#|kMyK+-|AMxS^-stclUR@e+Qk@$b z7@z7-e|Jau33m!Nl2Rd^Dv+&bl!@ZLJu=L=zMW>M&Shz=A(V**Se^bb_&m{QtgRE^ zXWIQ;@Sc2Nc*w-=5k69tpB9vQ{$}c#qipCN*M*f^KV*8AtG83(R5TEtJcs@mZY8HNK66y#qXehBQQ0$zW?M;1G1XQp8!85q_gm%|pnvxcex?C+N{ z1QdjlSp@SFWKVrtDsE&$!Fhg6cZ#|3)9QYpGFJ&XJ-ZU{4e%3l0Ur~Y{-3SL z{g*PyS-2xsWWvLnu~-m0;*63!4itzL=+h9-BW6yhsZ|rzEOGP)M5fCL_?Vh%v?HdK zDCu4nss1{>78{9~p!5*Z_g}w8D8PPah`t$d-gszv!2WbFN?Jq{Zr2O%tW+UBLishR zSoXpQ{St=Cm}rfcah1Lm8gdov=UXQ;f2w5*XXVUr1p6i)rdzMm_UkK8S;EhBo1CxHnnv` z#0q)7$g~do>9gTARXsJfnjUQlux5cX8LM36)rn|L#hkwC^fi(OCgQb%A~pVVFxz6Z z>WrppDv3>76HaBxWG_zyBh+5O?srXTVH__KN50%r0$z$r$0sWd5fZFzv~RJa*qb!z zEqXO7z=b-1B@SeAOKTaUmq5~9HK!Lxwgoe_Z#QdGNNkOK+6w(Ag_JS2N(e!w=rbzp z>7u^*=;GQ7t>9FS>&s_6;7fYZWsN+Bm_@OhmrQ?8cc``iw3Sp-T~!*U4fo91`~lk2 z=4{z4gG2yKa>lUp5}QXIdvGtduJYA`k#q#R?!9PW)R@*JQ~7@LAbybTC?9Hk-U>T& zv*6$tAz-^+z4wV88OY{#Vhp5cO!M_8K@(!yr+BO;e~5n#G*pZE6O6V=8fZyivI87s zEn|#+)ueN^OrdH<@650G z_Qa^jkyT#KSh+D>jdxtlbleEBZZ>Uh4m)nnI_~bV?%r+gemm{~Iv!_YJ;K^N&hNM< zS<0MkZIIQ%L8&0(dA5p{HeAd02N!?`4jrQG{S7p!?SjqTfgW9mk&zbAy>Fp=o}LS< z;<*>J@icJsYMt$A4MXi%SN$E2*E)W0V*TdY{NC^QebVuN7aJOkc3^+4f5{D#ieqcP zq(;?zDqNv5!{beFg?rb3*6V#N+T@7`8T(F|7U9(Hq~L1VT#S<9HQ$KYy*@?3`y1~D zndt@-E(hDR2RrG6+Cvz>V{Wd4zCdmzG0d9y{(oN=(E~y{&6^P65w3 zm(x45paGYUaXgB|*pd*g>!u%Na~@O=1rLWx$=T^=7aVo8hb2~o15ZXmuSCM{ge$V^ zm!kn7i*<7?wc;6@AzSYo+O>m%h}Y|y`n_5oUr*!{oED}p8NdC4$6ypm_J4J)5hr8a zuf%#kj`honhBPUR>!@a<4bAu>2pI2+GY)bzgsvxg)nHgCTqPQ60eCe89nYK(c z*4{IEI;#$X^LmXrmL#bL4=bloL8{rH%fmon98j25Q2p4b^&~|gjv}Jxr~Lee0*Ja( zrVTY;pIU?>Yp=>tBl6tYih|%19GwRKcoMHa5HU!n z5CBjN2ee&}0Tl@!O{@L_x~dq%7RXFWkHtLQ0?&J?VmqRs<;idl`Ym^FXzs0y3fF5S zu{AU9e_oVJB;LkSjyM2=JwDHSE@+@iwz`*tYXhp-kLAogG492LA;^WU&H!OG%UN~x zR&6_{2q@^9B8a9xXYB@n;sLowJGdS<{X{}9`+TXyA2iG-{%&WX-@sQJ<9^f^>S?tC z!RIajw8*_{-hzMcfQmb=yI<5;+;&(6S&`xjU+F+`zqu>)DRuE;^AuET=UsRg^UO|R zoZih?p?ieIGt)uvmAcE{w(oswy}0$;$c+pw(a$~XbR*y($!KIhlOqzqX5Zy%YS2s~ zLrrul-B}gu`{h+Ej(#%Ct*g>q+Tx60CF%T4DbH<;x%I~=r9iN)jn#U}|yDLmZ=Dqkw`;S=1WtCHR) z$t*GZyc7AYH2*6-Tr61zJ(2s>tU&cX zQFPUl+3G81)S7VriGiChNo)})+75zx;kW`5g)nvynpsyouHz$9Vk$s6vX?zUTJl9e zgQpMd6y@O&ytIEkju+cgS$EhK-&=JJP(6*i>)=x?ez)g*PhQG{UdQg{Wf0dO=gp)- zE0O7DXwp+cKL9{(zVw+%o4pQR@GBAlF*|!r^Pmp^VxYTFFQ0OS91XMVR#bm#^&iRkJtQBlnA~*?Kx^7F_RnLuB2@or`z@ ziOMFTO@#r+UmNn2RrDUkc-bRP#Z?gi@IWz6dml*c;e`9C`Xt|SQ++1TZ!+&%o}$9& z5uXrH^GW;x|Bb%yXP53`^0ka7yU$hbV2uAx8_pG0ohp9def+zY1LxQW0b;ww@DN|9 z>K}>rvMQ@nqK${MPSUV3KWN2*q%5%8`P6L9yRMA)ud=Sq@myzI`qQJ>-OHku45cE> zk0o{bg&Oht)O}B2v7vA;;Bv95WNVGCAa)IsI z{Ab^^*Hq*=P3s#Alit-F2-tjZ^EYho7JcEou>Qb9gGWR=VPA#HuoUwbyh1NM!Dw-A@)PxlqjiUKZn|AGbD| z1T6N8a!|gRh)!DXUNe@Paem4c!Q9H~mS_(UoMKMsm%ewn`j#S!xYaArQz{ZHUI8@t z=y`ueinOr)XLCJnu+(hp&UKi_vn{Ek-<^7)DDwA5|56?ZoE>t(`jhN$h*(c{U%eK0 z>1!**_T%@$&<5KxWp68!oi-bomuJ&V#1`}&GR6r$7-W2S-T=5x@P5Ao{DeR)g!ppgBOL` z=jMAxUC0ynj1mw2z_qI9>s}>WK#2@wWJLsjmiwMs$@d7`#ai+M%kG2|V>lqS z!Y&?E7$rE8A)@AS^%}>?`i0Jz)%hnGCmTN0D|tn>RZ(kzUw^?2ibPvYS} zPNTT-Cxcs>lVLcr7aJ_WXL-(IIPAVd#y?Qm zg)rBcTn9b`ond7Nl=MilR{1>1qp91APFB(F9i~QVPFM%s)cxQUlwk00rWjzn;Rf`? z*?gUb$-+8=PVq;yRWP)+Tg~Chq&vZR9{%(*`ExrvcZ~h#`Oqf7`2j~h)r!dy^4o$W zQ4RkGEslY!bR0ZXDG}^+a$#HKmAYU+g)>)*_sFd~ zw?5N@9u!>|3#-x&uQ}r?*E8t~*UTK7=CJ#|ZFYqz+E(j0T{-6N(eNStTz%JuUKI^E zoWxx~V!O-5^Y`!DTLqvGlqBWr@`6hd>*8Qu8|mLHM0n8U@*}n+NQylB-Cp^5g2dJ- znXkBi@FXUI*a&E-`Z-~D@yRY%>$z;1Odk-jd?WEQyOcfSBGK;psJqC;|i9A_$x33NAfyH06w)(F=(1hs*Sk!~auT8|NEzyCN{~Ht@EC zZvC~P!zq%|jy>IY3YYF;9loUN(&O-0_VG-@kC#_I%I6vTKdX>ma2+JO#>OqCtNE8? zia)u;zHr^iF@8D!>u{XE!_a}>7m)ThzM7KTjtSq4cjS-ExpHV(NvO5{0Z8bbSB{D6 z?RBICKkE&=-qL?t+Jg@}xt)yWst<8u1zW8-mZ;{BT-Uaz-ud=?DRFI#b?Q&^ySDe? z?h~;d{p1XvlVMoxYX{#OZZGX!cE&aSFo8DYAMSp3v7sO$ie^SH<+)88ELc!W29j`px)ky&_ z-(RO_;mh}M)`BiO z2r=I=yF#UMeeEO};`sV{?NwV;Fir`M&c+7LjdGq<96O~tk=wIY`4L-)L78-9cgPcJ~nz!g}` z@4`(*m7E)M^?diR%2+@4*#;m$!DatLRM)SH$LgB*eyN1cZO|u^Cq}M6|MnJTZOyJ3 zM?rq%pddYPP4(#BoTzP^y0NfHhQG~GsqBew7dD?8r@N>p`gfK(8qD)OyauSiJgT{6 zpFUkY2Dzar+%M1rU@x(EQ}Emj^eP$cNNrdpm}Cb?uIk+xa@*QLjEd7`obPdDOGBL!54-qH=Csx#0t1w%B8{ z_U*%EN6qhV2a6OMGfyb~TVcTN19Ymr@Q+Qmz5}GX1!E9-j;|jgl?I4g^roiua-g7VBQ~IB4gVV!DQLEHpR64_(I8tWcJu27o(}{g1V8fX5=bT% z>|E-N`*GLw*LTm`FJ7i5Bx2tFrtCD+$Ln2!Q67JkW?K%=s|)|Qle&EwEnomAgsq0> zzZNL~xBE1v39YhFQdyl7egJ8RI*g-RXaLkv@5rkHICMD={!cZqd8Y>~|S?hO?`oPB-!byIWMcS@G_3qb6#G)>Vn70Fs0= z>Osz{;yc(nZ}P`?3LzCAIXE=8rTwBy~syZ^@}J$oiYq4USzoJ*^T z7k4j3NwZMS_a@x|P4yeiL%Wo))9ktX!+TGqxZ0#8i;+CjDVY8jCRiMBd{{&$Y^4;$*#qRcizh)ai9#7}>wIN#g#m|koJlDE7jun`?n_qcL&%3P4}K_tekej?KzNc27HC@ zdEh_`&%C0FJQ1tDM**`OQu1~&8!j_X`D*S<1_?7P3vY1$fpXtC(2qKe)Fu6S>Cv#q zF>8Y=zj69|hLqgKyRV`O=GpxdToC*iSL}1UG^A<;lYYGL&XJ(0Jp04&bf+xE zQg-h+-Ay+2-z9o9`gp2C)EdvqjCjj=-O%jdbLS5uoPpwS*1Vxft%Rhdy(HXYzBfBb zivr1uSCZSm#*RNu*2znrIhm}>9%tn2XA$Wwdpri)Pj(VWnchos!^V$Vk)%k#mj6;P zJ1GNKlAq;x@3!-`2Le0NBwz)pS6Wm1ucVo2*t<~)iF!`)utf3-U({DY<=$WoYnp$s zOf$tq=@acph9=ua8}+2?rtqntAu1YBG7FMz&1(*T1pv}>XvC|J`PtL~ACmyXR_D^= z=x+2Clr(IAl0Vi`O|rX%aL@MyO|BX%W_xYtqnXfc2L$ z42FpL!KQZwGp^@>8vz{pEDhc)_IffxkC>s-3$G_@J%@3Y_ezET%IMR}G)F_0X^=s6 zj)LgRH(qmo!|<51RE{>e4;Wk^^_$ckv;S61t_uRB?%b4?6UzZ``c2*v{e&1KBPGj( zt+bGhjc64#TQM3^sfX&FJ<;?@YqA&4*D0w;&K#q~idi7{SlqXqPk^&P>zmyFNYZ;u z?tf%hfth=?-Wd<_HQTLgoMA)^nr)H{yB(+9&qB;anuyRLlK|M5u*^{CiC*lHv?v8K z1%Tb271}AtR0+C_>4k4ka{L1r7QPmGg5%yLvPqdE4d@CTG}mj}#u4mn)*d0pA}zMw zNNdFm6Esp>Us}PN-9u5Bh2eA^%~U}f)+~YTz+hQ8uNEI$KO1m^@QIpFa_!+@9%$Z{5wI8!n=6jdDlCfW)lLN|#?kQ! z-q#VG!I$s_(r>gHamctbo?pzZ?0xSIhdFl5fXO)h&T2vl0S7s=yOSiAuSoc(NU>^T6AU!92RUU)e}SVbQ>fUbz^ zg%9G8H(1#RmJ0vKNR>?}#0M)1WWFQ|b5J0AWbRV{G3+LIkHNLe;+|7SPDXNLx*&9l z(VjZ8KpGUy(o&c!YyyIJza1go5;@eUAZS3AJ+5pn6|&6|R#JZewMD5! zg0~smt3>t)b+{3nLq}aYs+N1V5z03OT4!+=0mN(zt6Dni_9stVP_%rHx6mSj-)Olh zADqoWq!>@%Q>KCgaY)|m@~SaV4jMUJ#>4tn&d~>-B(ksY$^5fMu7zcv_J#-2K|6X# zUs8VQCxkKL#MgG7cMR@O6lC@Qr7^8_E`b|R!+k)0a8r?Oo5hWok}?Lv9w`C@GC;Yg zJ46!K0TZbcRxO`irk$sM`SMx9@|_du_0q8oQ$(l=8JxpH*iYWA??sAaf$PZydkD_5 zE)-{mmWY1CW;M^g~w&lMHp3`V# zd?aQ-9sX8{eUb%HnuJa=*d6H&2+D~OfXo#c_9ra%``@*u7}*~J>&|p)9V%sEIzw!2 zxYM>uF`IQ9{a_u&<2~GoYZQ%WCebA#BDFE!?lF0)e-ueW>avGt zv-i6@+s<83=s#kf2FdIFe)xm@09ndCOT-!vfT9`QO+nxnVuprEm_0HZx2R~h&tqX; zv4wM{azx-|YlE6f_>$ezFTO+>=MsGu%sAadAC1iE1vQeoIL6CO(!mRgoVuHhN@zu( z@9`ySlLvGM&pkE-mylL(Rj@sw@uJrm+!CvDHp<6v50304kRtJMBom~Es@i45$DMn! z*9)x!0%vTi>TT}+*)is2`N*#wzq~$1QP7}~{!)ICK@?jZ>Vc^Ne1HXhqmJSc?PrfHh4=Ez-LLphvn5Wq$L>L8-@T(q&dLCc>E^@4`FadTzbK{M zGVurlP~vph1fw(i6W3b4M`t#wBhwxVOWGh05u>Je8?Kun>o*}k zYYo1PvKtye2i4&mWgzLW`y+apr{6v6-n}^(+SDK-%45r2#xmm2fL`q8YBzgq0Ef<; zL%o@Q8qGSsv5f8_Zi+@`fHpM-MKb+V_Vfi|aShQA;1n*?eQu2$Ahk*(Yn|*e^jY;& zWQ13E#eanrE52E6>WF@$%Dl|ml=RW|@pDVX(%ve~^k~i>y*cZ>P&=dHnDDB%jH*=} z`kj*WlizFxB99&$-SCWczfDSkJhGFK29Zf6dNLFJXwHVo`|LAmmnsM z7%2=Wd!2^=6)mQP`rEDX^f%PK5v@Z4fA8;k@(moJ4*jQ9Jm`Jm(4v@j4=-b#e9NIm zg;K0ycJhSt!lICx)76C+-H^vyg9=%79}TDkD0|dqXeu$P5xc-2oK9@%*#mHI*wc5* zpQ+ftbkNJXj&-!0p%q&>kn_4_}snq1F?+Tc*T`&-1T@^=PFnnrm zeEsrn%XJ-(D{sJ%>mC3a7T`MZS@84ckh7*PjbRyg4GH=LSN}xc3#NXzVt4t#0UMv* z^XU>q0IvP-LpMyqug6yJKY0)&VGp?+d*SPwq_2dtrc#ZTK_`t0LV%CFLabdtXC+rY zXszI%6R)P2qO?GK$=9=PS>^nT7U($3Gwrr3a3f^s+m(%PGFQIWl^ki*s762JT8;bq z9VN8d#--HaxY}O7>Oo!Qe!TkZpXZb77kVAnkn(Hu9&4i}lFv=n#x~Xx`_{h5=k6u} zMfC`F|JLYy>mw7klH0~wxG%FM>uD|Pa}SC)asW1}U}ueu64#BM5YuqHpjDWG)2BPb zpZV9{Z>a8VRD_sDs}MjqCC3%RUj!vJ7VfZK@9)Nsw*|omC5BP;ewv&7^7We*&o@(3 zZ@`H`F!`kcJ`b_~aG1EQKP6k|LQH>FQpAY@D^KIyJb!ZB_=){tqDCS?)z1sw*VhC< zBpZJ&iT;{5`4yi3Q~cZe!36@aPi+4YLWboQ-OOpXf3O098 z({++M!=IeUQ66k`+Q?yxia2TQe|wA65VT+Z>&1AMY90KeC7 z@95vssiww_J}SwCg#2Z&@j;LO0jGyqmL)#-=pbL}@GvixeEqN?`>^Zdp~lhS!5b@v zuaW*>e2QyY-|fSJhEuy*i8cWtAGJW|X26~Ue||6iS$4mwf8kFj-(U9pzmJ~&?RfK7 zym#Z<$^$n#`>Dt>IS!uUF%Qvi|htK6a#StM|(}O%#z^(s=>39 zpZa)UUIcg~>k}bUMCZci+1E=}3~9nGSsRxjn_NZr`rx^#WxE26GZPiw(_b8l^m*nNr z4f#s^?;sEls)L-4l=qw84x7$)ZwPrmzq2}A{TQT5TCQJXD4SSUSobr*(2f*t1%D%% zh|i;WYG=9L?Gw=&sj@tPG^VSe^ZlR-+$0su_HO95g4$8{@A&O+ZyKI^KgAZj+*p29 zb^5+$;-B9;KdxN(xP(Z0*fL-W;?Um2-P(7JG-DH!(8;IikWCT)r+{eWIR@#c$cIL5(xuiY+kkMGG{{@%J zG=Ya#xZ{I>9o>Pf`(qu`+x?iNHpHx5Z zrt_brXO6q>6V3*8L=EWb0QTwrRfiEFKhdWDn54dWfFf6~(dAQIcXaj^{%Pg{VZdw# z1@fW(fCWwqZ+wa7mzWsUHE^8RgQP1s{%$J%uAROFyE+y_;pZ00rTY@QJsi{QIu^XA0ggMrs3V%R&QzN*6|SHMKuzmpbL( zbKfVeplOIGdb5fmbwdZMge?8gex}wg<9GPOB#bi~(7F*Fm|5Lzy_AIJ$(2_9b8id? zkYB{HRdGz|IX2g|cMm=M_20X3&M*Pe$)mc66u#0L4kevZNt$3Us?92p{J3l5*pB@~ z`SBk)!KHhoU+|a>Z0&uXMNjf;?u1fyAW>n2LyhJ_KFRe*Q12r!rR2}$4%N5Ut_XN6 z`~im%d_;Jwil+!#z(J%0O(c~zfL2Wp1jGSyLPFJ=EuLRXtclyZ{v*Flpk?Ms>)rA! zeS{pW_dj0+EI)&(MC@JCGnhI1o(Lr6^{=rp?fw3&7-H&JVBrqh z>tqs=fwtQ(7=c8lw4N9w*NP#IxB}t^Z@(bYA7+aS*Q=W$0|!Ihu+|86S995rExoe= zK#p)K=y>qRW+z)7E^8%??tz~Mt%!((=UNs$+CY1#z+#b6+N*hZgbpH`qiz4W$~^+i zzk-ee@T6+wJ7?YM^u4;KZl*zr41xf`-Ku%0DEdp3e7N|jOqjKB2_6#g8HjMhfCL%= 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�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∈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 literal 0 HcmV?d00001 diff --git a/frontend/resources/images/on-proto.gif b/frontend/resources/images/on-proto.gif new file mode 100644 index 0000000000000000000000000000000000000000..9ccb7fbf862a4af247468986e3a429c3822e7c0b GIT binary patch literal 496554 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⪚Xk^{Ct1^!MX11 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Ξ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 z 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

      5M8zQ;Rw^-isLxkq_k5S^A=L^1n0+) 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 z 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

      L?7%U945u%i@j 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

      &z1ewLu{uPE%D>6?c} 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 D1t&{L literal 0 HcmV?d00001 diff --git a/frontend/resources/images/onboarding-start.jpg b/frontend/resources/images/onboarding-start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f089ba4a1573caff5b26816577d62ef2f38766dc GIT binary patch literal 32513 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 D@YPNv literal 0 HcmV?d00001 diff --git a/frontend/resources/images/onboarding-team.jpg b/frontend/resources/images/onboarding-team.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dbd28f9d47e67383d50bcb648a2b82ef52064cb6 GIT binary patch literal 20760 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

      C~ryaur}V0 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 Kybyrxv3~$tXEss* literal 0 HcmV?d00001 diff --git a/frontend/resources/images/open-source.svg b/frontend/resources/images/open-source.svg new file mode 100644 index 0000000000..7bc4f583e3 --- /dev/null +++ b/frontend/resources/images/open-source.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/resources/images/penpot-login2.jpg b/frontend/resources/images/penpot-login2.jpg deleted file mode 100644 index 3c9409fb5c8447f0ae8d6d178f26812daab6873f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195319 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 z


      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 diff --git a/frontend/resources/images/pot.png b/frontend/resources/images/pot.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8a96da49fb72cc2a9e36c56d312639166130d7 GIT binary patch literal 117830 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

      +ksP<-kgaNlPN$RSf@Zq%49dUl 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 (rp/mutation :update-profile-props {:props {:onboarding-viewed true}}) + (rx/map (constantly fetch-profile))))))) + + ;; --- Update Photo (defn update-photo @@ -165,7 +175,6 @@ ptk/WatchEvent (watch [_ state stream] (let [on-success di/notify-finished-loading - on-error #(do (di/notify-finished-loading) (di/process-error %)) diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 8d194113c0..635d2afa64 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -22,6 +22,7 @@ [app.main.ui.auth.verify-token :refer [verify-token]] [app.main.ui.cursors :as c] [app.main.ui.context :as ctx] + [app.main.ui.onboarding] [app.main.ui.dashboard :refer [dashboard]] [app.main.ui.icons :as i] [app.main.ui.messages :as msgs] diff --git a/frontend/src/app/main/ui/dashboard.cljs b/frontend/src/app/main/ui/dashboard.cljs index d1abccf4e7..6c5350f0c6 100644 --- a/frontend/src/app/main/ui/dashboard.cljs +++ b/frontend/src/app/main/ui/dashboard.cljs @@ -13,6 +13,7 @@ [app.common.spec :as us] [app.common.uuid :as uuid] [app.main.data.dashboard :as dd] + [app.main.data.modal :as modal] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.dashboard.files :refer [files-section]] @@ -24,6 +25,7 @@ [app.main.ui.icons :as i] [app.util.i18n :as i18n :refer [t]] [app.util.router :as rt] + [app.util.storage :refer [storage]] [cuerdas.core :as str] [okulary.core :as l] [rumext.alpha :as mf])) @@ -101,6 +103,11 @@ projects (mf/deref projects-ref) project (get projects project-id)] + (mf/use-effect + (fn [] + (when (and profile (not (get-in profile [:props :onboarding-viewed]))) + (st/emit! (modal/show {:type :onboarding}))))) + (mf/use-effect (mf/deps team-id) (st/emitf (dd/fetch-bundle {:id team-id}))) diff --git a/frontend/src/app/main/ui/modal.cljs b/frontend/src/app/main/ui/modal.cljs index 87d7ad5982..e9fa25c7a0 100644 --- a/frontend/src/app/main/ui/modal.cljs +++ b/frontend/src/app/main/ui/modal.cljs @@ -61,6 +61,7 @@ [props] (let [data (unchecked-get props "data") wrapper-ref (mf/use-ref nil) + components (mf/deref dm/components) allow-click-outside (:allow-click-outside data) @@ -86,9 +87,7 @@ (events/unlistenByKey key))))) [:div.modal-wrapper {:ref wrapper-ref} - (mf/element - (get @dm/components (:type data)) - (:props data))])) + (mf/element (get components (:type data)) (:props data))])) (def modal-ref @@ -97,5 +96,6 @@ (mf/defc modal [] (let [modal (mf/deref modal-ref)] - (when modal [:& modal-wrapper {:data modal - :key (:id modal)}]))) + (when modal + [:& modal-wrapper {:data modal + :key (:id modal)}]))) diff --git a/frontend/src/app/main/ui/onboarding.cljs b/frontend/src/app/main/ui/onboarding.cljs new file mode 100644 index 0000000000..77b88823aa --- /dev/null +++ b/frontend/src/app/main/ui/onboarding.cljs @@ -0,0 +1,230 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.onboarding + (:require + [app.common.spec :as us] + [app.main.data.dashboard :as dd] + [app.main.data.messages :as dm] + [app.main.data.modal :as modal] + [app.main.data.users :as du] + [app.main.store :as st] + [app.main.ui.components.forms :as fm :refer [input submit-button form]] + [app.util.router :as rt] + [app.util.timers :as tm] + [cljs.spec.alpha :as s] + [rumext.alpha :as mf])) + +(defmulti render-slide :slide) + +(defmethod render-slide :start + [{:keys [navigate] :as props}] + (mf/html + [:div.modal-container.onboarding + [:div.modal-left + [:img {:src "images/pot.png" :border "0" :alt "Penpot"}]] + [:div.modal-right + [:div.modal-title + [:h2 "Welcome to Penpot!"]] + [:span.release "Alpha version 1.0"] + [:div.modal-content + [:p "We are very happy to introduce you to the very first Alpha 1.0 release."] + [:p "Penpot is still at development stage and there will be constant updates. We hope you enjoy the first stable version."]] + [:div.modal-navigation + [:button.btn-secondary {:on-click #(navigate :opensource)} "Continue"]]] + [:img.deco {:src "images/deco-left.png" :border "0"}] + [:img.deco.right {:src "images/deco-right.png" :border "0"}]])) + + +(defmethod render-slide :opensource + [{:keys [navigate] :as props}] + (mf/html + [:div.modal-container.onboarding.black + [:div.modal-left + [:img {:src "images/open-source.svg" :border "0" :alt "Open Source"}]] + [:div.modal-right + [:div.modal-title + [:h2 "Open Source Contributor?"]] + [:div.modal-content + [:p "Penpot is Open Source, made by and for the community. If you want to collaborate, you are more than welcome!"] + [:p "You can access the " [:a {:href "https://github.com/penpot" :target "_blank"} "project on github"] " and follow the contribution instructions :)"]] + [:div.modal-navigation + [:button.btn-secondary {:on-click #(navigate :feature1)} "Continue"]]]])) + +(defmethod render-slide :feature1 + [{:keys [navigate skip] :as props}] + (mf/html + [:div.modal-container.onboarding.feature + [:div.modal-left + [:img {:src "images/on-design.gif" :border "0" :alt "Create designs"}]] + [:div.modal-right + [:div.modal-title + [:h2 "Design libraries, styles and components"]] + [:div.modal-content + [:p "Create beautiful user interfaces in collaboration with all team members."] + [:p "Maintain consistency at scale with components, libraries and design systems."]] + [:div.modal-navigation + [:button.btn-secondary {:on-click #(navigate :feature2)} "Continue"] + [:span.skip {:on-click skip} "Skip"] + [:ul.step-dots + [:li.current] + [:li] + [:li] + [:li]]]]])) + +(defmethod render-slide :feature2 + [{:keys [navigate skip] :as props}] + (mf/html + [:div.modal-container.onboarding.feature + [:div.modal-left + [:img {:src "images/on-proto.gif" :border "0" :alt "Interactive prototypes"}]] + [:div.modal-right + [:div.modal-title + [:h2 "Bring your designs to life with interactions"]] + [:div.modal-content + [:p "Create rich interactions to mimic the product behaviour."] + [:p "Share to stakeholders, present proposals to your team and start user testing with your designs, all in one place."]] + [:div.modal-navigation + [:button.btn-secondary {:on-click #(navigate :feature3)} "Continue"] + [:span.skip {:on-click skip} "Skip"] + [:ul.step-dots + [:li] + [:li.current] + [:li] + [:li]]]]])) + +(defmethod render-slide :feature3 + [{:keys [navigate skip] :as props}] + (mf/html + [:div.modal-container.onboarding.feature + [:div.modal-left + [:img {:src "images/on-feed.gif" :border "0" :alt "Get feedback"}]] + [:div.modal-right + [:div.modal-title + [:h2 "Get feedback, present and share your work"]] + [:div.modal-content + [:p "All team members working simultaneously with real time design multiplayer and centralised comments, ideas and feedback right over the designs."]] + [:div.modal-navigation + [:button.btn-secondary {:on-click #(navigate :feature4)} "Continue"] + [:span.skip {:on-click skip} "Skip"] + [:ul.step-dots + [:li] + [:li] + [:li.current] + [:li]]]]])) + +(defmethod render-slide :feature4 + [{:keys [navigate skip] :as props}] + (mf/html + [:div.modal-container.onboarding.feature + [:div.modal-left + [:img {:src "images/on-handoff.gif" :border "0" :alt "Handoff and lowcode"}]] + [:div.modal-right + [:div.modal-title + [:h2 "One shared source of truth"]] + [:div.modal-content + [:p "Sync the design and code of all your components and styles and get code snippets."] + [:p "Get and provide code specifications like markup (SVG, HTML) or styles (CSS, Less, Stylus…)."]] + [:div.modal-navigation + [:button.btn-secondary {:on-click skip} "Continue"] + [:span.skip {:on-click skip} "Skip"] + [:ul.step-dots + [:li] + [:li] + [:li] + [:li.current]]]]])) + +(mf/defc onboarding-modal + {::mf/register modal/components + ::mf/register-as :onboarding} + [props] + (let [slide (mf/use-state :start) + klass (mf/use-state "fadeInDown") + + navigate + (mf/use-callback #(reset! slide %)) + + skip + (mf/use-callback + (st/emitf (modal/hide) + (modal/show {:type :onboarding-team}) + (du/mark-onboarding-as-viewed)))] + + (mf/use-layout-effect + (mf/deps @slide) + (fn [] + (when (not= :start @slide) + (reset! klass "fadeIn")) + (let [sem (tm/schedule 300 #(reset! klass nil))] + (fn [] + (reset! klass nil) + (tm/dispose! sem))))) + + [:div.modal-overlay + [:div.animated {:class @klass} + (render-slide + (assoc props + :slide @slide + :navigate navigate + :skip skip))]])) + +(s/def ::name ::us/not-empty-string) +(s/def ::team-form + (s/keys :req-un [::name])) + +(defn- on-success + [form response] + (st/emit! (modal/hide) + (rt/nav :dashboard-projects {:team-id (:id response)}))) + +(defn- on-error + [form response] + (st/emit! (dm/error "Error on creating team."))) + +(defn- on-submit + [form event] + (let [mdata {:on-success (partial on-success form) + :on-error (partial on-error form)} + params {:name (get-in @form [:clean-data :name])}] + (st/emit! (dd/create-team (with-meta params mdata))))) + +(mf/defc onboarding-team-modal + {::mf/register modal/components + ::mf/register-as :onboarding-team} + [props] + (let [close (mf/use-fn (st/emitf (modal/hide))) + form (fm/use-form :spec ::team-form + :initial {}) + + on-submit + (mf/use-callback (partial on-submit form))] + [:div.modal-overlay + [:div.modal-container.onboarding.final.animated.fadeInUp + [:div.modal-left + [:img {:src "images/onboarding-team.jpg" :border "0" :alt "Create a team"}] + [:h2 "Create a team"] + [:p "Are you working with someone? Create a team to work together on projects and share design assets."] + + [:& fm/form {:form form + :on-submit on-submit} + [:& fm/input {:type "text" + :name :name + :label "Enter new team name"}] + [:& fm/submit-button + {:label "Create team"}]]] + [:div.modal-right + [:img {:src "images/onboarding-start.jpg" :border "0" :alt "Start designing"}] + [:h2 "Start designing"] + [:p "Jump right away into Penpot and start designing by your own. You will still have the chance to create teams later."] + [:button.btn-primary.btn-large {:on-click close} "Start right away"]] + + + [:img.deco {:src "images/deco-left.png" :border "0"}] + [:img.deco.right {:src "images/deco-right.png" :border "0"}]]])) + diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 2095bae52b..1dad84d487 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -29,6 +29,7 @@ [e] (.-target e)) + (defn classnames [& params] (assert (even? (count params))) @@ -39,6 +40,7 @@ [] (partition 2 params)))) + ;; --- New methods (defn get-element-by-class diff --git a/frontend/src/app/util/timers.cljs b/frontend/src/app/util/timers.cljs index 1861613449..a7afaff2b4 100644 --- a/frontend/src/app/util/timers.cljs +++ b/frontend/src/app/util/timers.cljs @@ -21,6 +21,10 @@ (-dispose [_] (js/clearTimeout sem)))))) +(defn dispose! + [v] + (rx/dispose! v)) + (defn asap [f] (-> (p/resolved nil) From 6cb2f1663eb3f2a16b687cc8466d231daee1a592 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Dec 2020 17:26:04 +0100 Subject: [PATCH 192/195] :fire: Remove unused code. --- backend/src/app/db.clj | 9 --------- backend/src/app/tasks/remove_media.clj | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj index a40318a990..50b492800e 100644 --- a/backend/src/app/db.clj +++ b/backend/src/app/db.clj @@ -219,15 +219,6 @@ :else (ex/raise :type :not-implemented))) -(defn decode-pgobject - [^PGobject obj] - (let [typ (.getType obj) - val (.getValue obj)] - (if (or (= typ "json") - (= typ "jsonb")) - (json/read-str val) - val))) - (defn decode-json-pgobject [^PGobject o] (let [typ (.getType o) diff --git a/backend/src/app/tasks/remove_media.clj b/backend/src/app/tasks/remove_media.clj index a517aadd2b..2d1a528582 100644 --- a/backend/src/app/tasks/remove_media.clj +++ b/backend/src/app/tasks/remove_media.clj @@ -76,7 +76,7 @@ [_task] (letfn [(decode-row [{:keys [data] :as row}] (cond-> row - (db/pgobject? data) (assoc :data (db/decode-pgobject data)))) + (db/pgobject? data) (assoc :data (db/decode-json-pgobject data)))) (retrieve-items [conn] (->> (db/exec! conn [sql:retrieve-peding-to-delete 10]) (map decode-row) From 83519e85133cb69fceec7d9212ea9a465b3ac11d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 10 Dec 2020 11:26:11 +0100 Subject: [PATCH 193/195] :bug: Fixes scroll and others --- frontend/resources/styles/main/partials/sidebar.scss | 2 +- frontend/src/app/main/ui/shapes/shape.cljs | 5 ++++- frontend/src/app/main/ui/workspace/viewport.cljs | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index 676219e9af..f474c2364f 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -171,7 +171,7 @@ $width-settings-bar: 16rem; .tool-window-content { display: flex; flex-direction: column; - // overflow-y: auto; + overflow-y: auto; height: 100%; width: 100%; } diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index cfe637c693..62760374e6 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -25,11 +25,14 @@ children (obj/get props "children") render-id (mf/use-memo #(str (uuid/next))) filter-id (str "filter_" render-id) + styles (cond-> (obj/new) + (:blocked shape) (obj/set! "pointerEvents" "none")) group-props (-> (obj/clone props) (obj/without ["shape" "children"]) (obj/set! "id" (str "shape-" (:id shape))) (obj/set! "className" (str "shape " (:type shape))) - (obj/set! "filter" (filters/filter-str filter-id shape)))] + (obj/set! "filter" (filters/filter-str filter-id shape)) + (obj/set! "style" styles))] [:& (mf/provider muc/render-ctx) {:value render-id} [:> :g group-props [:defs diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 0a3b821952..1a97b663e6 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -233,7 +233,9 @@ ctrl? (kbd/ctrl? event) shift? (kbd/shift? event) alt? (kbd/alt? event)] - (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) + (when (= 1 (.-which event)) + (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))) + (cond (and (= 1 (.-which event)) (not edition)) (if drawing-tool @@ -259,7 +261,8 @@ ctrl? (kbd/ctrl? event) shift? (kbd/shift? event) alt? (kbd/alt? event)] - (st/emit! (ms/->MouseEvent :up ctrl? shift? alt?)) + (when (= 1 (.-which event)) + (st/emit! (ms/->MouseEvent :up ctrl? shift? alt?))) (when (= 2 (.-which event)) (do From 45882ba6a1c1b13b5d30620d0d10773d4c9e47ed Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 10 Dec 2020 13:56:33 +0100 Subject: [PATCH 194/195] :recycle: Refactor pages namespaces --- backend/src/app/services/mutations/files.clj | 2 +- backend/src/app/services/queries/files.clj | 2 +- backend/src/app/services/queries/profile.clj | 1 - backend/src/app/tasks/trim_file.clj | 2 +- common/app/common/geom/align.cljc | 2 +- common/app/common/geom/shapes.cljc | 9 + common/app/common/pages.cljc | 1206 +---------------- common/app/common/pages/changes.cljc | 415 ++++++ common/app/common/pages/common.cljc | 56 + .../helpers.cljc} | 2 +- common/app/common/pages/init.cljc | 143 ++ .../migrations.cljc} | 11 +- common/app/common/pages/spec.cljc | 571 ++++++++ common/app/common/spec.cljc | 6 +- frontend/src/app/main/data/colors.cljs | 24 +- frontend/src/app/main/data/comments.cljs | 1 - frontend/src/app/main/data/viewer.cljs | 3 +- frontend/src/app/main/data/workspace.cljs | 27 +- .../src/app/main/data/workspace/common.cljs | 9 +- .../app/main/data/workspace/drawing/box.cljs | 4 +- .../src/app/main/data/workspace/groups.cljs | 5 +- .../app/main/data/workspace/libraries.cljs | 11 +- .../data/workspace/libraries_helpers.cljs | 2 +- .../app/main/data/workspace/persistence.cljs | 1 - .../app/main/data/workspace/selection.cljs | 5 +- .../app/main/data/workspace/transforms.cljs | 19 +- frontend/src/app/main/exports.cljs | 7 +- frontend/src/app/main/refs.cljs | 9 +- frontend/src/app/main/store.cljs | 4 +- frontend/src/app/main/ui/handoff/render.cljs | 3 +- frontend/src/app/main/ui/render.cljs | 5 +- frontend/src/app/main/ui/viewer.cljs | 4 +- frontend/src/app/main/ui/viewer/shapes.cljs | 3 +- .../app/main/ui/workspace/sidebar/assets.cljs | 1 - .../app/main/ui/workspace/sidebar/layers.cljs | 5 +- .../workspace/sidebar/options/component.cljs | 10 +- .../ui/workspace/sidebar/options/group.cljs | 1 - .../sidebar/options/interactions.cljs | 4 +- frontend/src/app/worker/selection.cljs | 3 +- frontend/src/app/worker/snaps.cljs | 3 +- 40 files changed, 1354 insertions(+), 1247 deletions(-) create mode 100644 common/app/common/pages/changes.cljc create mode 100644 common/app/common/pages/common.cljc rename common/app/common/{pages_helpers.cljc => pages/helpers.cljc} (99%) create mode 100644 common/app/common/pages/init.cljc rename common/app/common/{pages_migrations.cljc => pages/migrations.cljc} (89%) create mode 100644 common/app/common/pages/spec.cljc diff --git a/backend/src/app/services/mutations/files.clj b/backend/src/app/services/mutations/files.clj index ff1d243967..17742805d4 100644 --- a/backend/src/app/services/mutations/files.clj +++ b/backend/src/app/services/mutations/files.clj @@ -11,7 +11,7 @@ (:require [app.common.exceptions :as ex] [app.common.pages :as cp] - [app.common.pages-migrations :as pmg] + [app.common.pages.migrations :as pmg] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cfg] diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj index 73dddf0769..82393375ed 100644 --- a/backend/src/app/services/queries/files.clj +++ b/backend/src/app/services/queries/files.clj @@ -10,7 +10,7 @@ (ns app.services.queries.files (:require [app.common.exceptions :as ex] - [app.common.pages-migrations :as pmg] + [app.common.pages.migrations :as pmg] [app.common.spec :as us] [app.db :as db] [app.services.queries :as sq] diff --git a/backend/src/app/services/queries/profile.clj b/backend/src/app/services/queries/profile.clj index db954905d7..9f73e7c883 100644 --- a/backend/src/app/services/queries/profile.clj +++ b/backend/src/app/services/queries/profile.clj @@ -23,7 +23,6 @@ (s/def ::email ::us/email) (s/def ::fullname ::us/string) -(s/def ::metadata any?) (s/def ::old-password ::us/string) (s/def ::password ::us/string) (s/def ::path ::us/string) diff --git a/backend/src/app/tasks/trim_file.clj b/backend/src/app/tasks/trim_file.clj index dd16f2fd00..56e81777cd 100644 --- a/backend/src/app/tasks/trim_file.clj +++ b/backend/src/app/tasks/trim_file.clj @@ -9,7 +9,7 @@ (ns app.tasks.trim-file (:require - [app.common.pages-migrations :as pmg] + [app.common.pages.migrations :as pmg] [app.config :as cfg] [app.db :as db] [app.tasks :as tasks] diff --git a/common/app/common/geom/align.cljc b/common/app/common/geom/align.cljc index 4cec0fdf54..f06bcb4bd4 100644 --- a/common/app/common/geom/align.cljc +++ b/common/app/common/geom/align.cljc @@ -19,7 +19,7 @@ (declare calc-align-pos) -;; Duplicated from pages-helpers to remove cyclic dependencies +;; Duplicated from pages/helpers to remove cyclic dependencies (defn- get-children [id objects] (let [shapes (vec (get-in objects [id :shapes]))] (if shapes diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 628dc43222..1ddb96bb4a 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -254,6 +254,15 @@ (assoc :selrect selrect :points points)))) +(defn rotation-modifiers + [center shape angle] + (let [displacement (let [shape-center (gco/center-shape shape)] + (-> (gmt/matrix) + (gmt/rotate angle center) + (gmt/rotate (- angle) shape-center)))] + {:rotation angle + :displacement displacement})) + ;; EXPORTS (d/export gco/center-shape) diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index cdec3e8df3..c2ad88592a 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -10,1141 +10,73 @@ (ns app.common.pages "A common (clj/cljs) functions and specs for pages." (:require - [clojure.spec.alpha :as s] [app.common.data :as d] - [app.common.pages-helpers :as cph] - [app.common.exceptions :as ex] - [app.common.geom.shapes :as gsh] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.spec :as us] - [app.common.uuid :as uuid])) - -(def file-version 4) -(def max-safe-int 9007199254740991) -(def min-safe-int -9007199254740991) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Page Transformation Changes -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; --- Specs - -(s/def ::frame-id uuid?) -(s/def ::id uuid?) -(s/def ::name string?) -(s/def ::page-id uuid?) -(s/def ::parent-id uuid?) -(s/def ::string string?) -(s/def ::type keyword?) -(s/def ::uuid uuid?) - -(s/def ::component-id uuid?) -(s/def ::component-file uuid?) -(s/def ::component-root? boolean?) -(s/def ::shape-ref uuid?) - -(s/def ::safe-integer ::us/safe-integer) -(s/def ::safe-number ::us/safe-number) - -(s/def :internal.matrix/a ::us/safe-number) -(s/def :internal.matrix/b ::us/safe-number) -(s/def :internal.matrix/c ::us/safe-number) -(s/def :internal.matrix/d ::us/safe-number) -(s/def :internal.matrix/e ::us/safe-number) -(s/def :internal.matrix/f ::us/safe-number) - -(s/def ::matrix - (s/and (s/keys :req-un [:internal.matrix/a - :internal.matrix/b - :internal.matrix/c - :internal.matrix/d - :internal.matrix/e - :internal.matrix/f]) - gmt/matrix?)) - - -(s/def :internal.point/x ::us/safe-number) -(s/def :internal.point/y ::us/safe-number) - -(s/def ::point - (s/and (s/keys :req-un [:internal.point/x - :internal.point/y]) - gpt/point?)) - -;; GRADIENTS - -(s/def :internal.gradient.stop/color ::string) -(s/def :internal.gradient.stop/opacity ::safe-number) -(s/def :internal.gradient.stop/offset ::safe-number) - -(s/def :internal.gradient/type #{:linear :radial}) -(s/def :internal.gradient/start-x ::safe-number) -(s/def :internal.gradient/start-y ::safe-number) -(s/def :internal.gradient/end-x ::safe-number) -(s/def :internal.gradient/end-y ::safe-number) -(s/def :internal.gradient/width ::safe-number) - -(s/def :internal.gradient/stop - (s/keys :req-un [:internal.gradient.stop/color - :internal.gradient.stop/opacity - :internal.gradient.stop/offset])) - -(s/def :internal.gradient/stops - (s/coll-of :internal.gradient/stop :kind vector?)) - -(s/def ::gradient - (s/keys :req-un [:internal.gradient/type - :internal.gradient/start-x - :internal.gradient/start-y - :internal.gradient/end-x - :internal.gradient/end-y - :internal.gradient/width - :internal.gradient/stops])) - - -;;; COLORS - -(s/def :internal.color/name ::string) -(s/def :internal.color/value (s/nilable ::string)) -(s/def :internal.color/color (s/nilable ::string)) -(s/def :internal.color/opacity (s/nilable ::safe-number)) -(s/def :internal.color/gradient (s/nilable ::gradient)) - -(s/def ::color - (s/keys :opt-un [::id - :internal.color/name - :internal.color/value - :internal.color/color - :internal.color/opacity - :internal.color/gradient])) - - - -;;; SHADOW EFFECT - -(s/def :internal.shadow/id uuid?) -(s/def :internal.shadow/style #{:drop-shadow :inner-shadow}) -(s/def :internal.shadow/color ::color) -(s/def :internal.shadow/offset-x ::safe-number) -(s/def :internal.shadow/offset-y ::safe-number) -(s/def :internal.shadow/blur ::safe-number) -(s/def :internal.shadow/spread ::safe-number) -(s/def :internal.shadow/hidden boolean?) - -(s/def :internal.shadow/shadow - (s/keys :req-un [:internal.shadow/id - :internal.shadow/style - :internal.shadow/color - :internal.shadow/offset-x - :internal.shadow/offset-y - :internal.shadow/blur - :internal.shadow/spread - :internal.shadow/hidden])) - -(s/def ::shadow - (s/coll-of :internal.shadow/shadow :kind vector?)) - - -;;; BLUR EFFECT - -(s/def :internal.blur/id uuid?) -(s/def :internal.blur/type #{:layer-blur}) -(s/def :internal.blur/value ::safe-number) -(s/def :internal.blur/hidden boolean?) - -(s/def ::blur - (s/keys :req-un [:internal.blur/id - :internal.blur/type - :internal.blur/value - :internal.blur/hidden])) - -;; Page Options -(s/def :internal.page.grid.color/value string?) -(s/def :internal.page.grid.color/opacity ::safe-number) - -(s/def :internal.page.grid/size ::safe-integer) -(s/def :internal.page.grid/color - (s/keys :req-un [:internal.page.grid.color/value - :internal.page.grid.color/opacity])) - -(s/def :internal.page.grid/type #{:stretch :left :center :right}) -(s/def :internal.page.grid/item-length (s/nilable ::safe-integer)) -(s/def :internal.page.grid/gutter (s/nilable ::safe-integer)) -(s/def :internal.page.grid/margin (s/nilable ::safe-integer)) - -(s/def :internal.page.grid/square - (s/keys :req-un [:internal.page.grid/size - :internal.page.grid/color])) - -(s/def :internal.page.grid/column - (s/keys :req-un [:internal.page.grid/size - :internal.page.grid/color - :internal.page.grid/type - :internal.page.grid/item-length - :internal.page.grid/gutter - :internal.page.grid/margin])) - -(s/def :internal.page.grid/row :internal.page.grid/column) - -(s/def :internal.page.options/background string?) -(s/def :internal.page.options/saved-grids - (s/keys :req-un [:internal.page.grid/square - :internal.page.grid/row - :internal.page.grid/column])) - -(s/def :internal.page/options - (s/keys :opt-un [:internal.page.options/background])) - -;; Interactions - -(s/def :internal.shape.interaction/event-type #{:click}) ; In the future we will have more options -(s/def :internal.shape.interaction/action-type #{:navigate}) -(s/def :internal.shape.interaction/destination ::uuid) - -(s/def :internal.shape/interaction - (s/keys :req-un [:internal.shape.interaction/event-type - :internal.shape.interaction/action-type - :internal.shape.interaction/destination])) - -(s/def :internal.shape/interactions - (s/coll-of :internal.shape/interaction :kind vector?)) - -;; Page Data related -(s/def :internal.shape/blocked boolean?) -(s/def :internal.shape/collapsed boolean?) -(s/def :internal.shape/content any?) - -(s/def :internal.shape/fill-color string?) -(s/def :internal.shape/fill-opacity ::safe-number) -(s/def :internal.shape/fill-color-gradient (s/nilable ::gradient)) -(s/def :internal.shape/fill-color-ref-file (s/nilable uuid?)) -(s/def :internal.shape/fill-color-ref-id (s/nilable uuid?)) - -(s/def :internal.shape/font-family string?) -(s/def :internal.shape/font-size ::safe-integer) -(s/def :internal.shape/font-style string?) -(s/def :internal.shape/font-weight string?) -(s/def :internal.shape/hidden boolean?) -(s/def :internal.shape/letter-spacing ::safe-number) -(s/def :internal.shape/line-height ::safe-number) -(s/def :internal.shape/locked boolean?) -(s/def :internal.shape/page-id uuid?) -(s/def :internal.shape/proportion ::safe-number) -(s/def :internal.shape/proportion-lock boolean?) -(s/def :internal.shape/rx ::safe-number) -(s/def :internal.shape/ry ::safe-number) -(s/def :internal.shape/stroke-color string?) -(s/def :internal.shape/stroke-color-gradient (s/nilable ::gradient)) -(s/def :internal.shape/stroke-color-ref-file (s/nilable uuid?)) -(s/def :internal.shape/stroke-color-ref-id (s/nilable uuid?)) -(s/def :internal.shape/stroke-opacity ::safe-number) -(s/def :internal.shape/stroke-style #{:solid :dotted :dashed :mixed :none}) -(s/def :internal.shape/stroke-width ::safe-number) -(s/def :internal.shape/stroke-alignment #{:center :inner :outer}) -(s/def :internal.shape/text-align #{"left" "right" "center" "justify"}) -(s/def :internal.shape/x ::safe-number) -(s/def :internal.shape/y ::safe-number) -(s/def :internal.shape/cx ::safe-number) -(s/def :internal.shape/cy ::safe-number) -(s/def :internal.shape/width ::safe-number) -(s/def :internal.shape/height ::safe-number) -(s/def :internal.shape/index integer?) -(s/def :internal.shape/shadow ::shadow) -(s/def :internal.shape/blur ::blur) - -(s/def :internal.shape/x1 ::safe-number) -(s/def :internal.shape/y1 ::safe-number) -(s/def :internal.shape/x2 ::safe-number) -(s/def :internal.shape/y2 ::safe-number) - -(s/def :internal.shape.export/suffix string?) -(s/def :internal.shape.export/scale ::safe-number) -(s/def :internal.shape/export - (s/keys :req-un [::type - :internal.shape.export/suffix - :internal.shape.export/scale])) - -(s/def :internal.shape/exports - (s/coll-of :internal.shape/export :kind vector?)) - -(s/def :internal.shape/selrect - (s/keys :req-un [:internal.shape/x - :internal.shape/y - :internal.shape/x1 - :internal.shape/y1 - :internal.shape/x2 - :internal.shape/y2 - :internal.shape/width - :internal.shape/height])) - -(s/def :internal.shape/points - (s/every ::point :kind vector?)) - -(s/def :internal.shape/shapes - (s/every uuid? :kind vector?)) - -(s/def :internal.shape/transform ::matrix) -(s/def :internal.shape/transform-inverse ::matrix) - -(s/def ::shape-attrs - (s/keys :opt-un [:internal.shape/selrect - :internal.shape/points - :internal.shape/blocked - :internal.shape/collapsed - :internal.shape/content - :internal.shape/fill-color - :internal.shape/fill-opacity - :internal.shape/fill-color-gradient - :internal.shape/fill-color-ref-file - :internal.shape/fill-color-ref-id - :internal.shape/font-family - :internal.shape/font-size - :internal.shape/font-style - :internal.shape/font-weight - :internal.shape/hidden - :internal.shape/letter-spacing - :internal.shape/line-height - :internal.shape/locked - :internal.shape/proportion - :internal.shape/proportion-lock - :internal.shape/rx - :internal.shape/ry - :internal.shape/x - :internal.shape/y - :internal.shape/exports - :internal.shape/shapes - :internal.shape/stroke-color - :internal.shape/stroke-color-ref-file - :internal.shape/stroke-color-ref-id - :internal.shape/stroke-opacity - :internal.shape/stroke-style - :internal.shape/stroke-width - :internal.shape/stroke-alignment - :internal.shape/text-align - :internal.shape/transform - :internal.shape/transform-inverse - :internal.shape/width - :internal.shape/height - :internal.shape/interactions - :internal.shape/masked-group? - :internal.shape/shadow - :internal.shape/blur])) - -(def component-sync-attrs {:fill-color :fill-group - :fill-opacity :fill-group - :fill-color-gradient :fill-group - :fill-color-ref-file :fill-group - :fill-color-ref-id :fill-group - :content :content-group - :font-family :text-font-group - :font-size :text-font-group - :font-style :text-font-group - :font-weight :text-font-group - :letter-spacing :text-display-group - :line-height :text-display-group - :text-align :text-display-group - :stroke-color :stroke-group - :stroke-color-gradient :stroke-group - :stroke-color-ref-file :stroke-group - :stroke-color-ref-id :stroke-group - :stroke-opacity :stroke-group - :stroke-style :stroke-group - :stroke-width :stroke-group - :stroke-alignment :stroke-group - :rx :radius-group - :ry :radius-group - :selrect :geometry-group - :points :geometry-group - :locked :geometry-group - :proportion :geometry-group - :proportion-lock :geometry-group - :x :geometry-group - :y :geometry-group - :width :geometry-group - :height :geometry-group - :transform :geometry-group - :transform-inverse :geometry-group - :shadow :shadow-group - :blur :blur-group - :masked-group? :mask-group}) - ;; shapes-group is handled differently - -(s/def ::minimal-shape - (s/keys :req-un [::type ::name] - :opt-un [::id])) - -(s/def ::shape - (s/and ::minimal-shape ::shape-attrs - (s/keys :opt-un [::id - ::component-id - ::component-file - ::component-root? - ::shape-ref]))) - -(s/def :internal.page/objects (s/map-of uuid? ::shape)) - -(s/def ::page - (s/keys :req-un [::id - ::name - :internal.page/options - :internal.page/objects])) - - -(s/def ::recent-color - (s/keys :opt-un [:internal.color/value - :internal.color/color - :internal.color/opacity - :internal.color/gradient])) - -(s/def :internal.media-object/name ::string) -(s/def :internal.media-object/path ::string) -(s/def :internal.media-object/width ::safe-integer) -(s/def :internal.media-object/height ::safe-integer) -(s/def :internal.media-object/mtype ::string) -(s/def :internal.media-object/thumb-path ::string) -(s/def :internal.media-object/thumb-width ::safe-integer) -(s/def :internal.media-object/thumb-height ::safe-integer) -(s/def :internal.media-object/thumb-mtype ::string) - -(s/def ::media-object - (s/keys :req-un [::id ::name - :internal.media-object/name - :internal.media-object/path - :internal.media-object/width - :internal.media-object/height - :internal.media-object/mtype - :internal.media-object/thumb-path])) - -(s/def ::media-object-update - (s/keys :req-un [::id] - :req-opt [::name - :internal.media-object/name - :internal.media-object/path - :internal.media-object/width - :internal.media-object/height - :internal.media-object/mtype - :internal.media-object/thumb-path])) - -(s/def :internal.file/colors - (s/map-of ::uuid ::color)) - -(s/def :internal.file/recent-colors - (s/coll-of ::recent-color :kind vector?)) - -(s/def :internal.typography/id ::id) -(s/def :internal.typography/name ::string) -(s/def :internal.typography/font-id ::string) -(s/def :internal.typography/font-family ::string) -(s/def :internal.typography/font-variant-id ::string) -(s/def :internal.typography/font-size ::string) -(s/def :internal.typography/font-weight ::string) -(s/def :internal.typography/font-style ::string) -(s/def :internal.typography/line-height ::string) -(s/def :internal.typography/letter-spacing ::string) -(s/def :internal.typography/text-transform ::string) - -(s/def ::typography - (s/keys :req-un [:internal.typography/id - :internal.typography/name - :internal.typography/font-id - :internal.typography/font-family - :internal.typography/font-variant-id - :internal.typography/font-size - :internal.typography/font-weight - :internal.typography/font-style - :internal.typography/line-height - :internal.typography/letter-spacing - :internal.typography/text-transform])) - -(s/def :internal.file/pages - (s/coll-of ::uuid :kind vector?)) - -(s/def :internal.file/media - (s/map-of ::uuid ::media-object)) - -(s/def :internal.file/pages-index - (s/map-of ::uuid ::page)) - -(s/def ::data - (s/keys :req-un [:internal.file/pages-index - :internal.file/pages] - :opt-un [:internal.file/colors - :internal.file/recent-colors - :internal.file/media])) - -(s/def :internal.container/type #{:page :component}) - -(s/def ::container - (s/keys :req-un [:internal.container/type - ::id - ::name - :internal.page/objects])) - -(defmulti operation-spec :type) - -(s/def :internal.operations.set/attr keyword?) -(s/def :internal.operations.set/val any?) -(s/def :internal.operations.set/touched - (s/nilable (s/every keyword? :kind set?))) - -(defmethod operation-spec :set [_] - (s/keys :req-un [:internal.operations.set/attr - :internal.operations.set/val])) - -(defmethod operation-spec :set-touched [_] - (s/keys :req-un [:internal.operations.set/touched])) - -(defmulti change-spec :type) - -(s/def :internal.changes.set-option/option any?) -(s/def :internal.changes.set-option/value any?) - -(defmethod change-spec :set-option [_] - (s/keys :req-un [:internal.changes.set-option/option - :internal.changes.set-option/value])) - -(s/def :internal.changes.add-obj/obj ::shape) - -(defn- valid-container-id-frame? - [o] - (or (and (contains? o :page-id) - (not (contains? o :component-id)) - (some? (:frame-id o))) - (and (contains? o :component-id) - (not (contains? o :page-id)) - (nil? (:frame-id o))))) - -(defn- valid-container-id? - [o] - (or (and (contains? o :page-id) - (not (contains? o :component-id))) - (and (contains? o :component-id) - (not (contains? o :page-id))))) - -(defmethod change-spec :add-obj [_] - (s/and (s/keys :req-un [::id :internal.changes.add-obj/obj] - :opt-un [::page-id ::component-id ::parent-id ::frame-id]) - valid-container-id-frame?)) - -(s/def ::operation (s/multi-spec operation-spec :type)) -(s/def ::operations (s/coll-of ::operation)) - -(defmethod change-spec :mod-obj [_] - (s/and (s/keys :req-un [::id ::operations] - :opt-un [::page-id ::component-id]) - valid-container-id?)) - -(defmethod change-spec :del-obj [_] - (s/and (s/keys :req-un [::id] - :opt-un [::page-id ::component-id]) - valid-container-id?)) - -(s/def :internal.changes.reg-objects/shapes - (s/coll-of uuid? :kind vector?)) - -(defmethod change-spec :reg-objects [_] - (s/and (s/keys :req-un [:internal.changes.reg-objects/shapes] - :opt-un [::page-id ::component-id]) - valid-container-id?)) - -(defmethod change-spec :mov-objects [_] - (s/and (s/keys :req-un [::parent-id :internal.shape/shapes] - :opt-un [::page-id ::component-id ::index]) - valid-container-id?)) - -(defmethod change-spec :add-page [_] - (s/or :empty (s/keys :req-un [::id ::name]) - :complete (s/keys :req-un [::page]))) - -(defmethod change-spec :mod-page [_] - (s/keys :req-un [::id ::name])) - -(defmethod change-spec :del-page [_] - (s/keys :req-un [::id])) - -(defmethod change-spec :mov-page [_] - (s/keys :req-un [::id ::index])) - -(defmethod change-spec :add-color [_] - (s/keys :req-un [::color])) - -(defmethod change-spec :mod-color [_] - (s/keys :req-un [::color])) - -(defmethod change-spec :del-color [_] - (s/keys :req-un [::id])) - -(s/def :internal.changes.add-recent-color/color ::recent-color) - -(defmethod change-spec :add-recent-color [_] - (s/keys :req-un [:internal.changes.add-recent-color/color])) - -(s/def :internal.changes.media/object ::media-object) - -(defmethod change-spec :add-media [_] - (s/keys :req-un [:internal.changes.media/object])) - -(s/def :internal.changes.media.mod/object ::media-object-update) - -(defmethod change-spec :mod-media [_] - (s/keys :req-un [:internal.changes.media.mod/object])) - -(defmethod change-spec :del-media [_] - (s/keys :req-un [::id])) - -(s/def :internal.changes.add-component/shapes - (s/coll-of ::shape)) - -(defmethod change-spec :add-component [_] - (s/keys :req-un [::id ::name :internal.changes.add-component/shapes])) - -(defmethod change-spec :mod-component [_] - (s/keys :req-un [::id] - :opt-un [::name :internal.changes.add-component/shapes])) - -(defmethod change-spec :del-component [_] - (s/keys :req-un [::id])) - -(s/def :internal.changes.typography/typography ::typography) - -(defmethod change-spec :add-typography [_] - (s/keys :req-un [:internal.changes.typography/typography])) - -(defmethod change-spec :mod-typography [_] - (s/keys :req-un [:internal.changes.typography/typography])) - -(defmethod change-spec :del-typography [_] - (s/keys :req-un [:internal.typography/id])) - -(s/def ::change (s/multi-spec change-spec :type)) -(s/def ::changes (s/coll-of ::change)) - -(def root uuid/zero) - -(def empty-page-data - {:options {} - :name "Page" - :objects - {root - {:id root - :type :frame - :name "Root Frame"}}}) - -(def empty-file-data - {:version file-version - :pages [] - :pages-index {}}) - -(def default-color "#b1b2b5") ;; $color-gray-20 -(def default-shape-attrs - {:fill-color default-color - :fill-opacity 1}) - -(def default-frame-attrs - {:frame-id uuid/zero - :fill-color "#ffffff" - :fill-opacity 1 - :shapes []}) - -(def ^:private minimal-shapes - [{:type :rect - :name "Rect" - :fill-color default-color - :fill-opacity 1 - :stroke-style :none - :stroke-alignment :center - :stroke-width 0 - :stroke-color "#000000" - :stroke-opacity 0 - :rx 0 - :ry 0} - - {:type :image} - - {:type :icon} - - {:type :circle - :name "Circle" - :fill-color default-color - :fill-opacity 1 - :stroke-style :none - :stroke-alignment :center - :stroke-width 0 - :stroke-color "#000000" - :stroke-opacity 0} - - {:type :path - :name "Path" - :fill-color "#000000" - :fill-opacity 0 - :stroke-style :solid - :stroke-alignment :center - :stroke-width 2 - :stroke-color "#000000" - :stroke-opacity 1} - - {:type :frame - :name "Artboard" - :fill-color "#ffffff" - :fill-opacity 1 - :stroke-style :none - :stroke-alignment :center - :stroke-width 0 - :stroke-color "#000000" - :stroke-opacity 0} - - {:type :text - :name "Text" - :content nil}]) - -(defn make-minimal-shape - [type] - (let [type (cond (= type :curve) :path - :else type) - shape (d/seek #(= type (:type %)) minimal-shapes)] - (when-not shape - (ex/raise :type :assertion - :code :shape-type-not-implemented - :context {:type type})) - - (cond-> shape - :always - (assoc :id (uuid/next)) - - (not= :path (:type shape)) - (assoc :x 0 - :y 0 - :width 1 - :height 1 - :selrect {:x 0 - :y 0 - :x1 0 - :y1 0 - :x2 1 - :y2 1 - :width 1 - :height 1})))) - -(defn make-minimal-group - [frame-id selection-rect group-name] - {:id (uuid/next) - :type :group - :name group-name - :shapes [] - :frame-id frame-id - :x (:x selection-rect) - :y (:y selection-rect) - :width (:width selection-rect) - :height (:height selection-rect)}) - -(defn make-file-data - ([] (make-file-data (uuid/next))) - ([id] - (let [ - pd (assoc empty-page-data - :id id - :name "Page-1")] - (-> empty-file-data - (update :pages conj id) - (update :pages-index assoc id pd))))) - -;; --- Changes Processing Impl - -(defmulti process-change (fn [_ change] (:type change))) -(defmulti process-operation (fn [_ op] (:type op))) - -(defn process-changes - [data items] - (->> (us/verify ::changes items) - (reduce #(do - ;; (prn "process-change" (:type %2) (:id %2)) - (or (process-change %1 %2) %1)) - data))) - -(defmethod process-change :set-option - [data {:keys [page-id option value]}] - (d/update-in-when data [:pages-index page-id] - (fn [data] - (let [path (if (seqable? option) option [option])] - (if value - (assoc-in data (into [:options] path) value) - (assoc data :options (d/dissoc-in (:options data) path))))))) - -(defmethod process-change :add-obj - [data {:keys [id obj page-id component-id frame-id parent-id - index ignore-touched]}] - (letfn [(update-fn [data] - (let [parent-id (or parent-id frame-id) - objects (:objects data) - obj (assoc obj - :frame-id frame-id - :parent-id parent-id - :id id)] - (if (and (or (nil? parent-id) (contains? objects parent-id)) - (or (nil? frame-id) (contains? objects frame-id))) - (-> data - (update :objects assoc id obj) - (update-in [:objects parent-id :shapes] - (fn [shapes] - (let [shapes (or shapes [])] - (cond - (some #{id} shapes) - shapes - - (nil? index) - (if (= :frame (:type obj)) - (d/concat [id] shapes) - (conj shapes id)) - - :else - (cph/insert-at-index shapes index [id]))))) - - (cond-> (and (:shape-ref (get-in data [:objects parent-id])) - (not= parent-id frame-id) - (not ignore-touched)) - (update-in [:objects parent-id :touched] - cph/set-touched-group :shapes-group))) - data)))] - (if page-id - (d/update-in-when data [:pages-index page-id] update-fn) - (d/update-in-when data [:components component-id] update-fn)))) - -(defmethod process-change :mod-obj - [data {:keys [id page-id component-id operations]}] - (let [update-fn (fn [objects] - (if-let [obj (get objects id)] - (let [result (reduce process-operation obj operations)] - (us/verify ::shape result) - (assoc objects id result)) - objects))] - (if page-id - (d/update-in-when data [:pages-index page-id :objects] update-fn) - (d/update-in-when data [:components component-id :objects] update-fn)))) - -(defmethod process-change :del-obj - [data {:keys [page-id component-id id ignore-touched]}] - (letfn [(delete-object [objects id] - (if-let [target (get objects id)] - (let [parent-id (cph/get-parent id objects) - frame-id (:frame-id target) - parent (get objects parent-id) - objects (dissoc objects id)] - (cond-> objects - (and (not= parent-id frame-id) - (= :group (:type parent))) - (update-in [parent-id :shapes] (fn [s] (filterv #(not= % id) s))) - - (and (:shape-ref parent) (not ignore-touched)) - (update-in [parent-id :touched] cph/set-touched-group :shapes-group) - - (contains? objects frame-id) - (update-in [frame-id :shapes] (fn [s] (filterv #(not= % id) s))) - - (seq (:shapes target)) ; Recursive delete all - ; dependend objects - (as-> $ (reduce delete-object $ (:shapes target))))) - objects))] - (if page-id - (d/update-in-when data [:pages-index page-id :objects] delete-object id) - (d/update-in-when data [:components component-id :objects] delete-object id)))) - -(defn rotation-modifiers - [center shape angle] - (let [displacement (let [shape-center (gsh/center-shape shape)] - (-> (gmt/matrix) - (gmt/rotate angle center) - (gmt/rotate (- angle) shape-center)))] - {:rotation angle - :displacement displacement})) - -;; reg-objects operation "regenerates" the values for the parent groups -(defmethod process-change :reg-objects - [data {:keys [page-id component-id shapes]}] - (letfn [(reg-objects [objects] - (reduce #(update %1 %2 update-group %1) objects - (sequence (comp - (mapcat #(cons % (cph/get-parents % objects))) - (map #(get objects %)) - (filter #(= (:type %) :group)) - (map :id) - (distinct)) - shapes))) - (update-group [group objects] - (let [children (->> group :shapes (map #(get objects %)))] - (if (:masked-group? group) - (let [mask (first children)] - (-> group - (merge (select-keys mask [:selrect :points])) - (assoc :x (-> mask :selrect :x) - :y (-> mask :selrect :y) - :width (-> mask :selrect :width) - :height (-> mask :selrect :height)))) - (gsh/update-group-selrect group children))))] - - (if page-id - (d/update-in-when data [:pages-index page-id :objects] reg-objects) - (d/update-in-when data [:components component-id :objects] reg-objects)))) - -(defmethod process-change :mov-objects - [data {:keys [parent-id shapes index page-id component-id ignore-touched]}] - (letfn [(is-valid-move? [objects shape-id] - (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] - (and (not (invalid-targets parent-id)) - (cph/valid-frame-target shape-id parent-id objects)))) - - (insert-items [prev-shapes index shapes] - (let [prev-shapes (or prev-shapes [])] - (if index - (cph/insert-at-index prev-shapes index shapes) - (cph/append-at-the-end prev-shapes shapes)))) - - (check-insert-items [prev-shapes parent index shapes] - (if-not (:masked-group? parent) - (insert-items prev-shapes index shapes) - ;; For masked groups, the first shape is the mask - ;; and it cannot be moved. - (let [mask-id (first prev-shapes) - other-ids (rest prev-shapes) - not-mask-shapes (strip-id shapes mask-id) - new-index (if (nil? index) nil (max (dec index) 0)) - new-shapes (insert-items other-ids new-index not-mask-shapes)] - (d/concat [mask-id] new-shapes)))) - - (strip-id [coll id] - (filterv #(not= % id) coll)) - - (add-to-parent [parent index shapes] - (cond-> parent - true - (update :shapes check-insert-items parent index shapes) - - (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) - (update :touched cph/set-touched-group :shapes-group))) - - (remove-from-old-parent [cpindex objects shape-id] - (let [prev-parent-id (get cpindex shape-id)] - ;; Do nothing if the parent id of the shape is the same as - ;; the new destination target parent id. - (if (= prev-parent-id parent-id) - objects - (loop [sid shape-id - pid prev-parent-id - objects objects] - (let [obj (get objects pid)] - (if (and (= 1 (count (:shapes obj))) - (= sid (first (:shapes obj))) - (= :group (:type obj))) - (recur pid - (:parent-id obj) - (dissoc objects pid)) - (cond-> objects - true - (update-in [pid :shapes] strip-id sid) - - (and (:shape-ref obj) - (= (:type obj) :group) - (not ignore-touched)) - (update-in [pid :touched] - cph/set-touched-group :shapes-group)))))))) - - (update-parent-id [objects id] - (update objects id assoc :parent-id parent-id)) - - ;; Updates the frame-id references that might be outdated - (assign-frame-id [frame-id objects id] - (let [objects (update objects id assoc :frame-id frame-id) - obj (get objects id)] - (cond-> objects - ;; If we moving frame, the parent frame is the root - ;; and we DO NOT NEED update children because the - ;; children will point correctly to the frame what we - ;; are currently moving - (not= :frame (:type obj)) - (as-> $$ (reduce (partial assign-frame-id frame-id) $$ (:shapes obj)))))) - - (move-objects [objects] - (let [valid? (every? (partial is-valid-move? objects) shapes) - - ;; Create a index of shape ids pointing to the - ;; corresponding parents; used mainly for update old - ;; parents after move operation. - cpindex (reduce (fn [index id] - (let [obj (get objects id)] - (assoc! index id (:parent-id obj)))) - (transient {}) - (keys objects)) - cpindex (persistent! cpindex) - - parent (get objects parent-id) - frame-id (if (= :frame (:type parent)) - (:id parent) - (:frame-id parent))] - - (if (and valid? (seq shapes)) - (as-> objects $ - ;; Add the new shapes to the parent object. - (update $ parent-id #(add-to-parent % index shapes)) - - ;; Update each individual shapre link to the new parent - (reduce update-parent-id $ shapes) - - ;; Analyze the old parents and clear the old links - ;; only if the new parrent is different form old - ;; parent. - (reduce (partial remove-from-old-parent cpindex) $ shapes) - - ;; Ensure that all shapes of the new parent has a - ;; correct link to the topside frame. - (reduce (partial assign-frame-id frame-id) $ shapes)) - objects)))] - - (if page-id - (d/update-in-when data [:pages-index page-id :objects] move-objects) - (d/update-in-when data [:components component-id :objects] move-objects)))) - -(defmethod process-change :add-page - [data {:keys [id name page]}] - (cond - (and (string? name) (uuid? id)) - (let [page (assoc empty-page-data - :id id - :name name)] - (-> data - (update :pages conj id) - (update :pages-index assoc id page))) - - (map? page) - (-> data - (update :pages conj (:id page)) - (update :pages-index assoc (:id page) page)) - - :else - (ex/raise :type :conflict - :hint "name or page should be provided, never both"))) - -(defmethod process-change :mod-page - [data {:keys [id name]}] - (d/update-in-when data [:pages-index id] assoc :name name)) - -(defmethod process-change :del-page - [data {:keys [id]}] - (-> data - (update :pages (fn [pages] (filterv #(not= % id) pages))) - (update :pages-index dissoc id))) - -(defmethod process-change :mov-page - [data {:keys [id index]}] - (update data :pages cph/insert-at-index index [id])) - -(defmethod process-change :add-color - [data {:keys [color]}] - (update data :colors assoc (:id color) color)) - -(defmethod process-change :mod-color - [data {:keys [color]}] - (d/assoc-in-when data [:colors (:id color)] color)) - -(defmethod process-change :del-color - [data {:keys [id]}] - (update data :colors dissoc id)) - -(defmethod process-change :add-recent-color - [data {:keys [color]}] - ;; Moves the color to the top of the list and then truncates up to 15 - (update data :recent-colors (fn [rc] - (let [rc (conj (filterv (comp not #{color}) (or rc [])) color)] - (if (> (count rc) 15) - (subvec rc 1) - rc))))) - -;; -- Media - -(defmethod process-change :add-media - [data {:keys [object]}] - (update data :media assoc (:id object) object)) - -(defmethod process-change :mod-media - [data {:keys [object]}] - (d/update-in-when data [:media (:id object)] merge object)) - -(defmethod process-change :del-media - [data {:keys [id]}] - (update data :media dissoc id)) - -;; -- Components - -(defmethod process-change :add-component - [data {:keys [id name shapes]}] - (assoc-in data [:components id] - {:id id - :name name - :objects (d/index-by :id shapes)})) - -(defmethod process-change :mod-component - [data {:keys [id name objects]}] - (update-in data [:components id] - #(cond-> % - (some? name) - (assoc :name name) - - (some? objects) - (assoc :objects objects)))) - -(defmethod process-change :del-component - [data {:keys [id]}] - (d/dissoc-in data [:components id])) - -;; -- Typography - -(defmethod process-change :add-typography - [data {:keys [typography]}] - (update data :typographies assoc (:id typography) typography)) - -(defmethod process-change :mod-typography - [data {:keys [typography]}] - (d/update-in-when data [:typographies (:id typography)] merge typography)) - -(defmethod process-change :del-typography - [data {:keys [id]}] - (update data :typographies dissoc id)) - -;; -- Operations - -(defmethod process-operation :set - [shape op] - (let [attr (:attr op) - val (:val op) - ignore (:ignore-touched op) - shape-ref (:shape-ref shape) - group (get component-sync-attrs attr)] - - (cond-> shape - (and shape-ref group (not ignore) (not= val (get shape attr)) - ;; FIXME: it's difficult to tell if the geometry changes affect - ;; an individual shape inside the component, or are for - ;; the whole component (in which case we shouldn't set - ;; touched). For the moment we disable geometry touched. - (not= group :geometry-group)) - (update :touched cph/set-touched-group group) - - (nil? val) - (dissoc attr) - - (some? val) - (assoc attr val)))) - -(defmethod process-operation :set-touched - [shape op] - (let [touched (:touched op) - shape-ref (:shape-ref shape)] - (if (or (nil? shape-ref) (nil? touched) (empty? touched)) - (dissoc shape :touched) - (assoc shape :touched touched)))) - -(defmethod process-operation :default - [_ op] - (ex/raise :type :not-implemented - :code :operation-not-implemented - :context {:type (:type op)})) - + [app.common.pages.changes :as changes] + [app.common.pages.common :as common] + [app.common.pages.helpers :as helpers] + [app.common.pages.init :as init] + [app.common.pages.spec :as spec] + [clojure.spec.alpha :as s])) + +;; Common +(d/export common/root) +(d/export common/file-version) +(d/export common/default-color) +(d/export common/component-sync-attrs) + +;; Helpers + +(d/export helpers/walk-pages) +(d/export helpers/select-objects) +(d/export helpers/update-object-list) +(d/export helpers/get-root-shape) +(d/export helpers/make-container) +(d/export helpers/page?) +(d/export helpers/component?) +(d/export helpers/get-container) +(d/export helpers/get-shape) +(d/export helpers/get-component) +(d/export helpers/is-master-of) +(d/export helpers/get-component-root) +(d/export helpers/get-children) +(d/export helpers/get-children-objects) +(d/export helpers/get-object-with-children) +(d/export helpers/is-shape-grouped) +(d/export helpers/get-parent) +(d/export helpers/get-parents) +(d/export helpers/generate-child-parent-index) +(d/export helpers/calculate-invalid-targets) +(d/export helpers/valid-frame-target) +(d/export helpers/position-on-parent) +(d/export helpers/insert-at-index) +(d/export helpers/append-at-the-end) +(d/export helpers/select-toplevel-shapes) +(d/export helpers/select-frames) +(d/export helpers/clone-object) +(d/export helpers/indexed-shapes) +(d/export helpers/expand-region-selection) +(d/export helpers/frame-id-by-position) +(d/export helpers/set-touched-group) +(d/export helpers/touched-group?) + +;; Process changes +(d/export changes/process-changes) + +;; Initialization +(d/export init/default-frame-attrs) +(d/export init/default-shape-attrs) +(d/export init/make-file-data) +(d/export init/make-minimal-shape) +(d/export init/make-minimal-group) + +;; Specs + +(s/def ::changes ::spec/changes) +(s/def ::color ::spec/color) +(s/def ::data ::spec/data) +(s/def ::media-object ::spec/media-object) +(s/def ::minimal-shape ::spec/minimal-shape) +(s/def ::page ::spec/page) +(s/def ::recent-color ::spec/recent-color) +(s/def ::shape-attrs ::spec/shape-attrs) +(s/def ::typography ::spec/typography) diff --git a/common/app/common/pages/changes.cljc b/common/app/common/pages/changes.cljc new file mode 100644 index 0000000000..c327e02864 --- /dev/null +++ b/common/app/common/pages/changes.cljc @@ -0,0 +1,415 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.pages.changes + (:require + [app.common.data :as d] + [app.common.exceptions :as ex] + [app.common.geom.shapes :as gsh] + [app.common.pages.helpers :as cph] + [app.common.pages.spec :as ps] + [app.common.spec :as us] + [app.common.pages.common :refer [component-sync-attrs]] + [app.common.pages.init :as init] + [app.common.pages.spec :as spec])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Page Transformation Changes +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; --- Changes Processing Impl + +(defmulti process-change (fn [_ change] (:type change))) +(defmulti process-operation (fn [_ op] (:type op))) + +(defn process-changes + [data items] + (->> (us/verify ::spec/changes items) + (reduce #(do + ;; (prn "process-change" (:type %2) (:id %2)) + (or (process-change %1 %2) %1)) + data))) + +(defmethod process-change :set-option + [data {:keys [page-id option value]}] + (d/update-in-when data [:pages-index page-id] + (fn [data] + (let [path (if (seqable? option) option [option])] + (if value + (assoc-in data (into [:options] path) value) + (assoc data :options (d/dissoc-in (:options data) path))))))) + +(defmethod process-change :add-obj + [data {:keys [id obj page-id component-id frame-id parent-id + index ignore-touched]}] + (letfn [(update-fn [data] + (let [parent-id (or parent-id frame-id) + objects (:objects data) + obj (assoc obj + :frame-id frame-id + :parent-id parent-id + :id id)] + (if (and (or (nil? parent-id) (contains? objects parent-id)) + (or (nil? frame-id) (contains? objects frame-id))) + (-> data + (update :objects assoc id obj) + (update-in [:objects parent-id :shapes] + (fn [shapes] + (let [shapes (or shapes [])] + (cond + (some #{id} shapes) + shapes + + (nil? index) + (if (= :frame (:type obj)) + (d/concat [id] shapes) + (conj shapes id)) + + :else + (cph/insert-at-index shapes index [id]))))) + + (cond-> (and (:shape-ref (get-in data [:objects parent-id])) + (not= parent-id frame-id) + (not ignore-touched)) + (update-in [:objects parent-id :touched] + cph/set-touched-group :shapes-group))) + data)))] + (if page-id + (d/update-in-when data [:pages-index page-id] update-fn) + (d/update-in-when data [:components component-id] update-fn)))) + +(defmethod process-change :mod-obj + [data {:keys [id page-id component-id operations]}] + (let [update-fn (fn [objects] + (if-let [obj (get objects id)] + (let [result (reduce process-operation obj operations)] + (us/verify ::spec/shape result) + (assoc objects id result)) + objects))] + (if page-id + (d/update-in-when data [:pages-index page-id :objects] update-fn) + (d/update-in-when data [:components component-id :objects] update-fn)))) + +(defmethod process-change :del-obj + [data {:keys [page-id component-id id ignore-touched]}] + (letfn [(delete-object [objects id] + (if-let [target (get objects id)] + (let [parent-id (cph/get-parent id objects) + frame-id (:frame-id target) + parent (get objects parent-id) + objects (dissoc objects id)] + (cond-> objects + (and (not= parent-id frame-id) + (= :group (:type parent))) + (update-in [parent-id :shapes] (fn [s] (filterv #(not= % id) s))) + + (and (:shape-ref parent) (not ignore-touched)) + (update-in [parent-id :touched] cph/set-touched-group :shapes-group) + + (contains? objects frame-id) + (update-in [frame-id :shapes] (fn [s] (filterv #(not= % id) s))) + + (seq (:shapes target)) ; Recursive delete all + ; dependend objects + (as-> $ (reduce delete-object $ (:shapes target))))) + objects))] + (if page-id + (d/update-in-when data [:pages-index page-id :objects] delete-object id) + (d/update-in-when data [:components component-id :objects] delete-object id)))) + +;; reg-objects operation "regenerates" the values for the parent groups +(defmethod process-change :reg-objects + [data {:keys [page-id component-id shapes]}] + (letfn [(reg-objects [objects] + (reduce #(update %1 %2 update-group %1) objects + (sequence (comp + (mapcat #(cons % (cph/get-parents % objects))) + (map #(get objects %)) + (filter #(= (:type %) :group)) + (map :id) + (distinct)) + shapes))) + (update-group [group objects] + (let [children (->> group :shapes (map #(get objects %)))] + (if (:masked-group? group) + (let [mask (first children)] + (-> group + (merge (select-keys mask [:selrect :points])) + (assoc :x (-> mask :selrect :x) + :y (-> mask :selrect :y) + :width (-> mask :selrect :width) + :height (-> mask :selrect :height)))) + (gsh/update-group-selrect group children))))] + + (if page-id + (d/update-in-when data [:pages-index page-id :objects] reg-objects) + (d/update-in-when data [:components component-id :objects] reg-objects)))) + +(defmethod process-change :mov-objects + [data {:keys [parent-id shapes index page-id component-id ignore-touched]}] + (letfn [(is-valid-move? [objects shape-id] + (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] + (and (not (invalid-targets parent-id)) + (cph/valid-frame-target shape-id parent-id objects)))) + + (insert-items [prev-shapes index shapes] + (let [prev-shapes (or prev-shapes [])] + (if index + (cph/insert-at-index prev-shapes index shapes) + (cph/append-at-the-end prev-shapes shapes)))) + + (check-insert-items [prev-shapes parent index shapes] + (if-not (:masked-group? parent) + (insert-items prev-shapes index shapes) + ;; For masked groups, the first shape is the mask + ;; and it cannot be moved. + (let [mask-id (first prev-shapes) + other-ids (rest prev-shapes) + not-mask-shapes (strip-id shapes mask-id) + new-index (if (nil? index) nil (max (dec index) 0)) + new-shapes (insert-items other-ids new-index not-mask-shapes)] + (d/concat [mask-id] new-shapes)))) + + (strip-id [coll id] + (filterv #(not= % id) coll)) + + (add-to-parent [parent index shapes] + (cond-> parent + true + (update :shapes check-insert-items parent index shapes) + + (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) + (update :touched cph/set-touched-group :shapes-group))) + + (remove-from-old-parent [cpindex objects shape-id] + (let [prev-parent-id (get cpindex shape-id)] + ;; Do nothing if the parent id of the shape is the same as + ;; the new destination target parent id. + (if (= prev-parent-id parent-id) + objects + (loop [sid shape-id + pid prev-parent-id + objects objects] + (let [obj (get objects pid)] + (if (and (= 1 (count (:shapes obj))) + (= sid (first (:shapes obj))) + (= :group (:type obj))) + (recur pid + (:parent-id obj) + (dissoc objects pid)) + (cond-> objects + true + (update-in [pid :shapes] strip-id sid) + + (and (:shape-ref obj) + (= (:type obj) :group) + (not ignore-touched)) + (update-in [pid :touched] + cph/set-touched-group :shapes-group)))))))) + + (update-parent-id [objects id] + (update objects id assoc :parent-id parent-id)) + + ;; Updates the frame-id references that might be outdated + (assign-frame-id [frame-id objects id] + (let [objects (update objects id assoc :frame-id frame-id) + obj (get objects id)] + (cond-> objects + ;; If we moving frame, the parent frame is the root + ;; and we DO NOT NEED update children because the + ;; children will point correctly to the frame what we + ;; are currently moving + (not= :frame (:type obj)) + (as-> $$ (reduce (partial assign-frame-id frame-id) $$ (:shapes obj)))))) + + (move-objects [objects] + (let [valid? (every? (partial is-valid-move? objects) shapes) + + ;; Create a index of shape ids pointing to the + ;; corresponding parents; used mainly for update old + ;; parents after move operation. + cpindex (reduce (fn [index id] + (let [obj (get objects id)] + (assoc! index id (:parent-id obj)))) + (transient {}) + (keys objects)) + cpindex (persistent! cpindex) + + parent (get objects parent-id) + frame-id (if (= :frame (:type parent)) + (:id parent) + (:frame-id parent))] + + (if (and valid? (seq shapes)) + (as-> objects $ + ;; Add the new shapes to the parent object. + (update $ parent-id #(add-to-parent % index shapes)) + + ;; Update each individual shapre link to the new parent + (reduce update-parent-id $ shapes) + + ;; Analyze the old parents and clear the old links + ;; only if the new parrent is different form old + ;; parent. + (reduce (partial remove-from-old-parent cpindex) $ shapes) + + ;; Ensure that all shapes of the new parent has a + ;; correct link to the topside frame. + (reduce (partial assign-frame-id frame-id) $ shapes)) + objects)))] + + (if page-id + (d/update-in-when data [:pages-index page-id :objects] move-objects) + (d/update-in-when data [:components component-id :objects] move-objects)))) + +(defmethod process-change :add-page + [data {:keys [id name page]}] + (cond + (and (string? name) (uuid? id)) + (let [page (assoc init/empty-page-data + :id id + :name name)] + (-> data + (update :pages conj id) + (update :pages-index assoc id page))) + + (map? page) + (-> data + (update :pages conj (:id page)) + (update :pages-index assoc (:id page) page)) + + :else + (ex/raise :type :conflict + :hint "name or page should be provided, never both"))) + +(defmethod process-change :mod-page + [data {:keys [id name]}] + (d/update-in-when data [:pages-index id] assoc :name name)) + +(defmethod process-change :del-page + [data {:keys [id]}] + (-> data + (update :pages (fn [pages] (filterv #(not= % id) pages))) + (update :pages-index dissoc id))) + +(defmethod process-change :mov-page + [data {:keys [id index]}] + (update data :pages cph/insert-at-index index [id])) + +(defmethod process-change :add-color + [data {:keys [color]}] + (update data :colors assoc (:id color) color)) + +(defmethod process-change :mod-color + [data {:keys [color]}] + (d/assoc-in-when data [:colors (:id color)] color)) + +(defmethod process-change :del-color + [data {:keys [id]}] + (update data :colors dissoc id)) + +(defmethod process-change :add-recent-color + [data {:keys [color]}] + ;; Moves the color to the top of the list and then truncates up to 15 + (update data :recent-colors (fn [rc] + (let [rc (conj (filterv (comp not #{color}) (or rc [])) color)] + (if (> (count rc) 15) + (subvec rc 1) + rc))))) + +;; -- Media + +(defmethod process-change :add-media + [data {:keys [object]}] + (update data :media assoc (:id object) object)) + +(defmethod process-change :mod-media + [data {:keys [object]}] + (d/update-in-when data [:media (:id object)] merge object)) + +(defmethod process-change :del-media + [data {:keys [id]}] + (update data :media dissoc id)) + +;; -- Components + +(defmethod process-change :add-component + [data {:keys [id name shapes]}] + (assoc-in data [:components id] + {:id id + :name name + :objects (d/index-by :id shapes)})) + +(defmethod process-change :mod-component + [data {:keys [id name objects]}] + (update-in data [:components id] + #(cond-> % + (some? name) + (assoc :name name) + + (some? objects) + (assoc :objects objects)))) + +(defmethod process-change :del-component + [data {:keys [id]}] + (d/dissoc-in data [:components id])) + +;; -- Typography + +(defmethod process-change :add-typography + [data {:keys [typography]}] + (update data :typographies assoc (:id typography) typography)) + +(defmethod process-change :mod-typography + [data {:keys [typography]}] + (d/update-in-when data [:typographies (:id typography)] merge typography)) + +(defmethod process-change :del-typography + [data {:keys [id]}] + (update data :typographies dissoc id)) + +;; -- Operations + +(defmethod process-operation :set + [shape op] + (let [attr (:attr op) + val (:val op) + ignore (:ignore-touched op) + shape-ref (:shape-ref shape) + group (get component-sync-attrs attr)] + + (cond-> shape + (and shape-ref group (not ignore) (not= val (get shape attr)) + ;; FIXME: it's difficult to tell if the geometry changes affect + ;; an individual shape inside the component, or are for + ;; the whole component (in which case we shouldn't set + ;; touched). For the moment we disable geometry touched. + (not= group :geometry-group)) + (update :touched cph/set-touched-group group) + + (nil? val) + (dissoc attr) + + (some? val) + (assoc attr val)))) + +(defmethod process-operation :set-touched + [shape op] + (let [touched (:touched op) + shape-ref (:shape-ref shape)] + (if (or (nil? shape-ref) (nil? touched) (empty? touched)) + (dissoc shape :touched) + (assoc shape :touched touched)))) + +(defmethod process-operation :default + [_ op] + (ex/raise :type :not-implemented + :code :operation-not-implemented + :context {:type (:type op)})) + diff --git a/common/app/common/pages/common.cljc b/common/app/common/pages/common.cljc new file mode 100644 index 0000000000..2d58b6bbe3 --- /dev/null +++ b/common/app/common/pages/common.cljc @@ -0,0 +1,56 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.pages.common + (:require + [app.common.uuid :as uuid])) + +(def file-version 4) +(def default-color "#b1b2b5") ;; $color-gray-20 +(def root uuid/zero) + +(def component-sync-attrs + {:fill-color :fill-group + :fill-opacity :fill-group + :fill-color-gradient :fill-group + :fill-color-ref-file :fill-group + :fill-color-ref-id :fill-group + :content :content-group + :font-family :text-font-group + :font-size :text-font-group + :font-style :text-font-group + :font-weight :text-font-group + :letter-spacing :text-display-group + :line-height :text-display-group + :text-align :text-display-group + :stroke-color :stroke-group + :stroke-color-gradient :stroke-group + :stroke-color-ref-file :stroke-group + :stroke-color-ref-id :stroke-group + :stroke-opacity :stroke-group + :stroke-style :stroke-group + :stroke-width :stroke-group + :stroke-alignment :stroke-group + :rx :radius-group + :ry :radius-group + :selrect :geometry-group + :points :geometry-group + :locked :geometry-group + :proportion :geometry-group + :proportion-lock :geometry-group + :x :geometry-group + :y :geometry-group + :width :geometry-group + :height :geometry-group + :transform :geometry-group + :transform-inverse :geometry-group + :shadow :shadow-group + :blur :blur-group + :masked-group? :mask-group}) + diff --git a/common/app/common/pages_helpers.cljc b/common/app/common/pages/helpers.cljc similarity index 99% rename from common/app/common/pages_helpers.cljc rename to common/app/common/pages/helpers.cljc index 7c5aaa5b0a..f1435b33e7 100644 --- a/common/app/common/pages_helpers.cljc +++ b/common/app/common/pages/helpers.cljc @@ -7,7 +7,7 @@ ;; ;; Copyright (c) 2020 UXBOX Labs SL -(ns app.common.pages-helpers +(ns app.common.pages.helpers (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] diff --git a/common/app/common/pages/init.cljc b/common/app/common/pages/init.cljc new file mode 100644 index 0000000000..d39ecf1fe3 --- /dev/null +++ b/common/app/common/pages/init.cljc @@ -0,0 +1,143 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.pages.init + (:require + [app.common.data :as d] + [app.common.uuid :as uuid] + [app.common.exceptions :as ex] + [app.common.pages.common :refer [file-version default-color]])) + +(def root uuid/zero) + +(def empty-page-data + {:options {} + :name "Page" + :objects + {root + {:id root + :type :frame + :name "Root Frame"}}}) + +(def empty-file-data + {:version file-version + :pages [] + :pages-index {}}) + +(def default-shape-attrs + {:fill-color default-color + :fill-opacity 1}) + +(def default-frame-attrs + {:frame-id uuid/zero + :fill-color "#ffffff" + :fill-opacity 1 + :shapes []}) + +(def ^:private minimal-shapes + [{:type :rect + :name "Rect" + :fill-color default-color + :fill-opacity 1 + :stroke-style :none + :stroke-alignment :center + :stroke-width 0 + :stroke-color "#000000" + :stroke-opacity 0 + :rx 0 + :ry 0} + + {:type :image} + + {:type :icon} + + {:type :circle + :name "Circle" + :fill-color default-color + :fill-opacity 1 + :stroke-style :none + :stroke-alignment :center + :stroke-width 0 + :stroke-color "#000000" + :stroke-opacity 0} + + {:type :path + :name "Path" + :fill-color "#000000" + :fill-opacity 0 + :stroke-style :solid + :stroke-alignment :center + :stroke-width 2 + :stroke-color "#000000" + :stroke-opacity 1} + + {:type :frame + :name "Artboard" + :fill-color "#ffffff" + :fill-opacity 1 + :stroke-style :none + :stroke-alignment :center + :stroke-width 0 + :stroke-color "#000000" + :stroke-opacity 0} + + {:type :text + :name "Text" + :content nil}]) + +(defn make-minimal-shape + [type] + (let [type (cond (= type :curve) :path + :else type) + shape (d/seek #(= type (:type %)) minimal-shapes)] + (when-not shape + (ex/raise :type :assertion + :code :shape-type-not-implemented + :context {:type type})) + + (cond-> shape + :always + (assoc :id (uuid/next)) + + (not= :path (:type shape)) + (assoc :x 0 + :y 0 + :width 1 + :height 1 + :selrect {:x 0 + :y 0 + :x1 0 + :y1 0 + :x2 1 + :y2 1 + :width 1 + :height 1})))) + +(defn make-minimal-group + [frame-id selection-rect group-name] + {:id (uuid/next) + :type :group + :name group-name + :shapes [] + :frame-id frame-id + :x (:x selection-rect) + :y (:y selection-rect) + :width (:width selection-rect) + :height (:height selection-rect)}) + +(defn make-file-data + ([] (make-file-data (uuid/next))) + ([id] + (let [ + pd (assoc empty-page-data + :id id + :name "Page-1")] + (-> empty-file-data + (update :pages conj id) + (update :pages-index assoc id pd))))) diff --git a/common/app/common/pages_migrations.cljc b/common/app/common/pages/migrations.cljc similarity index 89% rename from common/app/common/pages_migrations.cljc rename to common/app/common/pages/migrations.cljc index ef16a5e549..5c65aa9ed2 100644 --- a/common/app/common/pages_migrations.cljc +++ b/common/app/common/pages/migrations.cljc @@ -1,4 +1,13 @@ -(ns app.common.pages-migrations +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.pages.migrations (:require [app.common.pages :as cp] [app.common.geom.shapes :as gsh] diff --git a/common/app/common/pages/spec.cljc b/common/app/common/pages/spec.cljc new file mode 100644 index 0000000000..1cd0a4dfa0 --- /dev/null +++ b/common/app/common/pages/spec.cljc @@ -0,0 +1,571 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.common.pages.spec + (:require + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.spec :as us] + [clojure.spec.alpha :as s])) + +;; --- Specs + +(s/def ::frame-id uuid?) +(s/def ::id uuid?) +(s/def ::name string?) +(s/def ::page-id uuid?) +(s/def ::parent-id uuid?) +(s/def ::string string?) +(s/def ::type keyword?) +(s/def ::uuid uuid?) + +(s/def ::component-id uuid?) +(s/def ::component-file uuid?) +(s/def ::component-root? boolean?) +(s/def ::shape-ref uuid?) + +(s/def ::safe-integer ::us/safe-integer) +(s/def ::safe-number ::us/safe-number) + +(s/def :internal.matrix/a ::us/safe-number) +(s/def :internal.matrix/b ::us/safe-number) +(s/def :internal.matrix/c ::us/safe-number) +(s/def :internal.matrix/d ::us/safe-number) +(s/def :internal.matrix/e ::us/safe-number) +(s/def :internal.matrix/f ::us/safe-number) + +(s/def ::matrix + (s/and (s/keys :req-un [:internal.matrix/a + :internal.matrix/b + :internal.matrix/c + :internal.matrix/d + :internal.matrix/e + :internal.matrix/f]) + gmt/matrix?)) + + +(s/def :internal.point/x ::us/safe-number) +(s/def :internal.point/y ::us/safe-number) + +(s/def ::point + (s/and (s/keys :req-un [:internal.point/x + :internal.point/y]) + gpt/point?)) + +;; GRADIENTS + +(s/def :internal.gradient.stop/color ::string) +(s/def :internal.gradient.stop/opacity ::safe-number) +(s/def :internal.gradient.stop/offset ::safe-number) + +(s/def :internal.gradient/type #{:linear :radial}) +(s/def :internal.gradient/start-x ::safe-number) +(s/def :internal.gradient/start-y ::safe-number) +(s/def :internal.gradient/end-x ::safe-number) +(s/def :internal.gradient/end-y ::safe-number) +(s/def :internal.gradient/width ::safe-number) + +(s/def :internal.gradient/stop + (s/keys :req-un [:internal.gradient.stop/color + :internal.gradient.stop/opacity + :internal.gradient.stop/offset])) + +(s/def :internal.gradient/stops + (s/coll-of :internal.gradient/stop :kind vector?)) + +(s/def ::gradient + (s/keys :req-un [:internal.gradient/type + :internal.gradient/start-x + :internal.gradient/start-y + :internal.gradient/end-x + :internal.gradient/end-y + :internal.gradient/width + :internal.gradient/stops])) + + +;;; COLORS + +(s/def :internal.color/name ::string) +(s/def :internal.color/value (s/nilable ::string)) +(s/def :internal.color/color (s/nilable ::string)) +(s/def :internal.color/opacity (s/nilable ::safe-number)) +(s/def :internal.color/gradient (s/nilable ::gradient)) + +(s/def ::color + (s/keys :opt-un [::id + :internal.color/name + :internal.color/value + :internal.color/color + :internal.color/opacity + :internal.color/gradient])) + + + +;;; SHADOW EFFECT + +(s/def :internal.shadow/id uuid?) +(s/def :internal.shadow/style #{:drop-shadow :inner-shadow}) +(s/def :internal.shadow/color ::color) +(s/def :internal.shadow/offset-x ::safe-number) +(s/def :internal.shadow/offset-y ::safe-number) +(s/def :internal.shadow/blur ::safe-number) +(s/def :internal.shadow/spread ::safe-number) +(s/def :internal.shadow/hidden boolean?) + +(s/def :internal.shadow/shadow + (s/keys :req-un [:internal.shadow/id + :internal.shadow/style + :internal.shadow/color + :internal.shadow/offset-x + :internal.shadow/offset-y + :internal.shadow/blur + :internal.shadow/spread + :internal.shadow/hidden])) + +(s/def ::shadow + (s/coll-of :internal.shadow/shadow :kind vector?)) + + +;;; BLUR EFFECT + +(s/def :internal.blur/id uuid?) +(s/def :internal.blur/type #{:layer-blur}) +(s/def :internal.blur/value ::safe-number) +(s/def :internal.blur/hidden boolean?) + +(s/def ::blur + (s/keys :req-un [:internal.blur/id + :internal.blur/type + :internal.blur/value + :internal.blur/hidden])) + +;; Page Options +(s/def :internal.page.grid.color/value string?) +(s/def :internal.page.grid.color/opacity ::safe-number) + +(s/def :internal.page.grid/size ::safe-integer) +(s/def :internal.page.grid/color + (s/keys :req-un [:internal.page.grid.color/value + :internal.page.grid.color/opacity])) + +(s/def :internal.page.grid/type #{:stretch :left :center :right}) +(s/def :internal.page.grid/item-length (s/nilable ::safe-integer)) +(s/def :internal.page.grid/gutter (s/nilable ::safe-integer)) +(s/def :internal.page.grid/margin (s/nilable ::safe-integer)) + +(s/def :internal.page.grid/square + (s/keys :req-un [:internal.page.grid/size + :internal.page.grid/color])) + +(s/def :internal.page.grid/column + (s/keys :req-un [:internal.page.grid/size + :internal.page.grid/color + :internal.page.grid/type + :internal.page.grid/item-length + :internal.page.grid/gutter + :internal.page.grid/margin])) + +(s/def :internal.page.grid/row :internal.page.grid/column) + +(s/def :internal.page.options/background string?) +(s/def :internal.page.options/saved-grids + (s/keys :req-un [:internal.page.grid/square + :internal.page.grid/row + :internal.page.grid/column])) + +(s/def :internal.page/options + (s/keys :opt-un [:internal.page.options/background])) + +;; Interactions + +(s/def :internal.shape.interaction/event-type #{:click}) ; In the future we will have more options +(s/def :internal.shape.interaction/action-type #{:navigate}) +(s/def :internal.shape.interaction/destination ::uuid) + +(s/def :internal.shape/interaction + (s/keys :req-un [:internal.shape.interaction/event-type + :internal.shape.interaction/action-type + :internal.shape.interaction/destination])) + +(s/def :internal.shape/interactions + (s/coll-of :internal.shape/interaction :kind vector?)) + +;; Page Data related +(s/def :internal.shape/blocked boolean?) +(s/def :internal.shape/collapsed boolean?) +(s/def :internal.shape/content any?) + +(s/def :internal.shape/fill-color string?) +(s/def :internal.shape/fill-opacity ::safe-number) +(s/def :internal.shape/fill-color-gradient (s/nilable ::gradient)) +(s/def :internal.shape/fill-color-ref-file (s/nilable uuid?)) +(s/def :internal.shape/fill-color-ref-id (s/nilable uuid?)) + +(s/def :internal.shape/font-family string?) +(s/def :internal.shape/font-size ::safe-integer) +(s/def :internal.shape/font-style string?) +(s/def :internal.shape/font-weight string?) +(s/def :internal.shape/hidden boolean?) +(s/def :internal.shape/letter-spacing ::safe-number) +(s/def :internal.shape/line-height ::safe-number) +(s/def :internal.shape/locked boolean?) +(s/def :internal.shape/page-id uuid?) +(s/def :internal.shape/proportion ::safe-number) +(s/def :internal.shape/proportion-lock boolean?) +(s/def :internal.shape/rx ::safe-number) +(s/def :internal.shape/ry ::safe-number) +(s/def :internal.shape/stroke-color string?) +(s/def :internal.shape/stroke-color-gradient (s/nilable ::gradient)) +(s/def :internal.shape/stroke-color-ref-file (s/nilable uuid?)) +(s/def :internal.shape/stroke-color-ref-id (s/nilable uuid?)) +(s/def :internal.shape/stroke-opacity ::safe-number) +(s/def :internal.shape/stroke-style #{:solid :dotted :dashed :mixed :none}) +(s/def :internal.shape/stroke-width ::safe-number) +(s/def :internal.shape/stroke-alignment #{:center :inner :outer}) +(s/def :internal.shape/text-align #{"left" "right" "center" "justify"}) +(s/def :internal.shape/x ::safe-number) +(s/def :internal.shape/y ::safe-number) +(s/def :internal.shape/cx ::safe-number) +(s/def :internal.shape/cy ::safe-number) +(s/def :internal.shape/width ::safe-number) +(s/def :internal.shape/height ::safe-number) +(s/def :internal.shape/index integer?) +(s/def :internal.shape/shadow ::shadow) +(s/def :internal.shape/blur ::blur) + +(s/def :internal.shape/x1 ::safe-number) +(s/def :internal.shape/y1 ::safe-number) +(s/def :internal.shape/x2 ::safe-number) +(s/def :internal.shape/y2 ::safe-number) + +(s/def :internal.shape.export/suffix string?) +(s/def :internal.shape.export/scale ::safe-number) +(s/def :internal.shape/export + (s/keys :req-un [::type + :internal.shape.export/suffix + :internal.shape.export/scale])) + +(s/def :internal.shape/exports + (s/coll-of :internal.shape/export :kind vector?)) + +(s/def :internal.shape/selrect + (s/keys :req-un [:internal.shape/x + :internal.shape/y + :internal.shape/x1 + :internal.shape/y1 + :internal.shape/x2 + :internal.shape/y2 + :internal.shape/width + :internal.shape/height])) + +(s/def :internal.shape/points + (s/every ::point :kind vector?)) + +(s/def :internal.shape/shapes + (s/every uuid? :kind vector?)) + +(s/def :internal.shape/transform ::matrix) +(s/def :internal.shape/transform-inverse ::matrix) + +(s/def ::shape-attrs + (s/keys :opt-un [:internal.shape/selrect + :internal.shape/points + :internal.shape/blocked + :internal.shape/collapsed + :internal.shape/content + :internal.shape/fill-color + :internal.shape/fill-opacity + :internal.shape/fill-color-gradient + :internal.shape/fill-color-ref-file + :internal.shape/fill-color-ref-id + :internal.shape/font-family + :internal.shape/font-size + :internal.shape/font-style + :internal.shape/font-weight + :internal.shape/hidden + :internal.shape/letter-spacing + :internal.shape/line-height + :internal.shape/locked + :internal.shape/proportion + :internal.shape/proportion-lock + :internal.shape/rx + :internal.shape/ry + :internal.shape/x + :internal.shape/y + :internal.shape/exports + :internal.shape/shapes + :internal.shape/stroke-color + :internal.shape/stroke-color-ref-file + :internal.shape/stroke-color-ref-id + :internal.shape/stroke-opacity + :internal.shape/stroke-style + :internal.shape/stroke-width + :internal.shape/stroke-alignment + :internal.shape/text-align + :internal.shape/transform + :internal.shape/transform-inverse + :internal.shape/width + :internal.shape/height + :internal.shape/interactions + :internal.shape/masked-group? + :internal.shape/shadow + :internal.shape/blur])) + + + ;; shapes-group is handled differently + +(s/def ::minimal-shape + (s/keys :req-un [::type ::name] + :opt-un [::id])) + +(s/def ::shape + (s/and ::minimal-shape ::shape-attrs + (s/keys :opt-un [::id + ::component-id + ::component-file + ::component-root? + ::shape-ref]))) + +(s/def :internal.page/objects (s/map-of uuid? ::shape)) + +(s/def ::page + (s/keys :req-un [::id + ::name + :internal.page/options + :internal.page/objects])) + + +(s/def ::recent-color + (s/keys :opt-un [:internal.color/value + :internal.color/color + :internal.color/opacity + :internal.color/gradient])) + +(s/def :internal.media-object/name ::string) +(s/def :internal.media-object/path ::string) +(s/def :internal.media-object/width ::safe-integer) +(s/def :internal.media-object/height ::safe-integer) +(s/def :internal.media-object/mtype ::string) +(s/def :internal.media-object/thumb-path ::string) +(s/def :internal.media-object/thumb-width ::safe-integer) +(s/def :internal.media-object/thumb-height ::safe-integer) +(s/def :internal.media-object/thumb-mtype ::string) + +(s/def ::media-object + (s/keys :req-un [::id ::name + :internal.media-object/name + :internal.media-object/path + :internal.media-object/width + :internal.media-object/height + :internal.media-object/mtype + :internal.media-object/thumb-path])) + +(s/def ::media-object-update + (s/keys :req-un [::id] + :req-opt [::name + :internal.media-object/name + :internal.media-object/path + :internal.media-object/width + :internal.media-object/height + :internal.media-object/mtype + :internal.media-object/thumb-path])) + +(s/def :internal.file/colors + (s/map-of ::uuid ::color)) + +(s/def :internal.file/recent-colors + (s/coll-of ::recent-color :kind vector?)) + +(s/def :internal.typography/id ::id) +(s/def :internal.typography/name ::string) +(s/def :internal.typography/font-id ::string) +(s/def :internal.typography/font-family ::string) +(s/def :internal.typography/font-variant-id ::string) +(s/def :internal.typography/font-size ::string) +(s/def :internal.typography/font-weight ::string) +(s/def :internal.typography/font-style ::string) +(s/def :internal.typography/line-height ::string) +(s/def :internal.typography/letter-spacing ::string) +(s/def :internal.typography/text-transform ::string) + +(s/def ::typography + (s/keys :req-un [:internal.typography/id + :internal.typography/name + :internal.typography/font-id + :internal.typography/font-family + :internal.typography/font-variant-id + :internal.typography/font-size + :internal.typography/font-weight + :internal.typography/font-style + :internal.typography/line-height + :internal.typography/letter-spacing + :internal.typography/text-transform])) + +(s/def :internal.file/pages + (s/coll-of ::uuid :kind vector?)) + +(s/def :internal.file/media + (s/map-of ::uuid ::media-object)) + +(s/def :internal.file/pages-index + (s/map-of ::uuid ::page)) + +(s/def ::data + (s/keys :req-un [:internal.file/pages-index + :internal.file/pages] + :opt-un [:internal.file/colors + :internal.file/recent-colors + :internal.file/media])) + +(s/def :internal.container/type #{:page :component}) + +(s/def ::container + (s/keys :req-un [:internal.container/type + ::id + ::name + :internal.page/objects])) + +(defmulti operation-spec :type) + +(s/def :internal.operations.set/attr keyword?) +(s/def :internal.operations.set/val any?) +(s/def :internal.operations.set/touched + (s/nilable (s/every keyword? :kind set?))) + +(defmethod operation-spec :set [_] + (s/keys :req-un [:internal.operations.set/attr + :internal.operations.set/val])) + +(defmethod operation-spec :set-touched [_] + (s/keys :req-un [:internal.operations.set/touched])) + +(defmulti change-spec :type) + +(s/def :internal.changes.set-option/option any?) +(s/def :internal.changes.set-option/value any?) + +(defmethod change-spec :set-option [_] + (s/keys :req-un [:internal.changes.set-option/option + :internal.changes.set-option/value])) + +(s/def :internal.changes.add-obj/obj ::shape) + +(defn- valid-container-id-frame? + [o] + (or (and (contains? o :page-id) + (not (contains? o :component-id)) + (some? (:frame-id o))) + (and (contains? o :component-id) + (not (contains? o :page-id)) + (nil? (:frame-id o))))) + +(defn- valid-container-id? + [o] + (or (and (contains? o :page-id) + (not (contains? o :component-id))) + (and (contains? o :component-id) + (not (contains? o :page-id))))) + +(defmethod change-spec :add-obj [_] + (s/and (s/keys :req-un [::id :internal.changes.add-obj/obj] + :opt-un [::page-id ::component-id ::parent-id ::frame-id]) + valid-container-id-frame?)) + +(s/def ::operation (s/multi-spec operation-spec :type)) +(s/def ::operations (s/coll-of ::operation)) + +(defmethod change-spec :mod-obj [_] + (s/and (s/keys :req-un [::id ::operations] + :opt-un [::page-id ::component-id]) + valid-container-id?)) + +(defmethod change-spec :del-obj [_] + (s/and (s/keys :req-un [::id] + :opt-un [::page-id ::component-id]) + valid-container-id?)) + +(s/def :internal.changes.reg-objects/shapes + (s/coll-of uuid? :kind vector?)) + +(defmethod change-spec :reg-objects [_] + (s/and (s/keys :req-un [:internal.changes.reg-objects/shapes] + :opt-un [::page-id ::component-id]) + valid-container-id?)) + +(defmethod change-spec :mov-objects [_] + (s/and (s/keys :req-un [::parent-id :internal.shape/shapes] + :opt-un [::page-id ::component-id ::index]) + valid-container-id?)) + +(defmethod change-spec :add-page [_] + (s/or :empty (s/keys :req-un [::id ::name]) + :complete (s/keys :req-un [::page]))) + +(defmethod change-spec :mod-page [_] + (s/keys :req-un [::id ::name])) + +(defmethod change-spec :del-page [_] + (s/keys :req-un [::id])) + +(defmethod change-spec :mov-page [_] + (s/keys :req-un [::id ::index])) + +(defmethod change-spec :add-color [_] + (s/keys :req-un [::color])) + +(defmethod change-spec :mod-color [_] + (s/keys :req-un [::color])) + +(defmethod change-spec :del-color [_] + (s/keys :req-un [::id])) + +(s/def :internal.changes.add-recent-color/color ::recent-color) + +(defmethod change-spec :add-recent-color [_] + (s/keys :req-un [:internal.changes.add-recent-color/color])) + +(s/def :internal.changes.media/object ::media-object) + +(defmethod change-spec :add-media [_] + (s/keys :req-un [:internal.changes.media/object])) + +(s/def :internal.changes.media.mod/object ::media-object-update) + +(defmethod change-spec :mod-media [_] + (s/keys :req-un [:internal.changes.media.mod/object])) + +(defmethod change-spec :del-media [_] + (s/keys :req-un [::id])) + +(s/def :internal.changes.add-component/shapes + (s/coll-of ::shape)) + +(defmethod change-spec :add-component [_] + (s/keys :req-un [::id ::name :internal.changes.add-component/shapes])) + +(defmethod change-spec :mod-component [_] + (s/keys :req-un [::id] + :opt-un [::name :internal.changes.add-component/shapes])) + +(defmethod change-spec :del-component [_] + (s/keys :req-un [::id])) + +(s/def :internal.changes.typography/typography ::typography) + +(defmethod change-spec :add-typography [_] + (s/keys :req-un [:internal.changes.typography/typography])) + +(defmethod change-spec :mod-typography [_] + (s/keys :req-un [:internal.changes.typography/typography])) + +(defmethod change-spec :del-typography [_] + (s/keys :req-un [:internal.typography/id])) + +(s/def ::change (s/multi-spec change-spec :type)) +(s/def ::changes (s/coll-of ::change)) diff --git a/common/app/common/spec.cljc b/common/app/common/spec.cljc index 929396e916..10a174debb 100644 --- a/common/app/common/spec.cljc +++ b/common/app/common/spec.cljc @@ -31,6 +31,9 @@ (def uuid-rx #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$") +(def max-safe-int (int 1e6)) +(def min-safe-int (int -1e6)) + ;; --- Conformers (defn- uuid-conformer @@ -118,9 +121,6 @@ (s/def ::point gpt/point?) (s/def ::id ::uuid) -(def max-safe-int 1000000) -(def min-safe-int -1000000) - (s/def ::safe-integer #(and (integer? %) diff --git a/frontend/src/app/main/data/colors.cljs b/frontend/src/app/main/data/colors.cljs index ae866dd50c..c84529a2b8 100644 --- a/frontend/src/app/main/data/colors.cljs +++ b/frontend/src/app/main/data/colors.cljs @@ -6,24 +6,24 @@ (ns app.main.data.colors (:require - [cljs.spec.alpha :as s] - [beicon.core :as rx] - [clojure.set :as set] - [potok.core :as ptk] - [app.main.streams :as ms] [app.common.data :as d] + [app.common.pages :as cp] [app.common.spec :as us] + [app.common.uuid :as uuid] + [app.main.data.modal :as md] + [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.texts :as dwt] [app.main.repo :as rp] [app.main.store :as st] + [app.main.streams :as ms] [app.util.color :as color] [app.util.i18n :refer [tr]] [app.util.router :as rt] [app.util.time :as dt] - [app.common.uuid :as uuid] - [app.main.data.workspace.common :as dwc] - [app.main.data.workspace.texts :as dwt] - [app.main.data.modal :as md] - [app.common.pages-helpers :as cph])) + [beicon.core :as rx] + [cljs.spec.alpha :as s] + [clojure.set :as set] + [potok.core :as ptk])) (def clear-color-for-rename (ptk/reify ::clear-color-for-rename @@ -112,7 +112,7 @@ (let [pid (:current-page-id state) objects (get-in state [:workspace-data :pages-index pid :objects]) not-frame (fn [shape-id] (not= (get-in objects [shape-id :type]) :frame)) - children (->> ids (filter not-frame) (mapcat #(cph/get-children % objects))) + children (->> ids (filter not-frame) (mapcat #(cp/get-children % objects))) ids (into ids children) is-text? #(= :text (:type (get objects %))) @@ -141,7 +141,7 @@ (let [pid (:current-page-id state) objects (get-in state [:workspace-data :pages-index pid :objects]) not-frame (fn [shape-id] (not= (get-in objects [shape-id :type]) :frame)) - children (->> ids (filter not-frame) (mapcat #(cph/get-children % objects))) + children (->> ids (filter not-frame) (mapcat #(cp/get-children % objects))) ids (into ids children) update-fn (fn [s] diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 7dd2e8df2d..dd8107898e 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -17,7 +17,6 @@ [app.common.geom.shapes :as geom] [app.common.math :as mth] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cfg] diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 8e7e7a40da..9f1c4ecd5d 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -12,7 +12,6 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.main.constants :as c] @@ -388,7 +387,7 @@ (conj id))] (-> state (assoc-in [:viewer-local :selected] - (cph/expand-region-selection objects selection))))))) + (cp/expand-region-selection objects selection))))))) (defn select-all [] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 126ed925bf..f42a029a0a 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -18,7 +18,6 @@ [app.common.geom.align :as gal] [app.common.math :as mth] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.config :as cfg] @@ -346,7 +345,7 @@ (initialize [state local] (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) - shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + shapes (cp/select-toplevel-shapes objects {:include-frames? true}) srect (gsh/selection-rect shapes) local (assoc local :vport size :zoom 1)] (cond @@ -517,7 +516,7 @@ (update [_ state] (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) - shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + shapes (cp/select-toplevel-shapes objects {:include-frames? true}) srect (gsh/selection-rect shapes)] (if (or (mth/nan? (:width srect)) @@ -572,7 +571,7 @@ page-id (:current-page-id state) frame-id (-> (dwc/lookup-page-objects state page-id) - (cph/frame-id-by-position {:x frame-x :y frame-y})) + (cp/frame-id-by-position {:x frame-x :y frame-y})) shape (-> (cp/make-minimal-shape type) (merge data) @@ -686,8 +685,8 @@ rchanges (d/concat (reduce (fn [res id] - (let [children (cph/get-children id objects) - parents (cph/get-parents id objects) + (let [children (cp/get-children id objects) + parents (cp/get-parents id objects) del-change #(array-map :type :del-obj :page-id page-id @@ -713,15 +712,15 @@ uchanges (d/concat (reduce (fn [res id] - (let [children (cph/get-children id objects) - parents (cph/get-parents id objects) + (let [children (cp/get-children id objects) + parents (cp/get-parents id objects) parent (get objects (first parents)) add-change (fn [id] (let [item (get objects id)] {:type :add-obj :id (:id item) :page-id page-id - :index (cph/position-on-parent id objects) + :index (cp/position-on-parent id objects) :frame-id (:frame-id item) :parent-id (:parent-id item) :obj item}))] @@ -802,7 +801,7 @@ :frame-id (:frame-id obj) :page-id page-id :shapes [id] - :index (cph/position-on-parent id objects)})) + :index (cp/position-on-parent id objects)})) selected)] ;; TODO: maybe missing the :reg-objects event? (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) @@ -826,7 +825,7 @@ (if (nil? ids) (vec res) (recur - (conj res (cph/get-parent (first ids) objects)) + (conj res (cp/get-parent (first ids) objects)) (next ids)))) groups-to-unmask @@ -869,7 +868,7 @@ {:type :mov-objects :parent-id (:parent-id obj) :page-id page-id - :index (cph/position-on-parent id objects) + :index (cp/position-on-parent id objects) :shapes [id]}))) [] (reverse ids)) [{:type :reg-objects @@ -1289,7 +1288,7 @@ [frame-id delta] (if (selected-frame? state) [(first page-selected) (get page-objects (first page-selected))] - [(cph/frame-id-by-position page-objects mouse-pos) + [(cp/frame-id-by-position page-objects mouse-pos) (gpt/subtract mouse-pos orig-pos)]) objects (d/mapm (fn [_ v] (assoc v :frame-id frame-id :parent-id frame-id)) objects) @@ -1328,7 +1327,7 @@ height 16 page-id (:current-page-id state) frame-id (-> (dwc/lookup-page-objects state page-id) - (cph/frame-id-by-position @ms/mouse-position)) + (cp/frame-id-by-position @ms/mouse-position)) shape (gsh/setup-selrect {:id id :type :text diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 663e037c79..037fa483e4 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -15,7 +15,6 @@ [potok.core :as ptk] [app.common.data :as d] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.main.worker :as uw] @@ -168,7 +167,7 @@ (defn get-frame-at-point [objects point] - (let [frames (cph/select-frames objects)] + (let [frames (cp/select-frames objects)] (d/seek #(gsh/has-point? % point) frames))) @@ -366,7 +365,7 @@ (let [expand-fn (fn [expanded] (merge expanded (->> ids - (map #(cph/get-parents % objects)) + (map #(cp/get-parents % objects)) flatten (filter #(not= % uuid/zero)) (map (fn [id] {id true})) @@ -423,7 +422,7 @@ (us/assert ::coll-of-uuid ids) (us/assert fn? f) (letfn [(impl-get-children [objects id] - (cons id (cph/get-children id objects))) + (cons id (cp/get-children id objects))) (impl-gen-changes [objects page-id ids] (loop [sids (seq ids) @@ -537,7 +536,7 @@ frame-id (if (= :frame (:type attrs)) uuid/zero (or (:frame-id attrs) - (cph/frame-id-by-position objects attrs))) + (cp/frame-id-by-position objects attrs))) shape (merge (if (= :frame (:type shape)) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 1519cd3652..dc6091372a 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -14,7 +14,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.uuid :as uuid] - [app.common.pages-helpers :as cph] + [app.common.pages :as cp] [app.main.data.workspace.common :as dwc] [app.main.snap :as snap] [app.main.streams :as ms] @@ -62,7 +62,7 @@ objects (dwc/lookup-page-objects state page-id) layout (get state :workspace-layout) - frames (cph/select-frames objects) + frames (cp/select-frames objects) fid (or (->> frames (filter #(gsh/has-point? % initial)) first diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index e5e6b78e1f..91d1e32e89 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -3,7 +3,6 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.selection :as dws] [beicon.core :as rx] @@ -14,7 +13,7 @@ (->> selected (map #(get objects %)) (filter #(not= :frame (:type %))) - (map #(assoc % ::index (cph/position-on-parent (:id %) objects))) + (map #(assoc % ::index (cp/position-on-parent (:id %) objects))) (sort-by ::index))) (defn- make-group @@ -61,7 +60,7 @@ (defn prepare-remove-group [page-id group objects] (let [shapes (:shapes group) - parent-id (cph/get-parent (:id group) objects) + parent-id (cp/get-parent (:id group) objects) parent (get objects parent-id) index-in-parent (->> (:shapes parent) (map-indexed vector) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 32cf296a84..8551541365 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -12,7 +12,6 @@ [app.common.data :as d] [app.common.spec :as us] [app.common.uuid :as uuid] - [app.common.pages-helpers :as cph] [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] [app.main.data.messages :as dm] @@ -303,7 +302,7 @@ (ptk/reify ::duplicate-component ptk/WatchEvent (watch [_ state stream] - (let [component (cph/get-component id + (let [component (cp/get-component id nil (get state :workspace-data) nil) @@ -365,7 +364,7 @@ objects (dwc/lookup-page-objects state page-id) unames (atom (dwc/retrieve-used-names objects)) - frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta)) + frame-id (cp/frame-id-by-position objects (gpt/add orig-pos delta)) update-new-shape (fn [new-shape original-shape] @@ -405,7 +404,7 @@ (dissoc :component-root?)))) [new-shape new-shapes _] - (cph/clone-object component-shape + (cp/clone-object component-shape nil (get component :objects) update-new-shape) @@ -440,7 +439,7 @@ (watch [_ state stream] (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) - shapes (cph/get-object-with-children id objects) + shapes (cp/get-object-with-children id objects) rchanges (map (fn [obj] {:type :mod-obj @@ -517,7 +516,7 @@ (log/info :msg "RESET-COMPONENT of shape" :id (str id)) (let [local-file (get state :workspace-data) libraries (get state :workspace-libraries) - container (cph/get-container (get state :current-page-id) + container (cp/get-container (get state :current-page-id) :page local-file) [rchanges uchanges] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 8347e9bc17..1cd2461e4b 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -12,7 +12,7 @@ [cljs.spec.alpha :as s] [app.common.spec :as us] [app.common.data :as d] - [app.common.pages-helpers :as cph] + [app.common.pages :as cph] ;; TODO: remove this namespace [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] [app.common.pages :as cp] diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index fe4efc91db..a4db5cce0b 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -187,7 +187,6 @@ (s/def ::version ::us/integer) (s/def ::revn ::us/integer) (s/def ::ordering ::us/integer) -(s/def ::metadata (s/nilable ::cp/metadata)) (s/def ::data ::cp/data) (s/def ::file ::dd/file) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 28a5aa5ff1..629b4bb83f 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -18,7 +18,6 @@ [app.common.geom.shapes :as geom] [app.common.math :as mth] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.main.data.workspace.common :as dwc] @@ -129,7 +128,7 @@ :pages-index page-id :objects shape-id :blocked] false)))] - (rx/of (->> (cph/select-toplevel-shapes objects) + (rx/of (->> (cp/select-toplevel-shapes objects) (map :id) (filter is-not-blocked) (into lks/empty-linked-set) @@ -235,7 +234,7 @@ name (dwc/generate-unique-name names (:name obj)) renamed-obj (assoc obj :id id :name name) moved-obj (geom/move renamed-obj delta) - frames (cph/select-frames objects) + frames (cp/select-frames objects) parent-id (or parent-id frame-id) children-changes diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 514b59b50c..f0c83a67bf 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -15,7 +15,6 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.selection :as dws] @@ -242,7 +241,7 @@ (let [position @ms/mouse-position page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) - frame-id (cph/frame-id-by-position objects position) + frame-id (cp/frame-id-by-position objects position) moving-shapes (->> ids (map #(get objects %)) @@ -399,20 +398,12 @@ (update-in objects [shape-id :modifiers] #(merge % modifiers))) ;; ID's + Children but remove frame children if the flag is set to false - ids-with-children (concat ids (mapcat #(cph/get-children % objects) + ids-with-children (concat ids (mapcat #(cp/get-children % objects) (filter not-frame-id? ids)))] (d/update-in-when state [:workspace-data :pages-index page-id :objects] #(reduce update-shape % ids-with-children))))))) -(defn rotation-modifiers [center shape angle] - (let [displacement (let [shape-center (gsh/center-shape shape)] - (-> (gmt/matrix) - (gmt/rotate angle center) - (gmt/rotate (- angle) shape-center)))] - {:rotation angle - :displacement displacement})) - ;; Set-rotation is custom because applies different modifiers to each ;; shape adjusting their position. @@ -423,14 +414,14 @@ ([delta-rotation shapes center] (letfn [(rotate-shape [objects angle shape center] - (update-in objects [(:id shape) :modifiers] merge (rotation-modifiers center shape angle))) + (update-in objects [(:id shape) :modifiers] merge (gsh/rotation-modifiers center shape angle))) (rotate-around-center [objects angle center shapes] (reduce #(rotate-shape %1 angle %2 center) objects shapes)) (set-rotation [objects] (let [id->obj #(get objects %) - get-children (fn [shape] (map id->obj (cph/get-children (:id shape) objects))) + get-children (fn [shape] (map id->obj (cp/get-children (:id shape) objects))) shapes (concat shapes (mapcat get-children shapes))] (rotate-around-center objects delta-rotation center shapes)))] @@ -452,7 +443,7 @@ objects1 (get-in state [:workspace-data :pages-index page-id :objects]) ;; ID's + Children ID's - ids-with-children (d/concat [] (mapcat #(cph/get-children % objects1) ids) ids) + ids-with-children (d/concat [] (mapcat #(cp/get-children % objects1) ids) ids) ;; For each shape applies the modifiers by transforming the objects update-shape #(update %1 %2 gsh/transform-shape) diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 6a85274e60..8166ab3340 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -14,7 +14,6 @@ [cuerdas.core :as str] [app.common.uuid :as uuid] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.math :as mth] [app.common.geom.shapes :as gsh] [app.common.geom.align :as gal] @@ -43,7 +42,7 @@ (defn- calculate-dimensions [{:keys [objects] :as data} vport] - (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + (let [shapes (cp/select-toplevel-shapes objects {:include-frames? true}) to-finite (fn [val fallback] (if (not (mth/finite? val)) fallback val)) rect (->> (gsh/selection-rect shapes) (gal/adjust-to-viewport vport))] @@ -144,7 +143,7 @@ frame-id (:id frame) - modifier-ids (concat [frame-id] (cph/get-children frame-id objects)) + modifier-ids (concat [frame-id] (cp/get-children frame-id objects)) update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) objects (reduce update-fn objects modifier-ids) frame (assoc-in frame [:modifiers :displacement] modifier) @@ -174,7 +173,7 @@ group-id (:id group) - modifier-ids (concat [group-id] (cph/get-children group-id objects)) + modifier-ids (concat [group-id] (cp/get-children group-id objects)) update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) objects (reduce update-fn objects modifier-ids) group (assoc-in group [:modifiers :displacement] modifier) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index ec587dbdd1..e2b13677f6 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -13,7 +13,6 @@ [beicon.core :as rx] [okulary.core :as l] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.uuid :as uuid] [app.main.constants :as c] [app.main.store :as st])) @@ -142,7 +141,7 @@ (l/derived :options workspace-page)) (def workspace-frames - (l/derived cph/select-frames workspace-page-objects)) + (l/derived cp/select-frames workspace-page-objects)) (defn object-by-id [id] @@ -162,7 +161,7 @@ (let [page-id (:current-page-id state) objects (get-in state [:workspace-data :pages-index page-id :objects]) selected (get-in state [:workspace-local :selected]) - children (cph/get-children id objects)] + children (cp/get-children id objects)] (some selected children)))] (l/derived selector st/state))) @@ -181,7 +180,7 @@ (let [selected (get-in state [:workspace-local :selected]) page-id (:current-page-id state) objects (get-in state [:workspace-data :pages-index page-id :objects]) - children (mapcat #(cph/get-children % objects) selected)] + children (mapcat #(cp/get-children % objects) selected)] (into selected children)))] (l/derived selector st/state =))) @@ -192,7 +191,7 @@ (let [selected (get-in state [:workspace-local :selected]) page-id (:current-page-id state) objects (get-in state [:workspace-data :pages-index page-id :objects]) - children (mapcat #(cph/get-children % objects) selected) + children (mapcat #(cp/get-children % objects) selected) shapes (into selected children)] (mapv #(get objects %) shapes)))] (l/derived selector st/state =))) diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index 4b06ecce08..333756e36e 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -12,7 +12,7 @@ [potok.core :as ptk] [cuerdas.core :as str] [app.common.data :as d] - [app.common.pages-helpers :as cph] + [app.common.pages :as cp] [app.common.uuid :as uuid] [app.util.storage :refer [storage]] [app.util.debug :refer [debug? debug-exclude-events logjs]])) @@ -119,7 +119,7 @@ (show-component [shape objects] (if (nil? (:shape-ref shape)) "" - (let [root-shape (cph/get-root-shape shape objects) + (let [root-shape (cp/get-root-shape shape objects) component-id (when root-shape (:component-id root-shape)) component-file-id (when root-shape (:component-file root-shape)) component-file (when component-file-id (get libraries component-file-id)) diff --git a/frontend/src/app/main/ui/handoff/render.cljs b/frontend/src/app/main/ui/handoff/render.cljs index 714abbc6e1..7af944e29e 100644 --- a/frontend/src/app/main/ui/handoff/render.cljs +++ b/frontend/src/app/main/ui/handoff/render.cljs @@ -15,7 +15,6 @@ [app.util.dom :as dom] [app.common.data :as d] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] @@ -141,7 +140,7 @@ (gmt/translate-matrix)) update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) - modifier-ids (d/concat [frame-id] (cph/get-children frame-id objects))] + modifier-ids (d/concat [frame-id] (cp/get-children frame-id objects))] (reduce update-fn objects modifier-ids))) (defn make-vbox [frame] diff --git a/frontend/src/app/main/ui/render.cljs b/frontend/src/app/main/ui/render.cljs index ec4b00d1f7..35612bdab6 100644 --- a/frontend/src/app/main/ui/render.cljs +++ b/frontend/src/app/main/ui/render.cljs @@ -14,7 +14,6 @@ [rumext.alpha :as mf] [app.common.uuid :as uuid] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.math :as mth] [app.common.geom.shapes :as geom] [app.common.geom.point :as gpt] @@ -34,7 +33,7 @@ (gpt/negate) (gmt/translate-matrix)) - mod-ids (cons frame-id (cph/get-children frame-id objects)) + mod-ids (cons frame-id (cp/get-children frame-id objects)) updt-fn #(-> %1 (assoc-in [%2 :modifiers :displacement] modifier) (update %2 geom/transform-shape)) @@ -82,7 +81,7 @@ [objects object-id] (if (uuid/zero? object-id) (let [object (get objects object-id) - shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + shapes (cp/select-toplevel-shapes objects {:include-frames? true}) srect (geom/selection-rect shapes) object (merge object (select-keys srect [:x :y :width :height])) object (geom/transform-shape object) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 74fc8f1623..94cefd3165 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -14,7 +14,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] - [app.common.pages-helpers :as cph] + [app.common.pages :as cp] [app.main.data.viewer :as dv] [app.main.data.comments :as dcm] [app.main.refs :as refs] @@ -143,7 +143,7 @@ update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) - objects (->> (d/concat [frame-id] (cph/get-children frame-id objects)) + objects (->> (d/concat [frame-id] (cp/get-children frame-id objects)) (reduce update-fn objects)) interactions? (:interactions-show? state) diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 6327a66d9a..d27dfe5256 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -13,7 +13,6 @@ [rumext.alpha :as mf] [app.common.data :as d] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.main.data.viewer :as dv] [app.main.refs :as refs] [app.main.store :as st] @@ -174,7 +173,7 @@ update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) frame-id (:id frame) - modifier-ids (d/concat [frame-id] (cph/get-children frame-id objects)) + modifier-ids (d/concat [frame-id] (cp/get-children frame-id objects)) objects (reduce update-fn objects modifier-ids) frame (assoc-in frame [:modifiers :displacement] modifier) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 8758831484..3b28d8daab 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -14,7 +14,6 @@ [app.common.geom.shapes :as geom] [app.common.media :as cm] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.uuid :as uuid] [app.config :as cfg] [app.main.data.colors :as dc] diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index bd9e012af9..9ac44acf47 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -11,7 +11,6 @@ (:require [app.common.data :as d] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] @@ -168,7 +167,7 @@ (if (= side :center) (st/emit! (dw/relocate-selected-shapes (:id item) 0)) (let [to-index (if (= side :top) (inc index) index) - parent-id (cph/get-parent (:id item) objects)] + parent-id (cp/get-parent (:id item) objects)] (st/emit! (dw/relocate-selected-shapes parent-id to-index))))) on-hold @@ -245,7 +244,7 @@ old-obs (unchecked-get oprops "objects")] (and (= new-itm old-itm) (identical? new-idx old-idx) - (let [childs (cph/get-children (:id new-itm) new-obs) + (let [childs (cp/get-children (:id new-itm) new-obs) childs' (conj childs (:id new-itm))] (and (or (= new-sel old-sel) (not (or (boolean (some new-sel childs')) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs index 41fe6bd195..0d4a125b7f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs @@ -10,7 +10,7 @@ (ns app.main.ui.workspace.sidebar.options.component (:require [rumext.alpha :as mf] - [app.common.pages-helpers :as cph] + [app.common.pages :as cp] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.icons :as i] @@ -32,10 +32,10 @@ show? (some? (:component-id values)) local-library (mf/deref refs/workspace-local-library) libraries (mf/deref refs/workspace-libraries) - component (cph/get-component (:component-id values) - (:component-file values) - local-library - libraries) + component (cp/get-component (:component-id values) + (:component-file values) + local-library + libraries) on-menu-click (mf/use-callback (fn [event] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs index 4dac6c4d80..4554a9530e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs @@ -13,7 +13,6 @@ [rumext.alpha :as mf] [app.common.attrs :as attrs] [app.common.geom.shapes :as geom] - [app.common.pages-helpers :as cph] [app.main.refs :as refs] [app.main.data.workspace.texts :as dwt] [app.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/interactions.cljs index bfa6c576ea..98f14837c3 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/interactions.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/interactions.cljs @@ -11,7 +11,7 @@ (:require [rumext.alpha :as mf] [app.common.data :as d] - [app.common.pages-helpers :as cph] + [app.common.pages :as cp] [app.main.data.workspace :as dw] [app.main.refs :as refs] [app.main.store :as st] @@ -32,7 +32,7 @@ destination (get objects (:destination interaction)) frames (mf/use-memo (mf/deps objects) - #(cph/select-frames objects)) + #(cp/select-frames objects)) show-frames-dropdown? (mf/use-state false) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index c41de8a86a..0372abf46b 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -15,7 +15,6 @@ [app.common.exceptions :as ex] [app.common.geom.shapes :as geom] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.common.uuid :as uuid] [app.util.quadtree :as qdt] @@ -65,7 +64,7 @@ (defn- create-index [objects] - (let [shapes (cph/select-toplevel-shapes objects {:include-frames? true}) + (let [shapes (cp/select-toplevel-shapes objects {:include-frames? true}) bounds (geom/selection-rect shapes) bounds #js {:x (:x bounds) :y (:y bounds) diff --git a/frontend/src/app/worker/snaps.cljs b/frontend/src/app/worker/snaps.cljs index 4f95a9d40d..ecd5ba34da 100644 --- a/frontend/src/app/worker/snaps.cljs +++ b/frontend/src/app/worker/snaps.cljs @@ -12,7 +12,6 @@ [okulary.core :as l] [app.common.uuid :as uuid] [app.common.pages :as cp] - [app.common.pages-helpers :as cph] [app.common.data :as d] [app.worker.impl :as impl] [app.util.range-tree :as rt] @@ -46,7 +45,7 @@ (let [frame-shapes (->> (vals objects) (filter :frame-id) (group-by :frame-id)) - frame-shapes (->> (cph/select-frames objects) + frame-shapes (->> (cp/select-frames objects) (reduce #(update %1 (:id %2) conj %2) frame-shapes))] (d/mapm (fn [frame-id shapes] {:x (create-coord-data frame-id shapes :x) From 574e8a92a8d461a2d5796cc9650b2a88f42f49f8 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 11 Dec 2020 08:27:51 +0100 Subject: [PATCH 195/195] :bug: Fixed problem with groups --- common/app/common/geom/shapes/transforms.cljc | 4 ++-- frontend/src/app/main/data/workspace/groups.cljs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 2def83afa2..0430f0ea2e 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -270,12 +270,12 @@ points (->> children (mapcat :points)) ;; Invert to get the points minus the transforms applied to the group - base-points (transform-points points shape-center (:transform-inverse group)) + base-points (transform-points points shape-center (:transform-inverse group (gmt/matrix))) ;; Defines the new selection rect with its transformations new-points (-> (gpr/points->selrect base-points) (gpr/rect->points) - (transform-points shape-center (:transform group))) + (transform-points shape-center (:transform group (gmt/matrix)))) ;; Calculte the new selrect new-selrect (gpr/points->selrect base-points)] diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index 91d1e32e89..fe79a6c071 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -169,7 +169,10 @@ :id (:id group) :operations [{:type :set :attr :masked-group? - :val nil}]})] + :val nil}]} + {:type :reg-objects + :page-id page-id + :shapes [(:id group)]})] (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (dwc/select-shapes (d/ordered-set (:id group))))))))))

      JQSIQc(McBp%(a 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

  • - +