From d856b9aae345b481bf2da7cb7f7efbe79fecc8af Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 30 Apr 2020 17:14:34 +0200 Subject: [PATCH 01/13] :sparkles: Make config module worker safe. --- frontend/src/uxbox/config.cljs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/uxbox/config.cljs b/frontend/src/uxbox/config.cljs index 3c867bcda8..5df7ff139b 100644 --- a/frontend/src/uxbox/config.cljs +++ b/frontend/src/uxbox/config.cljs @@ -8,17 +8,17 @@ ;; Copyright (c) 2016-2020 Andrey Antukh (ns uxbox.config - (:require [goog.object :as gobj])) + (:require [uxbox.util.object :as obj])) (defn- get-current-origin [] - (let [location (gobj/get goog.global "location")] - (gobj/get location "origin"))) + (let [location (obj/get goog.global "location")] + (obj/get location "origin"))) -(let [config (gobj/get goog.global "uxboxConfig") - public-url (gobj/get config "publicURL" "http://localhost:6060")] +(let [config (obj/get goog.global "uxboxConfig") + public-url (obj/get config "publicURL" "http://localhost:6060")] (def default-language "en") - (def demo-warning (gobj/get config "demoWarning" true)) + (def demo-warning (obj/get config "demoWarning" true)) (def url public-url) (def default-theme "default")) From 7fe7c3da6cfbc60e630a106380dad7b44841ac7c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 30 Apr 2020 17:16:10 +0200 Subject: [PATCH 02/13] :recycle: Refactor html5 history. --- frontend/src/uxbox/main.cljs | 29 ++++----- frontend/src/uxbox/main/fonts.cljs | 2 +- .../main/ui/components/chunked_list.cljs | 4 +- frontend/src/uxbox/util/browser_history.js | 49 +++++++++++++++ frontend/src/uxbox/util/components.cljs | 4 +- .../src/uxbox/util/html/TokenTransformer.js | 60 ------------------- frontend/src/uxbox/util/html/history.cljs | 31 ---------- frontend/src/uxbox/util/router.cljs | 58 ++++++++++++++---- frontend/src/uxbox/util/timers.cljs | 5 +- 9 files changed, 114 insertions(+), 128 deletions(-) create mode 100644 frontend/src/uxbox/util/browser_history.js delete mode 100644 frontend/src/uxbox/util/html/TokenTransformer.js delete mode 100644 frontend/src/uxbox/util/html/history.cljs diff --git a/frontend/src/uxbox/main.cljs b/frontend/src/uxbox/main.cljs index 63bf8a1b0d..aff80f4bcc 100644 --- a/frontend/src/uxbox/main.cljs +++ b/frontend/src/uxbox/main.cljs @@ -20,7 +20,6 @@ [uxbox.main.ui.modal :refer [modal]] [uxbox.main.worker] [uxbox.util.dom :as dom] - [uxbox.util.html.history :as html-history] [uxbox.util.i18n :as i18n] [uxbox.util.theme :as theme] [uxbox.util.router :as rt] @@ -29,38 +28,33 @@ (declare reinit) -(defn- on-navigate +(defn on-navigate [router path] (let [match (rt/match router path) profile (:profile storage)] (cond (and (= path "") (not profile)) - (st/emit! (rt/nav :login)) + (rt/nav :login) (and (= path "") profile) - (st/emit! (rt/nav :dashboard-team {:team-id (:default-team-id profile)})) + (rt/nav :dashboard-team {:team-id (:default-team-id profile)}) (nil? match) - (st/emit! (rt/nav :not-found)) + (rt/nav :not-found) :else - (st/emit! #(assoc % :route match))))) + #(assoc % :route match)))) (defn init-ui [] - (let [router (rt/init ui/routes) - cpath (deref html-history/path)] + (st/emit! (rt/initialize-router ui/routes) + (rt/initialize-history on-navigate)) - (st/emit! #(assoc % :router router)) - (add-watch html-history/path ::main #(on-navigate router %4)) + (when (:profile storage) + (st/emit! udu/fetch-profile)) - (when (:profile storage) - (st/emit! udu/fetch-profile)) - - (mf/mount (mf/element ui/app) (dom/get-element "app")) - (mf/mount (mf/element modal) (dom/get-element "modal")) - - (on-navigate router cpath))) + (mf/mount (mf/element ui/app) (dom/get-element "app")) + (mf/mount (mf/element modal) (dom/get-element "modal"))) (defn ^:export init [] @@ -73,7 +67,6 @@ (defn reinit [] - (remove-watch html-history/path ::main) (mf/unmount (dom/get-element "app")) (mf/unmount (dom/get-element "modal")) (init-ui)) diff --git a/frontend/src/uxbox/main/fonts.cljs b/frontend/src/uxbox/main/fonts.cljs index 2b89e33c62..0780bfd138 100644 --- a/frontend/src/uxbox/main/fonts.cljs +++ b/frontend/src/uxbox/main/fonts.cljs @@ -83,7 +83,7 @@ (group-by :backend (vals db))))) (add-watch fontsdb "main" (fn [_ _ _ db] - (ts/schedule-on-idle #(materialize-fontsview db)))) + (ts/schedule #(materialize-fontsview db)))) (defn register! [backend fonts] diff --git a/frontend/src/uxbox/main/ui/components/chunked_list.cljs b/frontend/src/uxbox/main/ui/components/chunked_list.cljs index e2a13cd93a..ad8d0694e9 100644 --- a/frontend/src/uxbox/main/ui/components/chunked_list.cljs +++ b/frontend/src/uxbox/main/ui/components/chunked_list.cljs @@ -12,7 +12,7 @@ (:require [beicon.core :as rx] [rumext.alpha :as mf] - [uxbox.util.timers :refer [schedule-on-idle]])) + [uxbox.util.timers :refer [schedule]])) (mf/defc chunked-list [{:keys [items children initial-size chunk-size] @@ -34,7 +34,7 @@ :pending-num (- pending-num chunk-size)})) (after-render [state] (when (pos? (:pending-num @state)) - (let [sem (schedule-on-idle (fn [] (swap! state update-state)))] + (let [sem (schedule (fn [] (swap! state update-state)))] #(rx/cancel! sem))))] (let [initial (mf/use-memo initial-state) diff --git a/frontend/src/uxbox/util/browser_history.js b/frontend/src/uxbox/util/browser_history.js new file mode 100644 index 0000000000..74e263b06b --- /dev/null +++ b/frontend/src/uxbox/util/browser_history.js @@ -0,0 +1,49 @@ +/** + * 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 + */ + +"use strict"; + +goog.provide("uxbox.util.browser_history"); +goog.require("goog.history.Html5History"); + + +goog.scope(function() { + const self = uxbox.util.browser_history; + const Html5History = goog.history.Html5History; + + class TokenTransformer { + retrieveToken(pathPrefix, location) { + return location.pathname.substr(pathPrefix.length) + location.search; + } + + createUrl(token, pathPrefix, location) { + return pathPrefix + token; + } + } + + self.create = function() { + const instance = new Html5History(null, new TokenTransformer()); + instance.setUseFragment(true); + return instance; + }; + + self.enable_BANG_ = function(instance) { + instance.setEnabled(true); + }; + + self.disable_BANG_ = function(instance) { + instance.setEnabled(false); + }; + + self.set_token_BANG_ = function(instance, token) { + instance.setToken(token); + } +}); diff --git a/frontend/src/uxbox/util/components.cljs b/frontend/src/uxbox/util/components.cljs index c343910dd6..1b3d78f204 100644 --- a/frontend/src/uxbox/util/components.cljs +++ b/frontend/src/uxbox/util/components.cljs @@ -9,7 +9,7 @@ (:require [beicon.core :as rx] [rumext.alpha :as mf] - [uxbox.util.timers :refer [schedule-on-idle]])) + [uxbox.util.timers :refer [schedule]])) ;; TODO: this file is DEPRECATED (pending deletion) @@ -33,7 +33,7 @@ :pending-num (- pending-num chunk-size)})) (after-render [state] (when (pos? (:pending-num @state)) - (let [sem (schedule-on-idle (fn [] (swap! state update-state)))] + (let [sem (schedule (fn [] (swap! state update-state)))] #(rx/cancel! sem))))] (let [initial (mf/use-memo initial-state) diff --git a/frontend/src/uxbox/util/html/TokenTransformer.js b/frontend/src/uxbox/util/html/TokenTransformer.js deleted file mode 100644 index be81568bbf..0000000000 --- a/frontend/src/uxbox/util/html/TokenTransformer.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * TokenTransformer - * - * @author Paul Anderson , 2018 - * @license BSD License - */ - -goog.provide('uxbox.util.html.TokenTransformer'); -goog.require('goog.history.Html5History'); - -goog.scope(function() { - /** - * A goog.history.Html5History.TokenTransformer implementation that - * includes the query string in the token. - * - * The implementation of token<->url transforms in - * `goog.history.Html5History`, when useFragment is false and no custom - * transformer is supplied, assumes that a token is equivalent to - * `window.location.pathname` minus any configured path prefix. Since - * bide allows constructing urls that include a query string, we want - * to be able to store those as tokens. - * - * Addresses funcool/bide#15. - * - * @constructor - * @implements {goog.history.Html5History.TokenTransformer} - */ - uxbox.util.html.TokenTransformer = function () {}; - - /** - * Retrieves a history token given the path prefix and - * `window.location` object. - * - * @param {string} pathPrefix The path prefix to use when storing token - * in a path; always begin with a slash. - * @param {Location} location The `window.location` object. - * Treat this object as read-only. - * @return {string} token The history token. - */ - uxbox.util.html.TokenTransformer.prototype.retrieveToken = function(pathPrefix, location) { - return location.pathname.substr(pathPrefix.length) + location.search; - }; - - /** - * Creates a URL to be pushed into HTML5 history stack when storing - * token without using hash fragment. - * - * @param {string} token The history token. - * @param {string} pathPrefix The path prefix to use when storing token - * in a path; always begin with a slash. - * @param {Location} location The `window.location` object. - * Treat this object as read-only. - * @return {string} url The complete URL string from path onwards - * (without {@code protocol://host:port} part); must begin with a - * slash. - */ - uxbox.util.html.TokenTransformer.prototype.createUrl = function(token, pathPrefix, location) { - return pathPrefix + token; - }; -}); diff --git a/frontend/src/uxbox/util/html/history.cljs b/frontend/src/uxbox/util/html/history.cljs deleted file mode 100644 index e41c6824e1..0000000000 --- a/frontend/src/uxbox/util/html/history.cljs +++ /dev/null @@ -1,31 +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 uxbox.util.html.history - "A singleton abstraction for the html5 fragment based history." - (:require [goog.events :as e]) - (:import uxbox.util.html.TokenTransformer - goog.history.Html5History - goog.history.EventType)) - -(defonce ^:private +instance+ - (doto (Html5History. nil (TokenTransformer.)) - (.setUseFragment true) - (.setEnabled true))) - -(defonce path (atom (.getToken +instance+))) - -(defonce ^:private +instance-sem+ - (e/listen +instance+ EventType.NAVIGATE - #(reset! path (.-token %)))) - -(defn set-path! - [path] - (.setToken +instance+ path)) - -(defn replace-path! - [path] - (.replaceToken +instance+ path)) diff --git a/frontend/src/uxbox/util/router.cljs b/frontend/src/uxbox/util/router.cljs index d38bf610af..3fee9cce1d 100644 --- a/frontend/src/uxbox/util/router.cljs +++ b/frontend/src/uxbox/util/router.cljs @@ -7,16 +7,19 @@ (ns uxbox.util.router (:refer-clojure :exclude [resolve]) (:require + [beicon.core :as rx] + [rumext.alpha :as mf] [reitit.core :as r] + [goog.events :as e] [cuerdas.core :as str] [potok.core :as ptk] - [uxbox.common.data :as d] - [uxbox.util.html.history :as html-history]) + [uxbox.util.browser-history :as bhistory] + [uxbox.common.data :as d]) (:import goog.Uri goog.Uri.QueryData)) -;; --- API +;; --- Router API (defn- parse-query-data [^QueryData qdata] @@ -50,10 +53,17 @@ (.setQueryData uri qdt) (.toString uri)))))) -(defn init +(defn create [routes] (r/router routes)) +(defn initialize-router + [routes] + (ptk/reify ::initialize-router + ptk/UpdateEvent + (update [_ state] + (assoc state :router (create routes))))) + (defn query-params "Given goog.Uri, read query parameters into Clojure map." [^goog.Uri uri] @@ -63,13 +73,6 @@ (map (juxt keyword #(.get q %))) (into {})))) -(defn navigate! - ([router id] (navigate! router id {} {})) - ([router id params] (navigate! router id params {})) - ([router id params qparams] - (-> (resolve router id params qparams) - (html-history/set-path!)))) - (defn match "Given routing tree and current path, return match with possibly coerced parameters. Return nil if no match found." @@ -87,8 +90,10 @@ (deftype Navigate [id params qparams] ptk/EffectEvent (effect [_ state stream] - (let [router (:router state)] - (navigate! router id params qparams)))) + (let [router (:router state) + history (:history state) + path (resolve router id params qparams)] + (bhistory/set-token! history path)))) (defn nav ([id] (nav id nil nil)) @@ -99,3 +104,30 @@ (def navigate nav) +;; --- History API + +(defn initialize-history + [on-change] + (ptk/reify ::initialize-history + ptk/UpdateEvent + (update [_ state] + (let [history (bhistory/create)] + (assoc state :history history))) + + ptk/WatchEvent + (watch [_ state stream] + (let [stoper (rx/filter (ptk/type? ::initialize-history) stream) + history (:history state) + router (:router state)] + (->> (rx/create (fn [sink] + (let [key (e/listen history "navigate" #(sink (.-token %)))] + (bhistory/enable! history) + (fn [] + (bhistory/disable! history) + (e/unlistenByKey key))))) + (rx/map #(on-change router %)) + (rx/take-until stoper)))))) + + + + diff --git a/frontend/src/uxbox/util/timers.cljs b/frontend/src/uxbox/util/timers.cljs index fb91729fa6..57531058c8 100644 --- a/frontend/src/uxbox/util/timers.cljs +++ b/frontend/src/uxbox/util/timers.cljs @@ -2,7 +2,10 @@ ;; 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 uxbox.util.timers (:require [beicon.core :as rx])) From 8446ad13cb0cd314687d05d348100fc891a0908e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 08:58:17 +0200 Subject: [PATCH 03/13] :bug: Fix minor issues on browser history handling. --- frontend/src/uxbox/main/data/dashboard.cljs | 8 +++-- .../main/data/workspace/notifications.cljs | 3 +- .../main/data/workspace/persistence.cljs | 14 ++++++-- frontend/src/uxbox/util/browser_history.js | 4 +++ frontend/src/uxbox/util/router.cljs | 34 ++++++++++++------- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/frontend/src/uxbox/main/data/dashboard.cljs b/frontend/src/uxbox/main/data/dashboard.cljs index 4574722d2e..8dc715066d 100644 --- a/frontend/src/uxbox/main/data/dashboard.cljs +++ b/frontend/src/uxbox/main/data/dashboard.cljs @@ -141,7 +141,9 @@ ptk/WatchEvent (watch [_ state stream] (->> (rp/query :projects-by-team {:team-id team-id}) - (rx/map projects-fetched))))) + (rx/map projects-fetched) + (rx/catch (fn [error] + (rx/of (rt/nav' :not-authorized)))))))) (defn projects-fetched [projects] @@ -208,7 +210,9 @@ (watch [_ state stream] (let [params {:team-id team-id}] (->> (rp/query :recent-files params) - (rx/map recent-files-fetched)))))) + (rx/map recent-files-fetched) + (rx/catch (fn [e] + (rx/of (rt/nav' :not-authorized))))))))) (defn recent-files-fetched [recent-files] diff --git a/frontend/src/uxbox/main/data/workspace/notifications.cljs b/frontend/src/uxbox/main/data/workspace/notifications.cljs index 5904186695..97b1b0724f 100644 --- a/frontend/src/uxbox/main/data/workspace/notifications.cljs +++ b/frontend/src/uxbox/main/data/workspace/notifications.cljs @@ -72,7 +72,8 @@ (ptk/reify ::finalize ptk/WatchEvent (watch [_ state stream] - (ws/-close (get-in state [:ws file-id])) + (when-let [ws (get-in state [:ws file-id])] + (ws/-close ws)) (rx/of ::finalize)))) ;; --- Handle: Presence diff --git a/frontend/src/uxbox/main/data/workspace/persistence.cljs b/frontend/src/uxbox/main/data/workspace/persistence.cljs index a402623d4d..0c957bb712 100644 --- a/frontend/src/uxbox/main/data/workspace/persistence.cljs +++ b/frontend/src/uxbox/main/data/workspace/persistence.cljs @@ -140,9 +140,17 @@ (rx/first) (rx/map (fn [[file users project pages]] (bundle-fetched file users project pages))) - (rx/catch (fn [{:keys [type] :as error}] - (when (= :not-found type) - (rx/of (rt/nav :not-found))))))))) + (rx/catch (fn [{:keys [type code] :as error}] + (cond + (= :not-found type) + (rx/of (rt/nav' :not-found)) + + (and (= :authentication type) + (= :unauthorized code)) + (rx/of (rt/nav' :not-authorized)) + + :else + (throw error)))))))) (defn- bundle-fetched [file users project pages] diff --git a/frontend/src/uxbox/util/browser_history.js b/frontend/src/uxbox/util/browser_history.js index 74e263b06b..da94b8a37e 100644 --- a/frontend/src/uxbox/util/browser_history.js +++ b/frontend/src/uxbox/util/browser_history.js @@ -46,4 +46,8 @@ goog.scope(function() { self.set_token_BANG_ = function(instance, token) { instance.setToken(token); } + + self.replace_token_BANG_ = function(instance, token) { + instance.replaceToken(token); + } }); diff --git a/frontend/src/uxbox/util/router.cljs b/frontend/src/uxbox/util/router.cljs index 3fee9cce1d..4f747651b3 100644 --- a/frontend/src/uxbox/util/router.cljs +++ b/frontend/src/uxbox/util/router.cljs @@ -87,20 +87,26 @@ ;; --- Navigate (Event) -(deftype Navigate [id params qparams] +(deftype Navigate [id params qparams replace] ptk/EffectEvent (effect [_ state stream] + (prn "Navigate" id params qparams replace) (let [router (:router state) history (:history state) path (resolve router id params qparams)] - (bhistory/set-token! history path)))) + (if ^boolean replace + (bhistory/replace-token! history path) + (bhistory/set-token! history path))))) (defn nav ([id] (nav id nil nil)) ([id params] (nav id params nil)) - ([id params qparams] - {:pre [(keyword? id)]} - (Navigate. id params qparams))) + ([id params qparams] (Navigate. id params qparams false))) + +(defn nav' + ([id] (nav id nil nil)) + ([id params] (nav id params nil)) + ([id params qparams] (Navigate. id params qparams true))) (def navigate nav) @@ -112,6 +118,7 @@ ptk/UpdateEvent (update [_ state] (let [history (bhistory/create)] + (bhistory/enable! history) (assoc state :history history))) ptk/WatchEvent @@ -119,14 +126,15 @@ (let [stoper (rx/filter (ptk/type? ::initialize-history) stream) history (:history state) router (:router state)] - (->> (rx/create (fn [sink] - (let [key (e/listen history "navigate" #(sink (.-token %)))] - (bhistory/enable! history) - (fn [] - (bhistory/disable! history) - (e/unlistenByKey key))))) - (rx/map #(on-change router %)) - (rx/take-until stoper)))))) + (rx/merge + (rx/of (on-change router (.getToken history))) + (->> (rx/create (fn [sink] + (let [key (e/listen history "navigate" #(sink (.-token %)))] + (fn [] + (bhistory/disable! history) + (e/unlistenByKey key))))) + (rx/map #(on-change router %)) + (rx/take-until stoper))))))) From a5592dfe049cc20961db2913d17d0f5097e8eaa5 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 09:14:10 +0200 Subject: [PATCH 04/13] :bug: Show proper profile photo just after login. --- backend/src/uxbox/services/mutations/profile.clj | 3 ++- backend/src/uxbox/services/queries/profile.clj | 2 +- frontend/src/uxbox/main/data/auth.cljs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/uxbox/services/mutations/profile.clj b/backend/src/uxbox/services/mutations/profile.clj index 8d4250bf0d..91d2327df7 100644 --- a/backend/src/uxbox/services/mutations/profile.clj +++ b/backend/src/uxbox/services/mutations/profile.clj @@ -89,7 +89,8 @@ (defn- retrieve-profile-by-email [conn email] - (db/query-one conn [sql:profile-by-email email])) + (-> (db/query-one conn [sql:profile-by-email email]) + (p/then #(images/resolve-media-uris % [:photo :photo-uri])))) ;; --- Mutation: Update Profile (own) diff --git a/backend/src/uxbox/services/queries/profile.clj b/backend/src/uxbox/services/queries/profile.clj index 81c03aa8eb..897295aabb 100644 --- a/backend/src/uxbox/services/queries/profile.clj +++ b/backend/src/uxbox/services/queries/profile.clj @@ -94,4 +94,4 @@ (defn strip-private-attrs "Only selects a publicy visible profile attrs." [profile] - (select-keys profile [:id :fullname :lang :email :created-at :photo :theme])) + (select-keys profile [:id :fullname :lang :email :created-at :photo :theme :photo-uri])) diff --git a/frontend/src/uxbox/main/data/auth.cljs b/frontend/src/uxbox/main/data/auth.cljs index 51551c22c9..a16d62c562 100644 --- a/frontend/src/uxbox/main/data/auth.cljs +++ b/frontend/src/uxbox/main/data/auth.cljs @@ -65,7 +65,7 @@ (ptk/reify ::clear-user-data ptk/UpdateEvent (update [_ state] - (select-keys state [:route :router :session-id])) + (select-keys state [:route :router :session-id :history])) ptk/WatchEvent (watch [_ state s] From 00168d392bd99dda5bf3d75c5aacb537d072fd10 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 11:07:39 +0200 Subject: [PATCH 05/13] :zap: Performance improvements on selection handlers. --- .../src/uxbox/main/ui/dashboard/sidebar.cljs | 2 +- .../uxbox/main/ui/workspace/selection.cljs | 120 +++++++++++------- frontend/src/uxbox/util/geom/shapes.cljs | 3 +- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs index 1d718b30eb..f7c8f5fef1 100644 --- a/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/sidebar.cljs @@ -167,7 +167,7 @@ :type "text" :placeholder (t locale "ds.search.placeholder") :default-value search-term-not-nil - :autoComplete "off" + :auto-complete "off" :on-focus on-search-focus :on-change on-search-change :ref #(when % (set! (.-value %) search-term-not-nil))}] diff --git a/frontend/src/uxbox/main/ui/workspace/selection.cljs b/frontend/src/uxbox/main/ui/workspace/selection.cljs index 10b9492a1d..ae9f1c56a8 100644 --- a/frontend/src/uxbox/main/ui/workspace/selection.cljs +++ b/frontend/src/uxbox/main/ui/workspace/selection.cljs @@ -19,6 +19,7 @@ [uxbox.main.store :as st] [uxbox.main.streams :as ms] [uxbox.util.dom :as dom] + [uxbox.util.object :as obj] [uxbox.util.geom.point :as gpt] [uxbox.util.geom.matrix :as gmt] [uxbox.util.debug :refer [debug?]])) @@ -32,49 +33,74 @@ 60) (mf/defc control-item - [{:keys [class on-click r cy cx] :as props}] - [:circle - {:class-name class - :on-mouse-down on-click - :r r - :style {:fillOpacity "1" - :strokeWidth "1px" + {::mf/wrap-props false} + [props] + (let [class (obj/get props "class") + on-click (obj/get props "on-click") + r (obj/get props "r") + cx (obj/get props "cx") + cy (obj/get props "cy")] + [:circle + {:class-name class + :on-mouse-down on-click + :r r + :style {:fillOpacity "1" + :strokeWidth "1px" :vectorEffect "non-scaling-stroke"} - :fill "#ffffff" - :stroke "#1FDEA7" - :cx cx - :cy cy}]) + :fill "#ffffff" + :stroke "#1FDEA7" + :cx cx + :cy cy}])) (def ^:private rotate-cursor-svg "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20px' height='20px' transform='rotate(%s)' viewBox='0 0 132.292 132.006'%3E%3Cpath d='M85.225 3.48c.034 4.989-.093 9.852-.533 14.78-29.218 5.971-54.975 27.9-63.682 56.683-1.51 2.923-1.431 7.632-3.617 9.546-5.825.472-11.544.5-17.393.45 11.047 15.332 20.241 32.328 32.296 46.725 5.632 1.855 7.155-5.529 10.066-8.533 8.12-12.425 17.252-24.318 24.269-37.482-6.25-.86-12.564-.88-18.857-1.057 5.068-17.605 19.763-31.81 37.091-37.122.181 6.402.206 12.825 1.065 19.184 15.838-9.05 30.899-19.617 45.601-30.257 2.985-4.77-3.574-7.681-6.592-9.791C111.753 17.676 98.475 8.889 85.23.046l-.005 3.435z'/%3E%3Cpath fill='%23fff' d='M92.478 23.995s-1.143.906-6.714 1.923c-29.356 5.924-54.352 30.23-59.717 59.973-.605 3.728-1.09 5.49-1.09 5.49l-11.483-.002s7.84 10.845 10.438 15.486c3.333 4.988 6.674 9.971 10.076 14.912a2266.92 2266.92 0 0019.723-29.326c-5.175-.16-10.35-.343-15.522-.572 3.584-27.315 26.742-50.186 53.91-54.096.306 5.297.472 10.628.631 15.91a2206.462 2206.462 0 0029.333-19.726c-9.75-6.7-19.63-13.524-29.483-20.12z'/%3E%3C/svg%3E\") 10 10, auto") +(defn rotation-cursor + [angle] + (str "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20px' height='20px' transform='rotate(" angle ")' viewBox='0 0 132.292 132.006'%3E%3Cpath d='M85.225 3.48c.034 4.989-.093 9.852-.533 14.78-29.218 5.971-54.975 27.9-63.682 56.683-1.51 2.923-1.431 7.632-3.617 9.546-5.825.472-11.544.5-17.393.45 11.047 15.332 20.241 32.328 32.296 46.725 5.632 1.855 7.155-5.529 10.066-8.533 8.12-12.425 17.252-24.318 24.269-37.482-6.25-.86-12.564-.88-18.857-1.057 5.068-17.605 19.763-31.81 37.091-37.122.181 6.402.206 12.825 1.065 19.184 15.838-9.05 30.899-19.617 45.601-30.257 2.985-4.77-3.574-7.681-6.592-9.791C111.753 17.676 98.475 8.889 85.23.046l-.005 3.435z'/%3E%3Cpath fill='%23fff' d='M92.478 23.995s-1.143.906-6.714 1.923c-29.356 5.924-54.352 30.23-59.717 59.973-.605 3.728-1.09 5.49-1.09 5.49l-11.483-.002s7.84 10.845 10.438 15.486c3.333 4.988 6.674 9.971 10.076 14.912a2266.92 2266.92 0 0019.723-29.326c-5.175-.16-10.35-.343-15.522-.572 3.584-27.315 26.742-50.186 53.91-54.096.306 5.297.472 10.628.631 15.91a2206.462 2206.462 0 0029.333-19.726c-9.75-6.7-19.63-13.524-29.483-20.12z'/%3E%3C/svg%3E\") 10 10, auto")) + +(def rotation-handler-positions + #{:top-left :top-right :bottom-left :bottom-right}) + (mf/defc rotation-handler - [{:keys [cx cy position on-mouse-down rotation zoom]}] - (when (#{:top-left :top-right :bottom-left :bottom-right} position) - (let [size (/ 20 zoom) - rotation (or rotation 0) - x (- cx (if (#{:top-left :bottom-left} position) size 0)) - y (- cy (if (#{:top-left :top-right} position) size 0)) - angle (case position - :top-left 0 - :top-right 90 - :bottom-right 180 - :bottom-left 270)] - [:rect {:style {:cursor (str/format rotate-cursor-svg (str (+ rotation angle)))} - :x x - :y y - :width size - :height size - :fill (if (debug? :rotation-handler) "red" "transparent") - :transform (gmt/rotate-matrix rotation (gpt/point cx cy)) - :on-mouse-down (or on-mouse-down (fn []))}]))) + {::mf/wrap-props false} + [props] + (let [cx (obj/get props "cx") + cy (obj/get props "cy") + position (obj/get props "position") + on-mouse-down (obj/get props "on-mouse-down") + rotation (obj/get props "rotation") + zoom (obj/get props "zoom")] + (when (contains? rotation-handler-positions position) + (let [size (/ 20 zoom) + rotation (or rotation 0) + x (- cx (if (#{:top-left :bottom-left} position) size 0)) + y (- cy (if (#{:top-left :top-right} position) size 0)) + angle (case position + :top-left 0 + :top-right 90 + :bottom-right 180 + :bottom-left 270)] + [:rect {:style {:cursor (rotation-cursor (+ rotation angle))} + :x x + :y y + :width size + :height size + :fill (if (debug? :rotation-handler) "red" "transparent") + :transform (gmt/rotate-matrix rotation (gpt/point cx cy)) + :on-mouse-down (or on-mouse-down (fn []))}])))) (mf/defc controls - [{:keys [shape zoom on-resize on-rotate] :as props}] - (let [{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape) + {::mf/wrap-props false} + [props] + (let [shape (obj/get props "shape") + zoom (obj/get props "zoom") + on-resize (obj/get props "on-resize") + on-rotate (obj/get props "on-rotate") + + {:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape) + radius (if (> (max width height) handler-size-threshold) 4.0 4.0) - transform (geom/transform-matrix shape) - resize-handlers {:top [(+ x (/ width 2 )) y] :right [(+ x width) (+ y (/ height 2))] :bottom [(+ x (/ width 2)) (+ y height)] @@ -83,7 +109,7 @@ :top-right [(+ x width) y] :bottom-left [x (+ y height)] :bottom-right [(+ x width) (+ y height)]}] - + [:g.controls [:rect.main {:transform transform :x (- x 1) :y (- y 1) @@ -95,17 +121,15 @@ (for [[position [cx cy]] resize-handlers] (let [tp (gpt/transform (gpt/point cx cy) transform)] - [:* {:key (str "fragment-" (name position))} - [:& rotation-handler {:key (str "rotation-" (name position)) - :cx (:x tp) + [:* {:key (name position)} + [:& rotation-handler {:cx (:x tp) :cy (:y tp) :position position :rotation (:rotation shape) :zoom zoom :on-mouse-down on-rotate}] - [:& control-item {:key (str "resize-" (name position)) - :class (name position) + [:& control-item {:class (name position) :on-click #(on-resize position %) :r (/ radius zoom) :cx (:x tp) @@ -170,6 +194,7 @@ [{:keys [shapes selected zoom objects] :as props}] (let [shape (geom/selection-rect shapes) shape-center (geom/center shape) + on-resize #(do (dom/stop-propagation %2) (st/emit! (dw/start-resize %1 selected shape objects))) @@ -189,11 +214,18 @@ (let [shape-id (:id shape) shape (geom/transform-shape shape) shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape) - on-resize #(do (dom/stop-propagation %2) - (st/emit! (dw/start-resize %1 #{shape-id} shape' objects))) - on-rotate #(do (dom/stop-propagation %) - (st/emit! (dw/start-rotate [shape])))] + on-resize + (mf/use-callback + (mf/deps shape-id) + #(do (dom/stop-propagation %2) + (st/emit! (dw/start-resize %1 #{shape-id} shape' objects)))) + + on-rotate + (mf/use-callback + (mf/deps shape-id) + #(do (dom/stop-propagation %) + (st/emit! (dw/start-rotate [shape]))))] [:& controls {:shape shape' :zoom zoom :on-rotate on-rotate diff --git a/frontend/src/uxbox/util/geom/shapes.cljs b/frontend/src/uxbox/util/geom/shapes.cljs index 6f08ba9767..f0e20c7772 100644 --- a/frontend/src/uxbox/util/geom/shapes.cljs +++ b/frontend/src/uxbox/util/geom/shapes.cljs @@ -465,7 +465,8 @@ (declare transform-apply-modifiers) -(defn selection-rect-shape [shape] +(defn selection-rect-shape + [shape] (-> shape (transform-apply-modifiers) (shape->rect-shape))) From 2ac42d15b6f7daac25ed68e9b663b7d644abedce Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 18:05:13 +0200 Subject: [PATCH 06/13] :zap: General performance improvements on workspace. --- .../src/uxbox/main/ui/components/defer.cljs | 47 +++++++++++++++++++ frontend/src/uxbox/main/ui/shapes/frame.cljs | 5 +- .../main/ui/workspace/sidebar/layers.cljs | 17 ++++--- .../main/ui/workspace/sidebar/options.cljs | 2 + .../ui/workspace/sidebar/options/fill.cljs | 11 +++++ .../workspace/sidebar/options/measures.cljs | 13 +++-- .../ui/workspace/sidebar/options/rect.cljs | 1 + .../ui/workspace/sidebar/options/stroke.cljs | 17 +++++++ .../src/uxbox/main/ui/workspace/viewport.cljs | 2 + frontend/src/uxbox/util/timers.cljs | 9 ++++ 10 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 frontend/src/uxbox/main/ui/components/defer.cljs diff --git a/frontend/src/uxbox/main/ui/components/defer.cljs b/frontend/src/uxbox/main/ui/components/defer.cljs new file mode 100644 index 0000000000..df75ebaca4 --- /dev/null +++ b/frontend/src/uxbox/main/ui/components/defer.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 uxbox.main.ui.components.defer + (:require + [rumext.alpha :as mf] + [uxbox.common.uuid :as uuid] + [uxbox.util.dom :as dom] + [uxbox.util.timers :as ts] + [goog.events :as events] + [goog.functions :as gf] + [goog.object :as gobj]) + (:import goog.events.EventType + goog.events.KeyCodes)) + +(defn deferred + ([component] (deferred component ts/raf)) + ([component schedule] + (mf/fnc deferred + {::mf/wrap-props false} + [props] + (let [[render? set-render!] (mf/useState false)] + (mf/use-effect + (fn [] (schedule #(set-render! true)))) + (when render? + (mf/create-element component props)))))) + +(defn throttle + [component ms] + (mf/fnc throttle + {::mf/wrap-props false} + [props] + (let [[state set-state] (mf/useState props) + set-state* (mf/use-memo #(gf/throttle set-state ms))] + + (mf/use-effect + nil + (fn [] + (set-state* props))) + + (mf/create-element component state)))) diff --git a/frontend/src/uxbox/main/ui/shapes/frame.cljs b/frontend/src/uxbox/main/ui/shapes/frame.cljs index 76d372537e..711e7c09e5 100644 --- a/frontend/src/uxbox/main/ui/shapes/frame.cljs +++ b/frontend/src/uxbox/main/ui/shapes/frame.cljs @@ -17,9 +17,11 @@ [uxbox.util.geom.shapes :as geom] [uxbox.main.refs :as refs] [uxbox.main.store :as st] + [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.common :as common] [uxbox.util.dom :as dom] + [uxbox.util.timers :as ts] [uxbox.util.interop :as itr] [uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.point :as gpt])) @@ -53,7 +55,8 @@ [shape-wrapper] (let [frame-shape (frame-shape shape-wrapper)] (mf/fnc frame-wrapper - {::mf/wrap [#(mf/memo' % frame-wrapper-memo-equals?)] + {::mf/wrap [#(deferred % ts/schedule-on-idle) + #(mf/memo' % frame-wrapper-memo-equals?)] ::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 77ded54a72..316ae3d038 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -10,21 +10,23 @@ (ns uxbox.main.ui.workspace.sidebar.layers (:require - [rumext.alpha :as mf] [okulary.core :as l] - [uxbox.common.data :as d] + [rumext.alpha :as mf] [uxbox.builtins.icons :as i] - [uxbox.main.data.workspace :as dw] + [uxbox.common.data :as d] + [uxbox.common.uuid :as uuid] [uxbox.main.data.helpers :as dh] + [uxbox.main.data.workspace :as dw] [uxbox.main.refs :as refs] [uxbox.main.store :as st] + [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.hooks :as hooks] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.shapes.icon :as icon] [uxbox.util.dom :as dom] - [uxbox.util.perf :as perf] - [uxbox.common.uuid :as uuid] - [uxbox.util.i18n :as i18n :refer [t]])) + [uxbox.util.timers :as ts] + [uxbox.util.i18n :as i18n :refer [t]] + [uxbox.util.perf :as perf])) ;; --- Helpers @@ -230,7 +232,8 @@ (mf/defc frame-wrapper {::mf/wrap-props false - ::mf/wrap [#(mf/memo' % frame-wrapper-memo-equals?)]} + ::mf/wrap [#(deferred % ts/idle-then-raf) + #(mf/memo' % frame-wrapper-memo-equals?)]} [props] [:> layer-item props]) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs index ddcebccedc..826a5f92c9 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs @@ -15,6 +15,7 @@ [uxbox.main.data.workspace :as udw] [uxbox.main.store :as st] [uxbox.main.refs :as refs] + [uxbox.main.ui.components.defer :refer [throttle]] [uxbox.main.ui.workspace.sidebar.align :refer [align-options]] [uxbox.main.ui.workspace.sidebar.options.frame :as frame] [uxbox.main.ui.workspace.sidebar.options.group :as group] @@ -30,6 +31,7 @@ ;; --- Options (mf/defc shape-options + {::mf/wrap [#(throttle % 60)]} [{:keys [shape] :as props}] [:div (case (:type shape) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/fill.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/fill.cljs index 4fbc633990..f33ac1ae29 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/fill.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/fill.cljs @@ -17,10 +17,21 @@ [uxbox.main.ui.modal :as modal] [uxbox.main.ui.workspace.colorpicker :refer [colorpicker-modal]] [uxbox.util.dom :as dom] + [uxbox.util.object :as obj] [uxbox.util.math :as math] [uxbox.util.i18n :as i18n :refer [tr t]])) +(defn- fill-menu-memo-equals? + [np op] + (let [new-shape (obj/get np "shape") + old-shape (obj/get op "shape")] + (and (identical? (:fill-color new-shape) + (:fill-color old-shape)) + (identical? (:fill-opacity new-shape) + (:fill-opacity old-shape))))) + (mf/defc fill-menu + {::mf/wrap [#(mf/memo' % fill-menu-memo-equals?)]} [{:keys [shape] :as props}] (let [locale (i18n/use-locale) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs index af16028ae4..4f3a881c2c 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/measures.cljs @@ -21,9 +21,10 @@ [uxbox.util.math :as math] [uxbox.util.i18n :refer [t] :as i18n])) - ;; -- User/drawing coords -(defn user-coords-vector [shape] + +(defn user-coords-vector + [shape] (let [{sel-x :x sel-y :y :as selrect} (-> shape gsh/shape->path @@ -35,11 +36,13 @@ dy (- rec-y sel-y)] (gpt/point dx dy))) -(defn user->draw [{:keys [x y width height] :as shape}] +(defn user->draw + [{:keys [x y width height] :as shape}] (let [dv (user-coords-vector shape)] - (-> shape (gsh/move dv)))) + (-> shape (gsh/move dv)))) -(defn draw->user [{:keys [x y width height] :as shape}] +(defn draw->user + [{:keys [x y width height] :as shape}] (let [dv (user-coords-vector shape)] (-> shape (gsh/move (gpt/negate dv))))) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/rect.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/rect.cljs index 5f5fcf7b1a..b13418bd2b 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/rect.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/rect.cljs @@ -15,6 +15,7 @@ [uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-menu]])) (mf/defc options + {::mf/wrap [mf/memo]} [{:keys [shape] :as props}] [:div [:& measures-menu {:shape shape}] diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs index ec2a2a0961..5c98aa6a63 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs @@ -17,10 +17,27 @@ [uxbox.main.ui.modal :as modal] [uxbox.main.ui.workspace.colorpicker :refer [colorpicker-modal]] [uxbox.util.dom :as dom] + [uxbox.util.object :as obj] [uxbox.util.i18n :as i18n :refer [tr t]] [uxbox.util.math :as math])) +(defn- stroke-menu-memo-equals? + [np op] + (let [new-shape (obj/get np "shape") + old-shape (obj/get op "shape")] + (and (identical? (:stroke-style new-shape) + (:stroke-style old-shape)) + (identical? (:stroke-alignment new-shape) + (:stroke-alignment old-shape)) + (identical? (:stroke-width new-shape) + (:stroke-width old-shape)) + (identical? (:stroke-color new-shape) + (:stroke-color old-shape)) + (identical? (:stroke-opacity new-shape) + (:stroke-opacity old-shape))))) + (mf/defc stroke-menu + {::mf/wrap [#(mf/memo' % stroke-menu-memo-equals?)]} [{:keys [shape] :as props}] (let [locale (i18n/use-locale) show-options (not= (:stroke-style shape) :none) diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index 122e571cf2..4ca78dab80 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -23,6 +23,7 @@ [uxbox.main.streams :as ms] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.hooks :as hooks] + [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.shapes :refer [shape-wrapper frame-wrapper]] [uxbox.main.ui.workspace.drawarea :refer [draw-area start-drawing]] [uxbox.main.ui.workspace.grid :refer [grid]] @@ -102,6 +103,7 @@ (-> (rx/take-until stoper ms/mouse-position) (rx/subscribe #(on-point dom reference %)))))))) + ;; --- Viewport (declare remote-user-cursors) diff --git a/frontend/src/uxbox/util/timers.cljs b/frontend/src/uxbox/util/timers.cljs index 57531058c8..ae866918f5 100644 --- a/frontend/src/uxbox/util/timers.cljs +++ b/frontend/src/uxbox/util/timers.cljs @@ -32,3 +32,12 @@ (reify rx/IDisposable (-dispose [_] (js/cancelIdleCallback sem))))) + +(defn raf + [f] + (js/window.requestAnimationFrame f)) + +(defn idle-then-raf + [f] + (schedule-on-idle #(raf f))) + From c2f91097bb86f29461bab8e1acfa2aa2ead6804c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 18:09:48 +0200 Subject: [PATCH 07/13] :zap: Improve performance of recents page rendering. --- frontend/src/uxbox/main/ui/dashboard/grid.cljs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/uxbox/main/ui/dashboard/grid.cljs b/frontend/src/uxbox/main/ui/dashboard/grid.cljs index 17014d12b6..6d3a6dd2eb 100644 --- a/frontend/src/uxbox/main/ui/dashboard/grid.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/grid.cljs @@ -9,15 +9,18 @@ [uxbox.main.ui.modal :as modal] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.confirm :refer [confirm-dialog]] + [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.components.context-menu :refer [context-menu]] [uxbox.util.dom :as dom] [uxbox.util.i18n :as i18n :refer [t tr]] [uxbox.util.router :as rt] + [uxbox.util.timers :as ts] [uxbox.util.time :as dt])) ;; --- Grid Item Thumbnail (mf/defc grid-item-thumbnail + {::mf/wrap [#(deferred % ts/schedule-on-idle)]} [{:keys [file] :as props}] [:div.grid-item-th [:& exports/page-svg {:data (:data file) From 7e643abc15ff1cb9f6a82318e4765f16f04eebd4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 18:17:49 +0200 Subject: [PATCH 08/13] :fire: Remove obsolete code. --- .../main/ui/components/chunked_list.cljs | 44 -- .../src/uxbox/main/ui/dashboard/icons.cljs | 384 ------------------ .../src/uxbox/main/ui/dashboard/library.cljs | 10 - frontend/src/uxbox/util/components.cljs | 43 -- 4 files changed, 481 deletions(-) delete mode 100644 frontend/src/uxbox/main/ui/components/chunked_list.cljs delete mode 100644 frontend/src/uxbox/main/ui/dashboard/icons.cljs delete mode 100644 frontend/src/uxbox/util/components.cljs diff --git a/frontend/src/uxbox/main/ui/components/chunked_list.cljs b/frontend/src/uxbox/main/ui/components/chunked_list.cljs deleted file mode 100644 index ad8d0694e9..0000000000 --- a/frontend/src/uxbox/main/ui/components/chunked_list.cljs +++ /dev/null @@ -1,44 +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 S.L - -(ns uxbox.main.ui.components.chunked-list - "A collection of general purpose utility components." - (:require - [beicon.core :as rx] - [rumext.alpha :as mf] - [uxbox.util.timers :refer [schedule]])) - -(mf/defc chunked-list - [{:keys [items children initial-size chunk-size] - :or {initial-size 30 chunk-size 5} - :as props}] - (letfn [(initial-state [] - (let [total (count items) - size (if (> total initial-size) initial-size total) - current (take size items) - pending (drop size items)] - {:current (vec current) - :pending pending - :pending-num (- total size)})) - - (update-state [{:keys [current pending pending-num] :as state}] - (let [chunk-size (if (> pending-num chunk-size) chunk-size pending-num)] - {:current (into current (take chunk-size pending)) - :pending (drop chunk-size pending) - :pending-num (- pending-num chunk-size)})) - (after-render [state] - (when (pos? (:pending-num @state)) - (let [sem (schedule (fn [] (swap! state update-state)))] - #(rx/cancel! sem))))] - - (let [initial (mf/use-memo initial-state) - state (mf/use-state initial)] - (mf/use-effect nil #(after-render state)) - (for [item (:current @state)] - (children item))))) diff --git a/frontend/src/uxbox/main/ui/dashboard/icons.cljs b/frontend/src/uxbox/main/ui/dashboard/icons.cljs deleted file mode 100644 index 6381a39fad..0000000000 --- a/frontend/src/uxbox/main/ui/dashboard/icons.cljs +++ /dev/null @@ -1,384 +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-2016 Juan de la Cruz -;; Copyright (c) 2015-2019 Andrey Antukh - -(ns uxbox.main.ui.dashboard.icons - (:require - [cljs.spec.alpha :as s] - [cuerdas.core :as str] - [lentes.core :as l] - [rumext.alpha :as mf] - [uxbox.common.data :as d] - [uxbox.common.spec :as us] - [uxbox.builtins.icons :as i] - [uxbox.main.data.icons :as di] - [uxbox.main.store :as st] - [uxbox.main.ui.confirm :refer [confirm-dialog]] - [uxbox.main.ui.dashboard.common :as common] - [uxbox.main.ui.keyboard :as kbd] - [uxbox.main.ui.modal :as modal] - [uxbox.main.ui.shapes.icon :as icon] - [uxbox.util.components :refer [chunked-list]] - [uxbox.util.data :refer [read-string seek]] - [uxbox.util.dom :as dom] - [uxbox.util.i18n :as i18n :refer [tr t]] - [uxbox.util.router :as rt] - [uxbox.util.time :as dt])) - -;; ;; --- Helpers & Constants -;; -;; (def +ordering-options+ -;; {:name "ds.ordering.by-name" -;; :created "ds.ordering.by-creation-date"}) -;; -;; (defn- sort-icons-by -;; [ordering icons] -;; (case ordering -;; :name (sort-by :name icons) -;; :created (reverse (sort-by :created-at icons)) -;; icons)) -;; -;; (defn- contains-term? -;; [phrase term] -;; {:pre [(string? phrase) -;; (string? term)]} -;; (let [term (name term)] -;; (str/includes? (str/lower phrase) (str/trim (str/lower term))))) -;; -;; (defn- filter-icons-by -;; [term icons] -;; (if (str/blank? term) -;; icons -;; (filter #(contains-term? (:name %) term) icons))) -;; -;; ;; --- Component: Grid Header -;; -;; (mf/defc grid-header -;; [{:keys [collection] :as props}] -;; (let [{:keys [id type]} collection -;; on-change #(st/emit! (di/rename-collection id %)) -;; on-deleted #(st/emit! (rt/nav :dashboard-icons nil {:type type})) -;; delete #(st/emit! (di/delete-collection id on-deleted)) -;; on-delete #(modal/show! confirm-dialog {:on-accept delete})] -;; [:& common/grid-header {:value (:name collection) -;; :on-change on-change -;; :on-delete on-delete}])) -;; -;; ;; --- Nav -;; -;; (mf/defc nav-item -;; [{:keys [collection selected?] :as props}] -;; (let [local (mf/use-state {}) -;; {:keys [id type name]} collection -;; editable? (= type :own) -;; -;; on-click -;; (fn [event] -;; (let [type (or type :own)] -;; (st/emit! (rt/nav :dashboard-icons {} {:type type :id id})))) -;; -;; -;; on-input-change -;; (fn [event] -;; (-> (dom/get-target event) -;; (dom/get-value) -;; (swap! local assoc :name))) -;; -;; on-cancel #(swap! local dissoc :name :edit) -;; on-double-click #(when editable? (swap! local assoc :edit true)) -;; -;; on-input-keyup -;; (fn [event] -;; (when (kbd/enter? event) -;; (let [value (-> (dom/get-target event) (dom/get-value))] -;; (st/emit! (di/rename-collection id (str/trim (:name @local)))) -;; (swap! local assoc :edit false))))] -;; -;; [:li {:on-click on-click -;; :on-double-click on-double-click -;; :class-name (when selected? "current")} -;; (if (:edit @local) -;; [:div -;; [:input.element-title {:value (or (:name @local) name) -;; :on-change on-input-change -;; :on-key-down on-input-keyup}] -;; [:span.close {:on-click on-cancel} i/close]] -;; [:span.element-title name])])) -;; -;; -;; (mf/defc nav -;; [{:keys [id type collections] :as props}] -;; (let [locale (i18n/use-locale) -;; own? (= type :own) -;; builtin? (= type :builtin) -;; create-collection #(st/emit! di/create-collection) -;; select-own-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :own})) -;; select-buitin-tab #(st/emit! (rt/nav :dashboard-icons nil {:type :builtin}))] -;; -;; [:div.library-bar -;; [:div.library-bar-inside -;; ;; Tabs -;; [:ul.library-tabs -;; [:li {:class (when own? "current") -;; :on-click select-own-tab} -;; (t locale "ds.your-icons-title")] -;; -;; [:li {:class (when builtin? "current") -;; :on-click select-buitin-tab} -;; (t locale "ds.store-icons-title")]] -;; -;; -;; ;; Collections List -;; [:ul.library-elements -;; (when own? -;; [:li -;; [:a.btn-primary {:on-click #(st/emit! di/create-collection)} -;; (tr "ds.icons-collection.new")]]) -;; (for [item collections] -;; [:& nav-item {:collection item -;; :selected? (= (:id item) id) -;; :key (:id item)}])]]])) -;; -;; -;; ;; (mf/def grid-options-tooltip -;; ;; :mixins [mf/reactive mf/memo] -;; -;; ;; :render -;; ;; (fn [own {:keys [selected on-select title]}] -;; ;; {:pre [(uuid? selected) -;; ;; (fn? on-select) -;; ;; (string? title)]} -;; ;; (let [colls (mf/react collections-iref) -;; ;; colls (->> (vals colls) -;; ;; (filter #(= :own (:type %))) -;; ;; (remove #(= selected (:id %))) -;; ;; (sort-by :name colls)) -;; ;; on-select (fn [event id] -;; ;; (dom/prevent-default event) -;; ;; (dom/stop-propagation event) -;; ;; (on-select id))] -;; ;; [:ul.move-list -;; ;; [:li.title title] -;; ;; [:li -;; ;; [:a {:href "#" :on-click #(on-select % nil)} "Storage"]] -;; ;; (for [{:keys [id name] :as coll} colls] -;; ;; [:li {:key (pr-str id)} -;; ;; [:a {:on-click #(on-select % id)} name]])]))) -;; -;; (mf/defc grid-options -;; [{:keys [id type selected] :as props}] -;; (let [local (mf/use-state {}) -;; delete #(st/emit! di/delete-selected) -;; on-delete #(modal/show! confirm-dialog {:on-accept delete}) -;; -;; ;; (on-toggle-copy [event] -;; ;; (swap! local update :show-copy-tooltip not)) -;; ;; (on-toggle-move [event] -;; ;; (swap! local update :show-move-tooltip not)) -;; ;; (on-copy [selected] -;; ;; (swap! local assoc -;; ;; :show-move-tooltip false -;; ;; :show-copy-tooltip false) -;; ;; (st/emit! (di/copy-selected selected))) -;; ;; (on-move [selected] -;; ;; (swap! local assoc -;; ;; :show-move-tooltip false -;; ;; :show-copy-tooltip false) -;; ;; (st/emit! (di/move-selected selected))) -;; ;; (on-rename [event] -;; ;; (let [selected (first selected)] -;; ;; (st/emit! (di/update-opts :edition selected)))) -;; ] -;; ;; MULTISELECT OPTIONS BAR -;; [:div.multiselect-bar -;; (when (= type :own) -;; ;; If editable -;; [:div.multiselect-nav -;; ;; [:span.move-item.tooltip.tooltip-top -;; ;; {:alt (tr "ds.multiselect-bar.copy") -;; ;; :on-click on-toggle-copy} -;; ;; (when (:show-copy-tooltip @local) -;; ;; [:& grid-options-tooltip {:selected id -;; ;; :title (tr "ds.multiselect-bar.copy-to-library") -;; ;; :on-select on-copy}]) -;; ;; i/copy] -;; ;; [:span.move-item.tooltip.tooltip-top -;; ;; {:alt (tr "ds.multiselect-bar.move") -;; ;; :on-click on-toggle-move} -;; ;; (when (:show-move-tooltip @local) -;; ;; [:& grid-options-tooltip {:selected id -;; ;; :title (tr "ds.multiselect-bar.move-to-library") -;; ;; :on-select on-move}]) -;; ;; i/move] -;; ;; (when (= 1 (count selected)) -;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.rename") -;; ;; :on-click on-rename} -;; ;; i/pencil]) -;; [:span.delete.tooltip.tooltip-top -;; {:alt (tr "ds.multiselect-bar.delete") -;; :on-click on-delete} -;; i/trash]] -;; -;; ;; If not editable -;; ;; [:div.multiselect-nav -;; ;; [:span.move-item.tooltip.tooltip-top {:alt (tr "ds.multiselect-bar.copy") -;; ;; :on-click on-toggle-copy} -;; ;; (when (:show-copy-tooltip @local) -;; ;; [:& grid-options-tooltip {:selected id -;; ;; :title (tr "ds.multiselect-bar.copy-to-library") -;; ;; :on-select on-copy}]) -;; ;; i/organize]] -;; )])) -;; -;; ;; --- Grid Form -;; -;; (mf/defc grid-form -;; [{:keys [id type uploading?] :as props}] -;; (let [locale (i18n/use-locale) -;; input (mf/use-ref nil) -;; on-click #(dom/click (mf/ref-node input)) -;; on-select #(st/emit! (->> (dom/get-target %) -;; (dom/get-files) -;; (array-seq) -;; (di/create-icons id)))] -;; [:div.grid-item.add-project {:on-click on-click} -;; (if uploading? -;; [:div i/loader-pencil] -;; [:span (t locale "ds.icon-new")]) -;; [:input.upload-icon-input -;; {:style {:display "none"} -;; :multiple true -;; :ref input -;; :value "" -;; :accept "icon/svg+xml" -;; :type "file" -;; :on-change on-select}]])) -;; -;; ;; --- Grid Item -;; -;; (mf/defc grid-item -;; [{:keys [icon selected? edition?] :as props}] -;; (let [toggle-selection #(st/emit! (if selected? -;; (di/deselect-icon (:id icon)) -;; (di/select-icon (:id icon)))) -;; on-blur -;; (fn [event] -;; (let [target (dom/get-target event) -;; name (dom/get-value target)] -;; (st/emit! (di/update-opts :edition false) -;; (di/rename-icon (:id icon) name)))) -;; -;; on-key-down -;; (fn [event] -;; (when (kbd/enter? event) -;; (on-blur event))) -;; -;; ignore-click -;; (fn [event] -;; (dom/stop-propagation event) -;; (dom/prevent-default event)) -;; -;; on-edit -;; (fn [event] -;; (dom/stop-propagation event) -;; (dom/prevent-default event) -;; (st/emit! (di/update-opts :edition (:id icon))))] -;; -;; [:div.grid-item.small-item.project-th -;; [:div.input-checkbox.check-primary -;; [:input {:type "checkbox" -;; :id (:id icon) -;; :on-change toggle-selection -;; :checked selected?}] -;; [:label {:for (:id icon)}]] -;; [:span.grid-item-icon -;; [:& icon/icon-svg {:shape icon}]] -;; [:div.item-info {:on-click ignore-click} -;; (if edition? -;; [:input.element-name {:type "text" -;; :auto-focus true -;; :on-key-down on-key-down -;; :on-blur on-blur -;; :on-click on-edit -;; :default-value (:name icon)}] -;; [:h3 {:on-double-click on-edit} -;; (:name icon)]) -;; (str (tr "ds.uploaded-at" (dt/format (:created-at icon) "dd/MM/yyyy")))]])) -;; -;; ;; --- Grid -;; -;; (def icons-iref -;; (-> (comp (l/key :icons) (l/lens vals)) -;; (l/derive st/state))) -;; -;; (mf/defc grid -;; [{:keys [id type collection opts] :as props}] -;; (let [editable? (= type :own) -;; icons (->> (mf/deref icons-iref) -;; (filter-icons-by (:filter opts "")) -;; (sort-icons-by (:order opts :name)))] -;; [:div.dashboard-grid-content -;; [:div.dashboard-grid-row -;; (when editable? -;; [:& grid-form {:id id :type type :uploading? (:uploading opts)}]) -;; -;; [:& chunked-list {:items icons -;; :initial-size 30 -;; :chunk-size 30 -;; :key (str type id (count icons))} -;; (fn [icon] -;; [:& grid-item {:icon icon -;; :key (:id icon) -;; :selected (contains? (:selected opts) (:id icon)) -;; :edition? (= (:edition opts) (:id icon))}])]]])) -;; -;; ;; --- Content -;; -;; (def opts-iref -;; (-> (l/key :dashboard-icons) -;; (l/derive st/state))) -;; -;; (mf/defc content -;; [{:keys [id type collection] :as props}] -;; (let [{:keys [selected] :as opts} (mf/deref opts-iref)] -;; [:section.dashboard-grid.library -;; (when collection -;; [:& grid-header {:collection collection}]) -;; (if collection -;; [:& grid {:id id :type type :collection collection :opts opts}] -;; [:span "EMPTY STATE TODO"]) -;; (when-not (empty? selected) -;; #_[:& grid-options {:id id :type type :selected (:selected opts)}])])) -;; -;; ;; --- Icons Page -;; -;; (def collections-iref -;; (-> (l/key :icons-collections) -;; (l/derive st/state))) -;; -;; (mf/defc icons-page -;; [{:keys [id type] :as props}] -;; (let [type (or type :own) -;; collections (mf/deref collections-iref) -;; collections (cond->> (vals collections) -;; (= type :own) (filter #(= :own (:type %))) -;; (= type :builtin) (filter #(= :builtin (:type %))) -;; true (sort-by :created-at)) -;; -;; collection (cond -;; (uuid? id) (seek #(= id (:id %)) collections) -;; :else (first collections)) -;; -;; id (:id collection)] -;; -;; (mf/use-effect #(st/emit! di/fetch-collections)) -;; (mf/use-effect -;; {:fn #(when id (st/emit! (di/initialize id))) -;; :deps (mf/deps id)}) -;; -;; [:section.dashboard-content -;; [:& nav {:type type :id id :collections collections}] -;; [:& content {:type type :id id :collection collection}]])) diff --git a/frontend/src/uxbox/main/ui/dashboard/library.cljs b/frontend/src/uxbox/main/ui/dashboard/library.cljs index a8b3d7e2d0..a6e4d37654 100644 --- a/frontend/src/uxbox/main/ui/dashboard/library.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/library.cljs @@ -377,16 +377,6 @@ ) }] [:* - ;; TODO: Fix the chunked list - #_[:& chunked-list {:items items - :initial-size 30 - :chunk-size 30} - (fn [item] - (let [item (assoc item :key (:id item))] - (case section - :icons [:& library-icon-card item] - :images [:& library-image-card item] - :palettes [:& library-color-card item ])))] (if (> (count items) 0) [:div.library-page-cards-container (for [item items] diff --git a/frontend/src/uxbox/util/components.cljs b/frontend/src/uxbox/util/components.cljs deleted file mode 100644 index 1b3d78f204..0000000000 --- a/frontend/src/uxbox/util/components.cljs +++ /dev/null @@ -1,43 +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 uxbox.util.components - "A collection of general purpose utility components." - (:require - [beicon.core :as rx] - [rumext.alpha :as mf] - [uxbox.util.timers :refer [schedule]])) - -;; TODO: this file is DEPRECATED (pending deletion) - -(mf/defc chunked-list - [{:keys [items children initial-size chunk-size] - :or {initial-size 30 chunk-size 5} - :as props}] - (letfn [(initial-state [] - (let [total (count items) - size (if (> total initial-size) initial-size total) - current (take size items) - pending (drop size items)] - {:current (vec current) - :pending pending - :pending-num (- total size)})) - - (update-state [{:keys [current pending pending-num] :as state}] - (let [chunk-size (if (> pending-num chunk-size) chunk-size pending-num)] - {:current (into current (take chunk-size pending)) - :pending (drop chunk-size pending) - :pending-num (- pending-num chunk-size)})) - (after-render [state] - (when (pos? (:pending-num @state)) - (let [sem (schedule (fn [] (swap! state update-state)))] - #(rx/cancel! sem))))] - - (let [initial (mf/use-memo initial-state) - state (mf/use-state initial)] - (mf/use-effect nil #(after-render state)) - (for [item (:current @state)] - (children item))))) From 2ac8d68e0175ea5b607500f40a118c7d46a81301 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 18:56:51 +0200 Subject: [PATCH 09/13] :arrow_up: Update npm deps. --- frontend/package-lock.json | 968 +++++++++++-------------------------- 1 file changed, 285 insertions(+), 683 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1351bce321..1e62dd2c69 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@babel/runtime-corejs3": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz", - "integrity": "sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz", + "integrity": "sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA==", "requires": { "core-js-pure": "^3.0.0", "regenerator-runtime": "^0.13.4" @@ -18,11 +18,6 @@ "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" }, - "@types/debounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.0.tgz", - "integrity": "sha512-bWG5wapaWgbss9E238T0R6bfo5Fh3OkeoSt245CM7JJwVwpw6MEBCbIxLq5z8KzsE3uJhzcIuQkyiZmzV3M/Dw==" - }, "@types/esrever": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@types/esrever/-/esrever-0.2.0.tgz", @@ -33,6 +28,11 @@ "resolved": "https://registry.npmjs.org/@types/is-hotkey/-/is-hotkey-0.1.1.tgz", "integrity": "sha512-QzVKww91fJv/KzARJBS/Im5GS2A8iE64E1HxOed72EmYOvPLG4PBw77QCIUjFl7VwWB3G/SVrxsHedJD/wtn1A==" }, + "@types/lodash": { + "version": "4.14.150", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.150.tgz", + "integrity": "sha512-kMNLM5JBcasgYscD9x/Gvr6lTAv2NVgsKtet/hm93qMyf/D1pt+7jeEZklKJKxMVmXjxbRVQQGfqDSfipYCO6w==" + }, "@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", @@ -40,9 +40,9 @@ "dev": true }, "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -453,6 +453,12 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -477,16 +483,6 @@ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bintrees": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", @@ -540,6 +536,12 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -627,13 +629,13 @@ } }, "browserslist": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", - "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", + "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001038", - "electron-to-chromium": "^1.3.390", + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", "node-releases": "^1.1.53", "pkg-up": "^2.0.0" } @@ -699,6 +701,14 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "camelcase": { @@ -708,9 +718,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001042", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001042.tgz", - "integrity": "sha512-igMQ4dlqnf4tWv0xjaaE02op9AJ2oQzXKjWf4EuAHFN694Uo9/EfPVIPJcmn2WkU9RqozCxx5e2KPcVClHDbDw==", + "version": "1.0.30001048", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz", + "integrity": "sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg==", "dev": true }, "caseless": { @@ -739,7 +749,6 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", - "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -788,6 +797,12 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -1020,6 +1035,23 @@ "requires": { "each-props": "^1.3.0", "is-plain-object": "^2.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "core-js-pure": { @@ -1211,11 +1243,6 @@ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, - "debounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", - "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1307,6 +1334,12 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -1425,6 +1458,23 @@ "requires": { "is-plain-object": "^2.0.1", "object.defaults": "^1.1.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "ecc-jsbn": { @@ -1438,9 +1488,9 @@ } }, "electron-to-chromium": { - "version": "1.3.412", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.412.tgz", - "integrity": "sha512-4bVdSeJScR8fT7ERveLWbxemY5uXEHVseqMRyORosiKcTUSGtVwBkV8uLjXCqoFLeImA57Z9hbz3TOid01U4Hw==", + "version": "1.3.426", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.426.tgz", + "integrity": "sha512-sdQ7CXQbFflKY5CU63ra+kIYq9F7d1OqI33856qJZxTrwo0sLASdmoRl9lWpGrQDS9Nk/RFliQWd3PPDrZ+Meg==", "dev": true }, "elliptic": { @@ -1710,6 +1760,21 @@ "requires": { "is-plain-object": "^2.0.4" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -1852,13 +1917,6 @@ "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==", "dev": true }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1914,6 +1972,23 @@ "object.defaults": "^1.1.0", "object.pick": "^1.2.0", "parse-filepath": "^1.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "flagged-respawn": { @@ -2006,557 +2081,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", - "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "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" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2706,9 +2230,9 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "growl": { @@ -2754,6 +2278,12 @@ "v8flags": "^3.0.1", "yargs": "^7.1.0" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -2904,6 +2434,14 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "has-values": { @@ -2928,13 +2466,33 @@ } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + } } }, "hash.js": { @@ -3215,12 +2773,11 @@ } }, "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", "requires": { - "isobject": "^3.0.1" + "isobject": "^4.0.0" } }, "is-regex": { @@ -3302,10 +2859,9 @@ "dev": true }, "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" }, "isstream": { "version": "0.1.2", @@ -3466,6 +3022,23 @@ "object.map": "^1.0.0", "rechoir": "^0.6.2", "resolve": "^1.1.7" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "load-json-file": { @@ -3792,18 +3365,18 @@ } }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "dev": true, "requires": { - "mime-db": "1.43.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -3857,6 +3430,21 @@ "requires": { "is-plain-object": "^2.0.4" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -3957,13 +3545,6 @@ "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", "dev": true }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -4167,6 +3748,14 @@ "dev": true, "requires": { "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "object.assign": { @@ -4191,6 +3780,14 @@ "array-slice": "^1.0.0", "for-own": "^1.0.0", "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "object.getownpropertydescriptors": { @@ -4220,6 +3817,14 @@ "dev": true, "requires": { "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "object.reduce": { @@ -4558,9 +4163,9 @@ } }, "postcss-value-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", - "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, "pretty-hrtime": { @@ -4949,9 +4554,9 @@ "dev": true }, "resolve": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.0.tgz", - "integrity": "sha512-LarL/PIKJvc09k1jaeT4kQb/8/7P+qV4qSnN2K80AES+OHdfZELAKVOBjxsvtToT/uLOfFbvYvKfZmV8cee7nA==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -5037,9 +4642,9 @@ "dev": true }, "sass": { - "version": "1.26.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.3.tgz", - "integrity": "sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw==", + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.5.tgz", + "integrity": "sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" @@ -5109,6 +4714,21 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -5129,9 +4749,9 @@ } }, "shadow-cljs": { - "version": "2.8.96", - "resolved": "https://registry.npmjs.org/shadow-cljs/-/shadow-cljs-2.8.96.tgz", - "integrity": "sha512-0vt7go2x3Ehm/YHu20QRbPkvH5JVy4ReLn/0addQvhdGI8EFmvYJS+v+o2mazl0Nip3VUoyz4z0zT1ncWgh/3g==", + "version": "2.8.109", + "resolved": "https://registry.npmjs.org/shadow-cljs/-/shadow-cljs-2.8.109.tgz", + "integrity": "sha512-xUN5kBYgyk2OVv3Gz9/dxJdDNoImskYg6VNLpHkubCG46Q1Lv9tymd11Hyekka6WWk24QCNSVIyPta82txZGfQ==", "dev": true, "requires": { "node-libs-browser": "^2.0.0", @@ -5258,59 +4878,29 @@ } }, "slate": { - "version": "0.57.1", - "resolved": "https://registry.npmjs.org/slate/-/slate-0.57.1.tgz", - "integrity": "sha512-av95C0zbsi0+khfOuyQlpZy0Q3Pqqh0loCusGGi0Wlb/J8OUBAyK/a5EgTfE0zK4pmjtEBnPksfBuVilg5jrNg==", + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.57.2.tgz", + "integrity": "sha512-qxx9iwNmN3fn13hPbwh1p65aNLCgpHMMK/XXLX7rBVv+GT2UFys9tU8OK6FyUF/lU2uEJ++sScDu8cHjzwLefw==", "requires": { "@types/esrever": "^0.2.0", "esrever": "^0.2.0", "immer": "^5.0.0", "is-plain-object": "^3.0.0", "tiny-warning": "^1.0.3" - }, - "dependencies": { - "is-plain-object": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", - "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", - "requires": { - "isobject": "^4.0.0" - } - }, - "isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" - } } }, "slate-react": { - "version": "0.57.1", - "resolved": "https://registry.npmjs.org/slate-react/-/slate-react-0.57.1.tgz", - "integrity": "sha512-W+M+YEcqBvuJD2xoU1gKgGbvhv6shwYJ5OOjPF8ZPEokUvGJh81Egxf65ZnnKxJejodsERdlwc2rRjpRphx2LQ==", + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/slate-react/-/slate-react-0.57.2.tgz", + "integrity": "sha512-fg91E7XISMnFfoHB8vPbbaKoTDpaTfE+iwnG9i6EzbIfwNysz8XvLDpRW3XExm1ZtAfhEKB3Um8nPMtGaugVRg==", "requires": { - "@types/debounce": "^1.2.0", "@types/is-hotkey": "^0.1.1", - "debounce": "^1.2.0", + "@types/lodash": "^4.14.149", "direction": "^1.0.3", "is-hotkey": "^0.1.6", "is-plain-object": "^3.0.0", + "lodash": "^4.17.4", "scroll-into-view-if-needed": "^2.2.20" - }, - "dependencies": { - "is-plain-object": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", - "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", - "requires": { - "isobject": "^4.0.0" - } - }, - "isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" - } } }, "snapdragon": { @@ -5403,6 +4993,12 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -5445,9 +5041,9 @@ } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -5476,9 +5072,9 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { @@ -6274,6 +5870,12 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, From df8451c4e3ef6a62472179518313b7d326ea958f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 May 2020 18:57:09 +0200 Subject: [PATCH 10/13] :zap: Throttle layers rendering. --- .../main/ui/workspace/sidebar/layers.cljs | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 316ae3d038..7510ae721e 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -19,10 +19,11 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.refs :as refs] [uxbox.main.store :as st] - [uxbox.main.ui.components.defer :refer [deferred]] + [uxbox.main.ui.components.defer :refer [throttle deferred]] [uxbox.main.ui.hooks :as hooks] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.shapes.icon :as icon] + [uxbox.util.object :as obj] [uxbox.util.dom :as dom] [uxbox.util.timers :as ts] [uxbox.util.i18n :as i18n :refer [t]] @@ -237,24 +238,11 @@ [props] [:> layer-item props]) -(def ^:private layers-objects - (letfn [(strip-data [obj] - (select-keys obj [:id :name :blocked :hidden :shapes :type])) - (selector [{:keys [objects] :as data}] - (persistent! - (reduce-kv (fn [res id obj] - (assoc! res id (strip-data obj))) - (transient {}) - objects)))] - (l/derived selector refs/workspace-data =))) - (mf/defc layers-tree - {::mf/wrap [mf/memo]} - [] + {::mf/wrap [#(mf/memo % =)]} + [{:keys [objects] :as props}] (let [selected (mf/deref refs/selected-shapes) - objects (mf/deref layers-objects) root (get objects uuid/zero)] - ;; [:& perf/profiler {:label "layers-tree" :enabled false} [:ul.element-list (for [[index id] (reverse (d/enumerate (:shapes root)))] (let [obj (get objects id)] @@ -272,16 +260,30 @@ :objects objects :key id}])))])) +(defn- strip-objects + [objects] + (let [strip-data #(select-keys % [:id :name :blocked :hidden :shapes :type])] + (persistent! + (reduce-kv (fn [res id obj] + (assoc! res id (strip-data obj))) + (transient {}) + objects)))) + +(mf/defc layers-tree-wrapper + {::mf/wrap-props false + ::mf/wrap [#(throttle % 200) mf/memo]} + [props] + (let [objects (obj/get props "objects") + objects (strip-objects objects)] + [:& layers-tree {:objects objects}])) ;; --- Layers Toolbox -;; NOTE: we need to consider using something like react window for -;; only render visible items instead of all. - (mf/defc layers-toolbox {:wrap [mf/memo]} [{:keys [page] :as props}] - (let [locale (i18n/use-locale) + (let [locale (mf/deref i18n/locale) + data (mf/deref refs/workspace-data) on-click #(st/emit! (dw/toggle-layout-flag :layers))] [:div#layers.tool-window [:div.tool-window-bar @@ -289,4 +291,5 @@ [:span (:name page)] #_[:div.tool-window-close {:on-click on-click} i/close]] [:div.tool-window-content - [:& layers-tree {:key (:id page)}]]])) + [:& layers-tree-wrapper {:key (:id page) + :objects (:objects data)}]]])) From 80dcf587bf07d70cc5b46dac1c6cc1c71deab9a3 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 May 2020 09:38:41 +0200 Subject: [PATCH 11/13] :arrow_up: Update to the latest version of rumext. --- frontend/deps.edn | 2 +- .../src/uxbox/main/ui/components/defer.cljs | 47 ------------------- .../src/uxbox/main/ui/dashboard/grid.cljs | 3 +- frontend/src/uxbox/main/ui/shapes/frame.cljs | 5 +- .../main/ui/workspace/sidebar/layers.cljs | 7 ++- .../main/ui/workspace/sidebar/options.cljs | 3 +- .../src/uxbox/main/ui/workspace/viewport.cljs | 1 - 7 files changed, 8 insertions(+), 60 deletions(-) delete mode 100644 frontend/src/uxbox/main/ui/components/defer.cljs diff --git a/frontend/deps.edn b/frontend/deps.edn index 75ed4f72f3..a31a8480d5 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -17,7 +17,7 @@ funcool/okulary {:mvn/version "2020.04.14-0"} funcool/potok {:mvn/version "2.8.0-SNAPSHOT"} funcool/promesa {:mvn/version "5.1.0"} - funcool/rumext {:mvn/version "2020.04.14-1"} + funcool/rumext {:mvn/version "2020.05.04-0"} } :aliases {:dev diff --git a/frontend/src/uxbox/main/ui/components/defer.cljs b/frontend/src/uxbox/main/ui/components/defer.cljs deleted file mode 100644 index df75ebaca4..0000000000 --- a/frontend/src/uxbox/main/ui/components/defer.cljs +++ /dev/null @@ -1,47 +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 uxbox.main.ui.components.defer - (:require - [rumext.alpha :as mf] - [uxbox.common.uuid :as uuid] - [uxbox.util.dom :as dom] - [uxbox.util.timers :as ts] - [goog.events :as events] - [goog.functions :as gf] - [goog.object :as gobj]) - (:import goog.events.EventType - goog.events.KeyCodes)) - -(defn deferred - ([component] (deferred component ts/raf)) - ([component schedule] - (mf/fnc deferred - {::mf/wrap-props false} - [props] - (let [[render? set-render!] (mf/useState false)] - (mf/use-effect - (fn [] (schedule #(set-render! true)))) - (when render? - (mf/create-element component props)))))) - -(defn throttle - [component ms] - (mf/fnc throttle - {::mf/wrap-props false} - [props] - (let [[state set-state] (mf/useState props) - set-state* (mf/use-memo #(gf/throttle set-state ms))] - - (mf/use-effect - nil - (fn [] - (set-state* props))) - - (mf/create-element component state)))) diff --git a/frontend/src/uxbox/main/ui/dashboard/grid.cljs b/frontend/src/uxbox/main/ui/dashboard/grid.cljs index 6d3a6dd2eb..059ae22ec9 100644 --- a/frontend/src/uxbox/main/ui/dashboard/grid.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/grid.cljs @@ -9,7 +9,6 @@ [uxbox.main.ui.modal :as modal] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.confirm :refer [confirm-dialog]] - [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.components.context-menu :refer [context-menu]] [uxbox.util.dom :as dom] [uxbox.util.i18n :as i18n :refer [t tr]] @@ -20,7 +19,7 @@ ;; --- Grid Item Thumbnail (mf/defc grid-item-thumbnail - {::mf/wrap [#(deferred % ts/schedule-on-idle)]} + {::mf/wrap [#(mf/deferred % ts/schedule-on-idle)]} [{:keys [file] :as props}] [:div.grid-item-th [:& exports/page-svg {:data (:data file) diff --git a/frontend/src/uxbox/main/ui/shapes/frame.cljs b/frontend/src/uxbox/main/ui/shapes/frame.cljs index 711e7c09e5..7aa4fd8a4c 100644 --- a/frontend/src/uxbox/main/ui/shapes/frame.cljs +++ b/frontend/src/uxbox/main/ui/shapes/frame.cljs @@ -17,7 +17,6 @@ [uxbox.util.geom.shapes :as geom] [uxbox.main.refs :as refs] [uxbox.main.store :as st] - [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.common :as common] [uxbox.util.dom :as dom] @@ -55,8 +54,8 @@ [shape-wrapper] (let [frame-shape (frame-shape shape-wrapper)] (mf/fnc frame-wrapper - {::mf/wrap [#(deferred % ts/schedule-on-idle) - #(mf/memo' % frame-wrapper-memo-equals?)] + {::mf/wrap [#(mf/memo' % frame-wrapper-memo-equals?) + #(mf/deferred % ts/schedule-on-idle)] ::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 7510ae721e..3cab83dac2 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -19,7 +19,6 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.refs :as refs] [uxbox.main.store :as st] - [uxbox.main.ui.components.defer :refer [throttle deferred]] [uxbox.main.ui.hooks :as hooks] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.shapes.icon :as icon] @@ -233,8 +232,8 @@ (mf/defc frame-wrapper {::mf/wrap-props false - ::mf/wrap [#(deferred % ts/idle-then-raf) - #(mf/memo' % frame-wrapper-memo-equals?)]} + ::mf/wrap [#(mf/memo' % frame-wrapper-memo-equals?) + #(mf/deferred % ts/idle-then-raf)]} [props] [:> layer-item props]) @@ -271,7 +270,7 @@ (mf/defc layers-tree-wrapper {::mf/wrap-props false - ::mf/wrap [#(throttle % 200) mf/memo]} + ::mf/wrap [mf/memo #(mf/throttle % 200)]} [props] (let [objects (obj/get props "objects") objects (strip-objects objects)] diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs index 826a5f92c9..40270cf79a 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options.cljs @@ -15,7 +15,6 @@ [uxbox.main.data.workspace :as udw] [uxbox.main.store :as st] [uxbox.main.refs :as refs] - [uxbox.main.ui.components.defer :refer [throttle]] [uxbox.main.ui.workspace.sidebar.align :refer [align-options]] [uxbox.main.ui.workspace.sidebar.options.frame :as frame] [uxbox.main.ui.workspace.sidebar.options.group :as group] @@ -31,7 +30,7 @@ ;; --- Options (mf/defc shape-options - {::mf/wrap [#(throttle % 60)]} + {::mf/wrap [#(mf/throttle % 60)]} [{:keys [shape] :as props}] [:div (case (:type shape) diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index 4ca78dab80..c01bbe909b 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -23,7 +23,6 @@ [uxbox.main.streams :as ms] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.hooks :as hooks] - [uxbox.main.ui.components.defer :refer [deferred]] [uxbox.main.ui.shapes :refer [shape-wrapper frame-wrapper]] [uxbox.main.ui.workspace.drawarea :refer [draw-area start-drawing]] [uxbox.main.ui.workspace.grid :refer [grid]] From af43eca3999bd9834b8931aef26610495d70475f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 May 2020 10:42:43 +0200 Subject: [PATCH 12/13] :bug: Remove not necessary use-callback usage. --- frontend/src/uxbox/main/ui/workspace/selection.cljs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/frontend/src/uxbox/main/ui/workspace/selection.cljs b/frontend/src/uxbox/main/ui/workspace/selection.cljs index ae9f1c56a8..db5f85af2d 100644 --- a/frontend/src/uxbox/main/ui/workspace/selection.cljs +++ b/frontend/src/uxbox/main/ui/workspace/selection.cljs @@ -216,16 +216,12 @@ shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape) on-resize - (mf/use-callback - (mf/deps shape-id) - #(do (dom/stop-propagation %2) - (st/emit! (dw/start-resize %1 #{shape-id} shape' objects)))) + #(do (dom/stop-propagation %2) + (st/emit! (dw/start-resize %1 #{shape-id} shape' objects))) on-rotate - (mf/use-callback - (mf/deps shape-id) - #(do (dom/stop-propagation %) - (st/emit! (dw/start-rotate [shape]))))] + #(do (dom/stop-propagation %) + (st/emit! (dw/start-rotate [shape])))] [:& controls {:shape shape' :zoom zoom :on-rotate on-rotate From 0a793723056a69c8d405e84612271c2dbdb8b446 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 4 May 2020 12:36:56 +0200 Subject: [PATCH 13/13] :fire: Remove unused prn. --- frontend/src/uxbox/util/router.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/uxbox/util/router.cljs b/frontend/src/uxbox/util/router.cljs index 4f747651b3..b889be5f7d 100644 --- a/frontend/src/uxbox/util/router.cljs +++ b/frontend/src/uxbox/util/router.cljs @@ -90,7 +90,6 @@ (deftype Navigate [id params qparams replace] ptk/EffectEvent (effect [_ state stream] - (prn "Navigate" id params qparams replace) (let [router (:router state) history (:history state) path (resolve router id params qparams)]