0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-12 18:18:24 -05:00

🎉 Refactor, performance improvements

This commit is contained in:
alonso.torres 2020-09-10 16:24:59 +02:00 committed by Alonso Torres
parent 726cdb9a27
commit e737ec0311
7 changed files with 165 additions and 98 deletions

View file

@ -18,12 +18,12 @@ goog.scope(function() {
const self = app.common.uuid_impl;
const fill = (() => {
if (typeof window === "object") {
if (typeof window === "object" && typeof window.crypto !== "undefined") {
return (buf) => {
window.crypto.getRandomValues(buf);
return buf;
};
} else if (typeof self === "object") {
} else if (typeof self === "object" && typeof self.crypto !== "undefined") {
return (buf) => {
self.crypto.getRandomValues(buf);
return buf;

View file

@ -10,13 +10,26 @@
(ns app.main.data.fetch
(:require
[promesa.core :as p]
[app.util.object :as obj]))
[potok.core :as ptk]
[okulary.core :as l]
[app.util.object :as obj]
[app.main.store :as st]))
(defn pending-ref []
(l/derived ::to-fetch st/state))
(defn add [to-fetch id]
(let [to-fetch (or to-fetch (hash-set))]
(conj to-fetch id)))
(defn fetch-as-data-uri [url]
(-> (js/fetch url)
(p/then (fn [res] (.blob res)))
(p/then (fn [blob]
(let [reader (js/FileReader.)]
(p/create (fn [resolve reject]
(obj/set! reader "onload" #(resolve [url (.-result reader)]))
(.readAsDataURL reader blob))))))))
(let [id (random-uuid)]
(st/emit! (fn [state] (update state ::to-fetch add id)))
(-> (js/fetch url)
(p/then (fn [res] (.blob res)))
(p/then (fn [blob]
(let [reader (js/FileReader.)]
(p/create (fn [resolve reject]
(obj/set! reader "onload" #(resolve [url (.-result reader)]))
(.readAsDataURL reader blob))))))
(p/finally #(st/emit! (fn [state] (update state ::to-fetch disj id)))))))

View file

@ -0,0 +1,14 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.main.ui.context
(:require
[rumext.alpha :as mf]))
(def embed-ctx (mf/create-context false))

View file

@ -14,6 +14,7 @@
[app.common.geom.shapes :as geom]
[app.main.ui.shapes.attrs :as attrs]
[app.util.object :as obj]
[app.main.ui.context :as muc]
[app.main.data.fetch :as df]
[promesa.core :as p]))
@ -24,13 +25,15 @@
(let [shape (unchecked-get props "shape")
{:keys [id x y width height rotation metadata]} shape
uri (cfg/resolve-media-path (:path metadata))
data-uri (mf/use-state nil)]
embed-resources? (mf/use-ctx muc/embed-ctx)
data-uri (mf/use-state (when (not embed-resources?) uri))]
(mf/use-effect
(mf/deps shape)
(mf/deps uri)
(fn []
(-> (df/fetch-as-data-uri uri)
(p/then #(reset! data-uri (second %))))))
(if embed-resources?
(-> (df/fetch-as-data-uri uri)
(p/then #(reset! data-uri (second %)))))))
(let [transform (geom/transform-matrix shape)
props (-> (attrs/extract-style-attrs shape)
@ -49,7 +52,4 @@
:stroke "#000000"})]
[:> "image" (obj/merge!
props
#js {:xlinkHref @data-uri})]))
))
#js {:href @data-uri})]))))

View file

@ -6,16 +6,17 @@
(ns app.main.ui.shapes.text
(:require
[clojure.set :as set]
[promesa.core :as p]
[cuerdas.core :as str]
[rumext.alpha :as mf]
[app.main.data.fetch :as df]
[app.main.fonts :as fonts]
[app.main.ui.context :as muc]
[app.common.data :as d]
[app.common.geom.shapes :as geom]
[app.common.geom.matrix :as gmt]
[app.main.fonts :as fonts]
[app.util.object :as obj]
[clojure.set :as set]))
[app.util.object :as obj]))
;; --- Text Editor Rendering
@ -114,11 +115,12 @@
([node] (render-text-node 0 node))
([index {:keys [type text children] :as node}]
(mf/html
(let [embeded-fonts (mf/use-state nil)]
(let [embed-resources? (mf/use-ctx muc/embed-ctx)
embeded-fonts (mf/use-state nil)]
(mf/use-effect
(mf/deps node)
(fn []
(when (= type "root")
(when (and embed-resources? (= type "root"))
(let [font-to-embed (get-all-fonts node)
embeded (map embed-font font-to-embed)]
(-> (p/all embeded)

View file

@ -19,7 +19,6 @@
[app.common.uuid :refer [uuid]]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.colors :as dwc]
#_[app.main.ui.modal :as modal]
[app.main.ui.modal :as modal]
[okulary.core :as l]
[app.main.refs :as refs]

View file

@ -24,6 +24,7 @@
[app.main.data.workspace :as dw]
[app.main.data.workspace.drawing :as dd]
[app.main.data.colors :as dwc]
[app.main.data.fetch :as mdf]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.streams :as ms]
@ -42,10 +43,12 @@
[app.util.dom :as dom]
[app.util.dom.dnd :as dnd]
[app.util.object :as obj]
[app.main.ui.context :as muc]
[app.common.geom.shapes :as gsh]
[app.common.geom.point :as gpt]
[app.util.perf :as perf]
[app.common.uuid :as uuid])
[app.common.uuid :as uuid]
[app.util.timers :as timers])
(:import goog.events.EventType))
;; --- Coordinates Widget
@ -161,6 +164,108 @@
:selected selected
:hover hover}]]))
(defn format-viewbox [vbox]
(str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
(:y vbox 0)
(:width vbox 0)
(:height vbox 0)]))
(mf/defc pixel-picker-overlay
{::mf/wrap-props false}
[props]
(let [vport (unchecked-get props "vport")
vbox (unchecked-get props "vbox")
viewport-ref (unchecked-get props "viewport-ref")
options (unchecked-get props "options")
svg-ref (mf/use-ref nil)
canvas-ref (mf/use-ref nil)
fetch-pending (mf/deref (mdf/pending-ref))
on-mouse-move-picker
(fn [event]
(when-let [zoom-view-node (.getElementById js/document "picker-detail")]
(let [{brx :left bry :top} (dom/get-bounding-rect (mf/ref-val viewport-ref))
x (- (.-clientX event) brx)
y (- (.-clientY event) bry)
zoom-context (.getContext zoom-view-node "2d")
canvas-node (mf/ref-val canvas-ref)
canvas-context (.getContext canvas-node "2d")
pixel-data (.getImageData canvas-context x y 1 1)
rgba (.-data pixel-data)
r (obj/get rgba 0)
g (obj/get rgba 1)
b (obj/get rgba 2)
a (obj/get rgba 3)
area-data (.getImageData canvas-context (- x 25) (- y 20) 50 40)]
(-> (js/createImageBitmap area-data)
(p/then (fn [image]
;; Draw area
(obj/set! zoom-context "imageSmoothingEnabled" false)
(.drawImage zoom-context image 0 0 200 160))))
(st/emit! (dwc/pick-color [r g b a])))))
on-mouse-down-picker
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dwc/pick-color-select true (kbd/shift? event))))
on-mouse-up-picker
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dwc/stop-picker))
(modal/disallow-click-outside!))]
(mf/use-effect
;; Everytime we finish retrieving a new URL we redraw the canvas
;; so even if we're not finished the user can start to pick basic
;; shapes
(mf/deps fetch-pending)
(fn []
(try
(timers/raf
#(let [svg-node (mf/ref-val svg-ref)
canvas-node (mf/ref-val canvas-ref)
canvas-context (.getContext canvas-node "2d")
xml (.serializeToString (js/XMLSerializer.) svg-node)
content (str "data:image/svg+xml;base64," (js/btoa xml))
img (js/Image.)]
(obj/set! img "onload"
(fn []
(.drawImage canvas-context img 0 0)))
(obj/set! img "src" content)))
(catch :default e (.error js/console e)))))
[:*
[:div.overlay
{:style {:position "absolute"
:top 0
:left 0
:width "100%"
:height "100%"
:cursor cur/picker}
:on-mouse-down on-mouse-down-picker
:on-mouse-up on-mouse-up-picker
:on-mouse-move on-mouse-move-picker}]
[:canvas {:ref canvas-ref
:width (:width vport 0)
:height (:height vport 0)
:style {:display "none"}}]
[:& (mf/provider muc/embed-ctx) {:value true}
[:svg.viewport
{:ref svg-ref
:preserveAspectRatio "xMidYMid meet"
:width (:width vport 0)
:height (:height vport 0)
:view-box (format-viewbox vbox)
:style {:display "none"
:background-color (get options :background "#E8E9EA")}}
[:& frames]]]]))
(mf/defc viewport
[{:keys [page-id page local layout] :as props}]
(let [{:keys [options-mode
@ -176,7 +281,6 @@
file (mf/deref refs/workspace-file)
viewport-ref (mf/use-ref nil)
canvas-ref (mf/use-ref nil)
zoom-view-ref (mf/use-ref nil)
last-position (mf/use-var nil)
drawing (mf/deref refs/workspace-drawing)
@ -418,46 +522,7 @@
prnt (dom/get-parent node)]
(st/emit! (dw/update-viewport-size (dom/get-client-size prnt)))))
options (mf/deref refs/workspace-page-options)
on-mouse-move-picker
(fn [event]
(when-let [zoom-view-node (.getElementById js/document "picker-detail")]
(let [{brx :left bry :top} (dom/get-bounding-rect (mf/ref-val viewport-ref))
x (- (.-clientX event) brx)
y (- (.-clientY event) bry)
zoom-context (.getContext zoom-view-node "2d")
canvas-node (mf/ref-val canvas-ref)
canvas-context (.getContext canvas-node "2d")
pixel-data (.getImageData canvas-context x y 1 1)
rgba (.-data pixel-data)
r (obj/get rgba 0)
g (obj/get rgba 1)
b (obj/get rgba 2)
a (obj/get rgba 3)
area-data (.getImageData canvas-context (- x 25) (- y 20) 50 40)]
(-> (js/createImageBitmap area-data)
(p/then (fn [image]
;; Draw area
(obj/set! zoom-context "imageSmoothingEnabled" false)
(.drawImage zoom-context image 0 0 200 160))))
(st/emit! (dwc/pick-color [r g b a])))))
on-mouse-down-picker
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dwc/pick-color-select true (kbd/shift? event))))
on-mouse-up-picker
(fn [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(st/emit! (dwc/stop-picker))
(modal/disallow-click-outside!))]
options (mf/deref refs/workspace-page-options)]
(mf/use-layout-effect
(fn []
@ -481,44 +546,18 @@
(mf/use-layout-effect (mf/deps layout) on-resize)
(mf/use-effect
(mf/deps props)
(fn []
(when picking-color?
(try
(let [svg-node (mf/ref-val viewport-ref)
canvas-node (mf/ref-val canvas-ref)
canvas-context (.getContext canvas-node "2d")
xml (.serializeToString (js/XMLSerializer.) svg-node)
content (str "data:image/svg+xml;base64," (js/btoa xml))
img (js/Image.)]
(obj/set! img "onload"
(fn []
(.drawImage canvas-context img 0 0)))
(obj/set! img "src" content))
(catch :default e (.error js/console e))))))
[:*
(when picking-color?
[:canvas {:ref canvas-ref
:width (:width vport 0)
:height (:height vport 0)
:on-mouse-down on-mouse-down-picker
:on-mouse-up on-mouse-up-picker
:on-mouse-move on-mouse-move-picker
:style {:position "absolute"
:top 0
:left 0
:cursor cur/picker}}])
[:& pixel-picker-overlay {:vport vport
:vbox vbox
:viewport-ref viewport-ref
:options options}])
[:svg.viewport
{:preserveAspectRatio "xMidYMid meet"
:width (:width vport 0)
:height (:height vport 0)
:view-box (str/join " " [(+ (:x vbox 0) (:left-offset vbox 0))
(:y vbox 0)
(:width vbox 0)
(:height vbox 0)])
:view-box (format-viewbox vbox)
:ref viewport-ref
:class (when drawing-tool "drawing")
:style {:cursor (cond