mirror of
https://github.com/penpot/penpot.git
synced 2025-01-22 14:39:45 -05:00
✨ Update to React 18
This commit is contained in:
parent
5ea9a52e69
commit
4b8ee8ef84
30 changed files with 396 additions and 250 deletions
|
@ -13,8 +13,8 @@
|
|||
funcool/tubax {:mvn/version "2021.05.20-0"}
|
||||
|
||||
funcool/rumext
|
||||
{:git/tag "v2.6"
|
||||
:git/sha "97203a5"
|
||||
{:git/tag "v2.7"
|
||||
:git/sha "37fa860"
|
||||
:git/url "https://github.com/funcool/rumext.git"
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
"opentype.js": "^1.3.4",
|
||||
"postcss-modules": "^6.0.0",
|
||||
"randomcolor": "^0.6.2",
|
||||
"react": "~17.0.2",
|
||||
"react-dom": "~17.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"rxjs": "~7.8.1",
|
||||
"sax": "^1.2.4",
|
||||
|
|
|
@ -45,10 +45,18 @@
|
|||
|
||||
(declare reinit)
|
||||
|
||||
(defonce app-root
|
||||
(let [el (dom/get-element "app")]
|
||||
(mf/create-root el)))
|
||||
|
||||
(defonce modal-root
|
||||
(let [el (dom/get-element "modal")]
|
||||
(mf/create-root el)))
|
||||
|
||||
(defn init-ui
|
||||
[]
|
||||
(mf/mount (mf/element ui/app) (dom/get-element "app"))
|
||||
(mf/mount (mf/element modal) (dom/get-element "modal")))
|
||||
(mf/render! app-root (mf/element ui/app))
|
||||
(mf/render! modal-root (mf/element modal)))
|
||||
|
||||
(defn- initialize-profile
|
||||
"Event used mainly on application bootstrap; it fetches the profile
|
||||
|
@ -110,9 +118,15 @@
|
|||
|
||||
(defn ^:export reinit
|
||||
[]
|
||||
#_(mf/unmount (dom/get-element "app"))
|
||||
#_(mf/unmount (dom/get-element "modal"))
|
||||
#_(st/emit! (ev/initialize))
|
||||
;; NOTE: in cases of some strange behavior after hot-reload,
|
||||
;; uncomment this lines; they make a hard-rerender instead
|
||||
;; soft-rerender.
|
||||
;;
|
||||
;; (mf/unmount! app-root)
|
||||
;; (mf/unmount! modal-root)
|
||||
;; (set! app-root (mf/create-root (dom/get-element "app")))
|
||||
;; (set! modal-root (mf/create-root (dom/get-element "modal")))
|
||||
(st/emit! (ev/initialize))
|
||||
(init-ui))
|
||||
|
||||
(defn ^:dev/after-load after-load
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
shapes (cph/get-immediate-children objects)
|
||||
srect (gsh/shapes->rect shapes)
|
||||
local (assoc local :vport size :zoom 1 :zoom-inverse 1)]
|
||||
|
||||
(cond
|
||||
(or (not (d/num? (:width srect)))
|
||||
(not (d/num? (:height srect))))
|
||||
|
@ -52,6 +53,7 @@
|
|||
(> (:height srect) height))
|
||||
(let [srect (gal/adjust-to-viewport size srect {:padding 40})
|
||||
zoom (/ (:width size) (:width srect))]
|
||||
|
||||
(-> local
|
||||
(assoc :zoom zoom)
|
||||
(assoc :zoom-inverse (/ 1 zoom))
|
||||
|
|
|
@ -229,10 +229,16 @@
|
|||
edition? (mf/use-state false)
|
||||
|
||||
on-show-options
|
||||
(mf/use-fn #(reset! options true))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! options true)))
|
||||
|
||||
on-hide-options
|
||||
(mf/use-fn #(reset! options false))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! options false)))
|
||||
|
||||
on-edit-clicked
|
||||
(mf/use-fn
|
||||
|
|
|
@ -97,21 +97,17 @@
|
|||
(dom/focus! (dom/get-element next-id))))
|
||||
|
||||
(when (kbd/tab? event)
|
||||
(on-close))))
|
||||
(on-close))))]
|
||||
|
||||
on-mount
|
||||
(fn []
|
||||
(let [keys [(events/listen globals/document EventType.CLICK on-click)
|
||||
(events/listen globals/document EventType.CONTEXTMENU on-click)
|
||||
(events/listen globals/document EventType.KEYUP on-keyup)
|
||||
(events/listen globals/document EventType.KEYDOWN on-key-down)]]
|
||||
#(doseq [key keys]
|
||||
(events/unlistenByKey key))))]
|
||||
(mf/with-effect []
|
||||
(let [keys [(events/listen globals/document EventType.CLICK on-click)
|
||||
(events/listen globals/document EventType.CONTEXTMENU on-click)
|
||||
(events/listen globals/document EventType.KEYUP on-keyup)
|
||||
(events/listen globals/document EventType.KEYDOWN on-key-down)]]
|
||||
#(doseq [key keys]
|
||||
(events/unlistenByKey key))))
|
||||
|
||||
(mf/use-effect on-mount)
|
||||
[:ul {:class list-class
|
||||
:role "menu"}
|
||||
children]))
|
||||
[:ul {:class list-class :role "menu"} children]))
|
||||
|
||||
(mf/defc dropdown-menu
|
||||
{::mf/wrap-props false}
|
||||
|
|
|
@ -32,8 +32,14 @@
|
|||
emit-blur? (mf/use-ref nil)
|
||||
font-size-wrapper-ref (mf/use-ref)
|
||||
|
||||
open-dropdown #(swap! state assoc :is-open? true)
|
||||
close-dropdown #(swap! state assoc :is-open? false)
|
||||
open-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? true))
|
||||
close-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? false))
|
||||
select-item (fn [value]
|
||||
(fn [_]
|
||||
(swap! state assoc :current-value value)
|
||||
|
|
|
@ -39,8 +39,15 @@
|
|||
current-label (get label-index current-value)
|
||||
is-open? (:is-open? state)
|
||||
|
||||
open-dropdown (mf/use-fn #(swap! state* assoc :is-open? true))
|
||||
close-dropdown (mf/use-fn #(swap! state* assoc :is-open? false))
|
||||
open-dropdown (mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state* assoc :is-open? true)))
|
||||
|
||||
close-dropdown (mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state* assoc :is-open? false)))
|
||||
|
||||
select-item
|
||||
(mf/use-fn
|
||||
|
@ -77,8 +84,9 @@
|
|||
(mf/with-effect [default-value]
|
||||
(swap! state* assoc :current-value default-value))
|
||||
(if new-css-system
|
||||
[:div {:on-click open-dropdown :class (dom/classnames (css class) true
|
||||
(css :custom-select) true)}
|
||||
[:div {:on-click open-dropdown
|
||||
:class (dom/classnames (css class) true
|
||||
(css :custom-select) true)}
|
||||
[:span {:class (css :current-label)} current-label]
|
||||
[:span {:class (css :dropdown-button)} i/arrow-refactor]
|
||||
[:& dropdown {:show is-open? :on-close close-dropdown}
|
||||
|
@ -98,8 +106,8 @@
|
|||
:on-click select-item}
|
||||
[:span {:class (css :label)} label]
|
||||
[:span {:class (css :check-icon)} i/tick-refactor]])))]]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[:div.custom-select {:on-click open-dropdown :class class}
|
||||
[:span current-label]
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
i/search])]))
|
||||
|
||||
(mf/defc teams-selector-dropdown-items
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [team profile teams] :as props}]
|
||||
(let [on-create-clicked
|
||||
(mf/use-callback
|
||||
|
@ -257,6 +258,7 @@
|
|||
(team-selected (:id team-item) event)))
|
||||
:id (str "teams-selector-" (:id team-item))
|
||||
:klass "team-name"
|
||||
:key (str "teams-selector-" (:id team-item))
|
||||
:unique-key (dm/str (:id team-item))}
|
||||
[:span.team-icon
|
||||
[:img {:src (cf/resolve-team-photo-url team-item)
|
||||
|
@ -472,7 +474,9 @@
|
|||
[:div.sidebar-team-switch
|
||||
[:div.switch-content
|
||||
[:button.current-team {:tab-index "0"
|
||||
:on-click #(reset! show-teams-ddwn? true)
|
||||
:on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-teams-ddwn? true))
|
||||
:on-key-down (fn [event]
|
||||
(when (or (kbd/space? event) (kbd/enter? event))
|
||||
(dom/prevent-default event)
|
||||
|
@ -496,7 +500,9 @@
|
|||
i/arrow-down]]
|
||||
|
||||
(when-not (:is-default team)
|
||||
[:button.switch-options {:on-click #(reset! show-team-opts-ddwn? true)
|
||||
[:button.switch-options {:on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-team-opts-ddwn? true))
|
||||
:tab-index "0"
|
||||
:on-key-down (fn [event]
|
||||
(when (or (kbd/space? event) (kbd/enter? event))
|
||||
|
@ -674,6 +680,7 @@
|
|||
(mf/use-callback
|
||||
(fn [section event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show false)
|
||||
(if (keyword? section)
|
||||
(st/emit! (rt/nav section))
|
||||
(st/emit! section))))
|
||||
|
@ -689,7 +696,9 @@
|
|||
|
||||
[:div.profile-section
|
||||
[:div.profile {:tab-index "0"
|
||||
:on-click #(reset! show true)
|
||||
:on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show true))
|
||||
:on-key-down (fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(reset! show true)))
|
||||
|
@ -698,7 +707,9 @@
|
|||
:alt (:fullname profile)}]
|
||||
[:span (:fullname profile)]]
|
||||
|
||||
[:& dropdown-menu {:on-close #(reset! show false)
|
||||
[:& dropdown-menu {:on-close (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show false))
|
||||
:show @show}
|
||||
[:ul.dropdown
|
||||
[:li {:tab-index (if show
|
||||
|
|
|
@ -226,6 +226,13 @@
|
|||
(reset! ptr value))
|
||||
ptr))
|
||||
|
||||
(defn use-update-ref
|
||||
[value]
|
||||
(let [ref (mf/use-ref value)]
|
||||
(mf/with-effect [value]
|
||||
(mf/set-ref-val! ref value))
|
||||
ref))
|
||||
|
||||
(defn use-ref-callback
|
||||
"Returns a stable callback pointer what calls the interned
|
||||
callback. The interned callback will be automatically updated on
|
||||
|
|
|
@ -82,11 +82,11 @@
|
|||
:modal-wrapper (not new-css-system))}
|
||||
(mf/element component (:props data))])))
|
||||
|
||||
|
||||
(def modal-ref
|
||||
(l/derived ::dm/modal st/state))
|
||||
|
||||
(mf/defc modal
|
||||
{::mf/wrap-props false}
|
||||
[]
|
||||
(let [modal (mf/deref modal-ref)
|
||||
new-css-system (features/use-feature :new-css-system)]
|
||||
|
|
|
@ -115,4 +115,5 @@
|
|||
[:& filters/filters {:shape shape-without-shadows :filter-id (dm/fmt "filter_blur_%" render-id)}]
|
||||
[:& fills/fills {:shape shape :render-id render-id}]
|
||||
[:& frame/frame-clip-def {:shape shape :render-id render-id}]]
|
||||
|
||||
children]]))
|
||||
|
|
|
@ -42,7 +42,10 @@
|
|||
on-zoom-fill]
|
||||
:as props}]
|
||||
(let [show-dropdown? (mf/use-state false)]
|
||||
[:div.zoom-widget {:on-click #(reset! show-dropdown? true)}
|
||||
[:div.zoom-widget {:on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-dropdown? true))}
|
||||
[:span.label (fmt/format-percent zoom)]
|
||||
[:span.icon i/arrow-down]
|
||||
[:& dropdown {:show @show-dropdown?
|
||||
|
|
|
@ -272,7 +272,6 @@
|
|||
:transform (gsh/transform-str shape)}])))
|
||||
|
||||
|
||||
|
||||
;; TODO: use-memo use-fn
|
||||
|
||||
(defn generic-wrapper-factory
|
||||
|
|
|
@ -154,7 +154,10 @@
|
|||
:color color}])]]]]
|
||||
|
||||
[:div.color-palette-actions
|
||||
{:on-click #(swap! state assoc :show-menu true)}
|
||||
{:on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :show-menu true))}
|
||||
[:div.color-palette-actions-button i/actions]]
|
||||
|
||||
[:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide]
|
||||
|
@ -163,7 +166,7 @@
|
|||
[:div.color-palette-empty {:style {:position "absolute"
|
||||
:left "50%"
|
||||
:top "50%"
|
||||
:transform "translate(-50%, -50%)"}}
|
||||
:transform "translate(-50%, -50%)"}}
|
||||
(tr "workspace.libraries.colors.empty-palette")]
|
||||
[:div.color-palette-inside {:style {:position "relative"
|
||||
:right (str (* 66 offset) "px")}}
|
||||
|
|
|
@ -92,7 +92,10 @@
|
|||
[:div.comments-section.comment-threads-section
|
||||
[:div.workspace-comment-threads-sidebar-header
|
||||
[:div.label (tr "labels.comments")]
|
||||
[:div.options {:on-click #(reset! options? true)}
|
||||
[:div.options {:on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! options? true))}
|
||||
[:div.label (case (:mode local)
|
||||
(nil :all) (tr "labels.all")
|
||||
:yours (tr "labels.only-yours"))]
|
||||
|
|
|
@ -79,10 +79,16 @@
|
|||
open? (deref open*)
|
||||
|
||||
open-dropdown
|
||||
(mf/use-fn #(reset! open* true))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! open* true)))
|
||||
|
||||
close-dropdown
|
||||
(mf/use-fn #(reset! open* false))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! open* false)))
|
||||
|
||||
on-increase
|
||||
(mf/use-fn
|
||||
|
@ -449,9 +455,23 @@
|
|||
sub-menu* (mf/use-state false)
|
||||
sub-menu (deref sub-menu*)
|
||||
|
||||
open-menu (mf/use-fn #(reset! show-menu* true))
|
||||
close-menu (mf/use-fn #(reset! show-menu* false))
|
||||
close-sub-menu (mf/use-fn #(reset! sub-menu* nil))
|
||||
open-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-menu* true)))
|
||||
|
||||
close-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-menu* false)))
|
||||
|
||||
close-sub-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! sub-menu* nil)))
|
||||
|
||||
on-menu-click
|
||||
(mf/use-fn
|
||||
|
@ -465,6 +485,7 @@
|
|||
toggle-flag
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [flag (-> (dom/get-current-target event)
|
||||
(dom/get-data "flag")
|
||||
(keyword))]
|
||||
|
|
|
@ -613,9 +613,23 @@
|
|||
sub-menu* (mf/use-state false)
|
||||
sub-menu (deref sub-menu*)
|
||||
|
||||
open-menu (mf/use-fn #(reset! show-menu* true))
|
||||
close-menu (mf/use-fn #(reset! show-menu* false))
|
||||
close-sub-menu (mf/use-fn #(reset! sub-menu* nil))
|
||||
open-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-menu* true)))
|
||||
|
||||
close-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! show-menu* false)))
|
||||
|
||||
close-sub-menu
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! sub-menu* nil)))
|
||||
|
||||
on-menu-click
|
||||
(mf/use-fn
|
||||
|
@ -629,6 +643,7 @@
|
|||
toggle-flag
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [flag (-> (dom/get-current-target event)
|
||||
(dom/get-data "test")
|
||||
(keyword))]
|
||||
|
|
|
@ -72,10 +72,16 @@
|
|||
open? (deref open*)
|
||||
|
||||
open-dropdown
|
||||
(mf/use-fn #(reset! open* true))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! open* true)))
|
||||
|
||||
close-dropdown
|
||||
(mf/use-fn #(reset! open* false))
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(reset! open* false)))
|
||||
|
||||
on-increase
|
||||
(mf/use-fn
|
||||
|
|
|
@ -57,15 +57,14 @@
|
|||
{::mf/wrap [#(mf/memo' % check-props)]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
frame-id (:id shape)
|
||||
objects (wsh/lookup-page-objects @st/state)
|
||||
node-ref (mf/use-var nil)
|
||||
node-ref (mf/use-ref nil)
|
||||
modifiers-ref (mf/use-memo (mf/deps frame-id) #(refs/workspace-modifiers-by-frame-id frame-id))
|
||||
modifiers (mf/deref modifiers-ref)]
|
||||
|
||||
(fdm/use-dynamic-modifiers objects @node-ref modifiers)
|
||||
(fdm/use-dynamic-modifiers objects (mf/ref-val node-ref) modifiers)
|
||||
(let [shape (unchecked-get props "shape")]
|
||||
[:& frame-shape {:shape shape :ref node-ref}])))))
|
||||
|
||||
|
@ -86,62 +85,71 @@
|
|||
|
||||
objects (wsh/lookup-page-objects @st/state)
|
||||
|
||||
node* (mf/use-var nil)
|
||||
node-ref (mf/use-ref nil)
|
||||
root-ref (mf/use-ref nil)
|
||||
|
||||
force-render* (mf/use-state false)
|
||||
force-render? (deref force-render*)
|
||||
|
||||
;; when `true` we've called the mount for the frame
|
||||
rendered* (mf/use-var false)
|
||||
rendered-ref (mf/use-ref false)
|
||||
|
||||
modifiers-ref (mf/with-memo [frame-id]
|
||||
(refs/workspace-modifiers-by-frame-id frame-id))
|
||||
modifiers (mf/deref modifiers-ref)
|
||||
|
||||
|
||||
fonts (mf/with-memo [shape objects]
|
||||
(ff/shape->fonts shape objects))
|
||||
fonts (hooks/use-equal-memo fonts)
|
||||
|
||||
disable-thumbnail? (d/not-empty? (dm/get-in modifiers [frame-id :modifiers]))
|
||||
|
||||
[on-load-frame-dom render-frame? thumbnail-renderer]
|
||||
(ftr/use-render-thumbnail page-id shape node* rendered* disable-thumbnail? force-render?)
|
||||
[on-load-frame-dom render-frame? children]
|
||||
(ftr/use-render-thumbnail page-id shape root-ref node-ref rendered-ref disable-thumbnail? force-render?)
|
||||
|
||||
on-frame-load
|
||||
(fns/use-node-store thumbnail? node* rendered* render-frame?)]
|
||||
(fns/use-node-store node-ref rendered-ref thumbnail? render-frame?)
|
||||
]
|
||||
|
||||
(fdm/use-dynamic-modifiers objects @node* modifiers)
|
||||
(fdm/use-dynamic-modifiers objects (mf/ref-val node-ref) modifiers)
|
||||
|
||||
(mf/with-effect []
|
||||
;; When a change in the data is received a "force-render" event is emitted
|
||||
;; that will force the component to be mounted in memory
|
||||
(let [sub (->> (dwt/force-render-stream frame-id)
|
||||
(rx/take-while #(not @rendered*))
|
||||
(rx/take-while #(not (mf/ref-val rendered-ref)))
|
||||
(rx/subs #(reset! force-render* true)))]
|
||||
#(some-> sub rx/dispose!)))
|
||||
|
||||
(mf/with-effect [shape fonts thumbnail? on-load-frame-dom force-render? render-frame?]
|
||||
(when (and (some? @node*)
|
||||
(or @rendered*
|
||||
(not thumbnail?)
|
||||
force-render?
|
||||
render-frame?))
|
||||
(let [elem (mf/element frame-shape #js {:ref on-load-frame-dom :shape shape :fonts fonts})]
|
||||
(mf/mount elem @node*)
|
||||
(when (not @rendered*)
|
||||
(reset! rendered* true)))))
|
||||
(when (and (some? (mf/ref-val node-ref))
|
||||
(or (mf/ref-val rendered-ref)
|
||||
(false? thumbnail?)
|
||||
(true? force-render?)
|
||||
(true? render-frame?)))
|
||||
|
||||
(when (false? (mf/ref-val rendered-ref))
|
||||
(when-let [node (mf/ref-val node-ref)]
|
||||
(mf/set-ref-val! root-ref (mf/create-root node))
|
||||
(mf/set-ref-val! rendered-ref true)))
|
||||
|
||||
(when-let [root (mf/ref-val root-ref)]
|
||||
(mf/render! root (mf/element frame-shape #js {:ref on-load-frame-dom :shape shape :fonts fonts})))
|
||||
|
||||
(constantly nil)))
|
||||
|
||||
[:& shape-container {:shape shape}
|
||||
[:g.frame-container {:id (dm/str "frame-container-" frame-id)
|
||||
:key "frame-container"
|
||||
:ref on-frame-load
|
||||
:opacity (when (:hidden shape) 0)}
|
||||
[:g.frame-container
|
||||
{:id (dm/str "frame-container-" frame-id)
|
||||
:key "frame-container"
|
||||
:ref on-frame-load
|
||||
:opacity (when (:hidden shape) 0)}
|
||||
[:& ff/fontfaces-style {:fonts fonts}]
|
||||
[:g.frame-thumbnail-wrapper
|
||||
{:id (dm/str "thumbnail-container-" frame-id)
|
||||
;; Hide the thumbnail when not displaying
|
||||
:opacity (when-not thumbnail? 0)}
|
||||
thumbnail-renderer]]
|
||||
children]]
|
||||
|
||||
]))))
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.viewport.utils :as vwu]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
[app.util.timers :as ts]
|
||||
[debug :refer [debug?]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -230,85 +230,87 @@
|
|||
|
||||
(defn use-dynamic-modifiers
|
||||
[objects node modifiers]
|
||||
|
||||
(let [transforms
|
||||
(mf/use-memo
|
||||
(mf/deps modifiers)
|
||||
(fn []
|
||||
(when (some? modifiers)
|
||||
(d/mapm (fn [id {current-modifiers :modifiers}]
|
||||
(let [shape (get objects id)
|
||||
adapt-text? (and (= :text (:type shape)) (not (ctm/only-move? current-modifiers)))
|
||||
(mf/with-memo [modifiers]
|
||||
(when (some? modifiers)
|
||||
(d/mapm (fn [id {current-modifiers :modifiers}]
|
||||
(let [shape (get objects id)
|
||||
adapt-text? (and (= :text (:type shape)) (not (ctm/only-move? current-modifiers)))
|
||||
|
||||
current-modifiers
|
||||
(cond-> current-modifiers
|
||||
adapt-text?
|
||||
(adapt-text-modifiers shape))]
|
||||
(ctm/modifiers->transform current-modifiers)))
|
||||
modifiers))))
|
||||
current-modifiers
|
||||
(cond-> current-modifiers
|
||||
adapt-text?
|
||||
(adapt-text-modifiers shape))]
|
||||
(ctm/modifiers->transform current-modifiers)))
|
||||
modifiers)))
|
||||
|
||||
add-children (mf/use-memo (mf/deps modifiers) #(ctm/added-children-frames modifiers))
|
||||
add-children (hooks/use-equal-memo add-children)
|
||||
add-children-prev (hooks/use-previous add-children)
|
||||
add-children
|
||||
(mf/with-memo [modifiers]
|
||||
(ctm/added-children-frames modifiers))
|
||||
|
||||
shapes
|
||||
(mf/use-memo
|
||||
(mf/deps transforms)
|
||||
(fn []
|
||||
(->> (keys transforms)
|
||||
(filter #(some? (get transforms %)))
|
||||
(mapv (comp (add-masking-child? objects) (d/getf objects))))))
|
||||
(mf/with-memo [transforms]
|
||||
(->> (keys transforms)
|
||||
(filter #(some? (get transforms %)))
|
||||
(mapv (comp (add-masking-child? objects) (d/getf objects)))))
|
||||
|
||||
prev-shapes (mf/use-var nil)
|
||||
prev-modifiers (mf/use-var nil)
|
||||
prev-transforms (mf/use-var nil)]
|
||||
add-children (hooks/use-equal-memo add-children)
|
||||
add-children-prev (hooks/use-previous add-children)
|
||||
prev-shapes (mf/use-var nil)
|
||||
prev-modifiers (mf/use-var nil)
|
||||
prev-transforms (mf/use-var nil)]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps add-children)
|
||||
(fn []
|
||||
(doseq [{:keys [shape]} add-children-prev]
|
||||
(let [shape-node (get-shape-node shape)
|
||||
mirror-node (dom/query (dm/fmt ".mirror-shape[href='#shape-%'" shape))]
|
||||
(when mirror-node (.remove mirror-node))
|
||||
(dom/remove-attribute! (dom/get-parent shape-node) "display")))
|
||||
(mf/with-effect [add-children]
|
||||
(ts/raf
|
||||
#(doseq [{:keys [shape]} add-children-prev]
|
||||
(let [shape-node (get-shape-node shape)
|
||||
mirror-node (dom/query (dm/fmt ".mirror-shape[href='#shape-%'" shape))]
|
||||
(when mirror-node (.remove mirror-node))
|
||||
(dom/remove-attribute! (dom/get-parent shape-node) "display"))))
|
||||
|
||||
(doseq [{:keys [frame shape]} add-children]
|
||||
(let [frame-node (get-shape-node frame)
|
||||
shape-node (get-shape-node shape)
|
||||
(ts/raf
|
||||
#(doseq [{:keys [frame shape]} add-children]
|
||||
(let [frame-node (get-shape-node frame)
|
||||
shape-node (get-shape-node shape)
|
||||
|
||||
clip-id
|
||||
(dom/get-attribute (dom/query frame-node ":scope > defs > .frame-clip-def") "id")
|
||||
clip-id
|
||||
(-> (dom/query frame-node ":scope > defs > .frame-clip-def")
|
||||
(dom/get-attribute "id"))
|
||||
|
||||
use-node
|
||||
(.createElementNS globals/document "http://www.w3.org/2000/svg" "use")
|
||||
use-node
|
||||
(dom/create-element "http://www.w3.org/2000/svg" "use")
|
||||
|
||||
contents-node
|
||||
(or (dom/query frame-node ".frame-children") frame-node)]
|
||||
contents-node
|
||||
(or (dom/query frame-node ".frame-children") frame-node)]
|
||||
|
||||
(dom/set-attribute! use-node "href" (dm/fmt "#shape-%" shape))
|
||||
(dom/set-attribute! use-node "clip-path" (dm/fmt "url(#%)" clip-id))
|
||||
(dom/add-class! use-node "mirror-shape")
|
||||
(dom/append-child! contents-node use-node)
|
||||
(dom/set-attribute! (dom/get-parent shape-node) "display" "none")))))
|
||||
(dom/set-attribute! use-node "href" (dm/fmt "#shape-%" shape))
|
||||
(dom/set-attribute! use-node "clip-path" (dm/fmt "url(#%)" clip-id))
|
||||
(dom/add-class! use-node "mirror-shape")
|
||||
(dom/append-child! contents-node use-node)
|
||||
(dom/set-attribute! (dom/get-parent shape-node) "display" "none")))))
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps transforms)
|
||||
(fn []
|
||||
(let [curr-shapes-set (into #{} (map :id) shapes)
|
||||
prev-shapes-set (into #{} (map :id) @prev-shapes)
|
||||
(mf/with-effect [transforms]
|
||||
(let [curr-shapes-set (into #{} (map :id) shapes)
|
||||
prev-shapes-set (into #{} (map :id) @prev-shapes)
|
||||
|
||||
new-shapes (->> shapes (remove #(contains? prev-shapes-set (:id %))))
|
||||
removed-shapes (->> @prev-shapes (remove #(contains? curr-shapes-set (:id %))))]
|
||||
new-shapes (->> shapes (remove #(contains? prev-shapes-set (:id %))))
|
||||
removed-shapes (->> @prev-shapes (remove #(contains? curr-shapes-set (:id %))))]
|
||||
|
||||
(when (d/not-empty? new-shapes)
|
||||
(start-transform! node new-shapes))
|
||||
;; NOTE: we schedule the dom modifications to be executed
|
||||
;; asynchronously for avoid component flickering when react18
|
||||
;; is used.
|
||||
|
||||
(when (d/not-empty? shapes)
|
||||
(update-transform! node shapes transforms modifiers))
|
||||
(when (d/not-empty? new-shapes)
|
||||
(ts/raf #(start-transform! node new-shapes)))
|
||||
|
||||
(when (d/not-empty? removed-shapes)
|
||||
(remove-transform! node removed-shapes)))
|
||||
(when (d/not-empty? shapes)
|
||||
(ts/raf #(update-transform! node shapes transforms modifiers)))
|
||||
|
||||
(reset! prev-modifiers modifiers)
|
||||
(reset! prev-transforms transforms)
|
||||
(reset! prev-shapes shapes)))))
|
||||
(when (d/not-empty? removed-shapes)
|
||||
(ts/raf #(remove-transform! node removed-shapes))))
|
||||
|
||||
(reset! prev-modifiers modifiers)
|
||||
(reset! prev-transforms transforms)
|
||||
(reset! prev-shapes shapes))
|
||||
|
||||
))
|
||||
|
|
|
@ -7,40 +7,49 @@
|
|||
(ns app.main.ui.workspace.shapes.frame.node-store
|
||||
(:require
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn use-node-store
|
||||
"Hook responsible of storing the rendered DOM node in memory while not being used"
|
||||
[thumbnail? node-ref rendered? render-frame?]
|
||||
[node-ref rendered-ref thumbnail? render-frame?]
|
||||
|
||||
(let [;; when `true` the node is in memory
|
||||
in-memory? (mf/use-state true)
|
||||
|
||||
;; State just for re-rendering
|
||||
re-render (mf/use-state 0)
|
||||
|
||||
parent-ref (mf/use-var nil)
|
||||
(let [re-render* (mf/use-state 0)
|
||||
parent-ref (mf/use-ref nil)
|
||||
present-ref (mf/use-ref false)
|
||||
|
||||
on-frame-load
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [node]
|
||||
(when (and (some? node) (nil? @node-ref))
|
||||
(let [content (-> (.createElementNS globals/document "http://www.w3.org/2000/svg" "g")
|
||||
(when (and (some? node)
|
||||
(nil? (mf/ref-val node-ref)))
|
||||
(let [content (-> (dom/create-element "http://www.w3.org/2000/svg" "g")
|
||||
(dom/add-class! "frame-content"))]
|
||||
(reset! node-ref content)
|
||||
(reset! parent-ref node)
|
||||
(swap! re-render inc)))))]
|
||||
(mf/set-ref-val! node-ref content)
|
||||
(mf/set-ref-val! parent-ref node)
|
||||
(swap! re-render* inc)))))]
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps thumbnail? render-frame?)
|
||||
(fn []
|
||||
(when (and (some? @parent-ref) (some? @node-ref) @rendered? (and thumbnail? (not render-frame?)))
|
||||
(.removeChild @parent-ref @node-ref)
|
||||
(reset! in-memory? true))
|
||||
(mf/with-effect [thumbnail? render-frame?]
|
||||
(let [rendered? (mf/ref-val rendered-ref)
|
||||
present? (mf/ref-val present-ref)]
|
||||
|
||||
(when (and (some? @node-ref) @in-memory? (or (not thumbnail?) render-frame?))
|
||||
(.appendChild @parent-ref @node-ref)
|
||||
(reset! in-memory? false))))
|
||||
(when (and (true? rendered?)
|
||||
(true? thumbnail?)
|
||||
(false? render-frame?)
|
||||
(true? present?))
|
||||
(when-let [parent (mf/ref-val parent-ref)]
|
||||
(when-let [node (mf/ref-val node-ref)]
|
||||
(dom/remove-child! parent node)
|
||||
(mf/set-ref-val! present-ref false)
|
||||
(swap! re-render* inc))))
|
||||
|
||||
(when (and (false? present?)
|
||||
(or (false? thumbnail?)
|
||||
(true? render-frame?)))
|
||||
(when-let [parent (mf/ref-val parent-ref)]
|
||||
(when-let [node (mf/ref-val node-ref)]
|
||||
(when-not (dom/child? parent node)
|
||||
(dom/append-child! parent node)
|
||||
(mf/set-ref-val! present-ref true)
|
||||
(swap! re-render* inc)))))))
|
||||
|
||||
on-frame-load))
|
||||
|
|
|
@ -66,18 +66,17 @@
|
|||
|
||||
(defn use-render-thumbnail
|
||||
"Hook that will create the thumbnail data"
|
||||
[page-id {:keys [id] :as shape} node-ref rendered? disable? force-render]
|
||||
[page-id {:keys [id] :as shape} root-ref node-ref rendered-ref disable? force-render]
|
||||
|
||||
(let [frame-image-ref (mf/use-ref nil)
|
||||
|
||||
disable* (mf/use-var disable?)
|
||||
regenerate* (mf/use-var false)
|
||||
disable-ref (mf/use-ref disable?)
|
||||
regenerate-ref (mf/use-ref false)
|
||||
|
||||
all-children-ref (mf/with-memo [id]
|
||||
(refs/all-children-objects id))
|
||||
all-children (mf/deref all-children-ref)
|
||||
|
||||
;; FIXME: performance rect
|
||||
bounds
|
||||
(if (:show-content shape)
|
||||
(gsh/shapes->rect (cons shape all-children))
|
||||
|
@ -89,37 +88,44 @@
|
|||
height (dm/get-prop bounds :height)
|
||||
|
||||
svg-uri* (mf/use-state nil)
|
||||
bitmap-uri* (mf/use-state nil)
|
||||
observer* (mf/use-var nil)
|
||||
svg-uri (deref svg-uri*)
|
||||
|
||||
bounds* (hooks/use-update-var bounds)
|
||||
bitmap-uri* (mf/use-state nil)
|
||||
bitmap-uri (deref bitmap-uri*)
|
||||
|
||||
observer-ref (mf/use-ref nil)
|
||||
|
||||
bounds-ref (hooks/use-update-ref bounds)
|
||||
updates-s (mf/use-memo rx/subject)
|
||||
|
||||
thumbnail-uri-ref (mf/with-memo [page-id id]
|
||||
(refs/thumbnail-frame-data page-id id))
|
||||
thumbnail-uri (mf/deref thumbnail-uri-ref)
|
||||
thumbnail-uri* (mf/with-memo [page-id id]
|
||||
(refs/thumbnail-frame-data page-id id))
|
||||
thumbnail-uri (mf/deref thumbnail-uri*)
|
||||
|
||||
;; State to indicate to the parent that should render the frame
|
||||
render-frame* (mf/use-state (not thumbnail-uri))
|
||||
render-frame? (deref render-frame*)
|
||||
|
||||
debug? (debug? :thumbnails)
|
||||
|
||||
on-bitmap-load
|
||||
(mf/use-fn
|
||||
(mf/deps svg-uri)
|
||||
(fn []
|
||||
;; We revoke the SVG Blob URI to free memory only when we
|
||||
;; are sure that it is not used anymore.
|
||||
(wapi/revoke-uri @svg-uri*)
|
||||
(some-> svg-uri wapi/revoke-uri)
|
||||
(reset! svg-uri* nil)))
|
||||
|
||||
on-svg-load
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps thumbnail-uri)
|
||||
(fn []
|
||||
(let [image-node (mf/ref-val frame-image-ref)]
|
||||
(dom/set-data! image-node "ready" "true")
|
||||
|
||||
;; If we don't have the thumbnail data saved (normally the first load) we update the data
|
||||
;; when available
|
||||
(when (not ^boolean @thumbnail-uri-ref)
|
||||
(when-not (some? thumbnail-uri)
|
||||
(st/emit! (dwt/update-thumbnail page-id id)))
|
||||
|
||||
(reset! render-frame* false))))
|
||||
|
@ -131,34 +137,37 @@
|
|||
(try
|
||||
;; When starting generating the canvas we mark it as not ready so its not send to back until
|
||||
;; we have time to update it
|
||||
(let [node @node-ref]
|
||||
|
||||
(when-let [node (mf/ref-val node-ref)]
|
||||
(if (dom/has-children? node)
|
||||
;; The frame-content need to have children in order to generate the thumbnail
|
||||
(let [style-node (dom/query (dm/str "#frame-container-" id " style"))
|
||||
url (create-svg-blob-uri-from @bounds* node style-node)]
|
||||
bounds (mf/ref-val bounds-ref)
|
||||
url (create-svg-blob-uri-from bounds node style-node)]
|
||||
|
||||
(reset! svg-uri* url))
|
||||
|
||||
;; Node not yet ready, we schedule a new generation
|
||||
(ts/raf generate-thumbnail)))
|
||||
|
||||
(catch :default e
|
||||
(.error js/console e)))))
|
||||
|
||||
on-change-frame
|
||||
(mf/use-fn
|
||||
(mf/deps id)
|
||||
(mf/deps id generate-thumbnail)
|
||||
(fn []
|
||||
(when (and ^boolean @node-ref
|
||||
^boolean @rendered?
|
||||
^boolean @regenerate*)
|
||||
(let [loading-images? (some? (dom/query @node-ref "[data-loading='true']"))
|
||||
(when (and (some? (mf/ref-val node-ref))
|
||||
(some? (mf/ref-val rendered-ref))
|
||||
(some? (mf/ref-val regenerate-ref)))
|
||||
(let [node (mf/ref-val node-ref)
|
||||
loading-images? (some? (dom/query node "[data-loading='true']"))
|
||||
loading-fonts? (some? (dom/query (dm/str "#frame-container-" id " > style[data-loading='true']")))]
|
||||
(when (and (not loading-images?)
|
||||
(not loading-fonts?))
|
||||
(reset! svg-uri* nil)
|
||||
(reset! bitmap-uri* nil)
|
||||
(generate-thumbnail)
|
||||
(reset! regenerate* false))))))
|
||||
(mf/set-ref-val! regenerate-ref false))))))
|
||||
|
||||
;; When the frame is updated, it is marked as not ready
|
||||
;; so that it is not sent to the background until
|
||||
|
@ -169,23 +178,27 @@
|
|||
(let [image-node (mf/ref-val frame-image-ref)]
|
||||
(when (not= "false" (dom/get-data image-node "ready"))
|
||||
(dom/set-data! image-node "ready" "false")))
|
||||
(when-not ^boolean @disable*
|
||||
|
||||
(when-not ^boolean (mf/ref-val disable-ref)
|
||||
(reset! svg-uri* nil)
|
||||
(reset! bitmap-uri* nil)
|
||||
(reset! render-frame* true)
|
||||
(reset! regenerate* true))))
|
||||
(mf/set-ref-val! regenerate-ref true))))
|
||||
|
||||
on-load-frame-dom
|
||||
(mf/use-fn
|
||||
(fn [node]
|
||||
(when (and (some? node)
|
||||
(nil? @observer*))
|
||||
(when-not (some? @thumbnail-uri-ref)
|
||||
(when (and (nil? (mf/ref-val observer-ref)) (some? node))
|
||||
(when-not (some? @thumbnail-uri*)
|
||||
(rx/push! updates-s :update))
|
||||
|
||||
(let [observer (js/MutationObserver. (partial rx/push! updates-s))]
|
||||
(.observe observer node #js {:childList true :attributes true :attributeOldValue true :characterData true :subtree true})
|
||||
(reset! observer* observer)))))]
|
||||
(.observe observer node #js {:childList true
|
||||
:attributes true
|
||||
:attributeOldValue true
|
||||
:characterData true
|
||||
:subtree true})
|
||||
(mf/set-ref-val! observer-ref observer)))))]
|
||||
|
||||
(mf/with-effect [thumbnail-uri]
|
||||
(when (some? thumbnail-uri)
|
||||
|
@ -213,25 +226,30 @@
|
|||
(partial rx/dispose! subid)))
|
||||
|
||||
(mf/with-effect [disable?]
|
||||
(when (and ^boolean disable?
|
||||
(not @disable*))
|
||||
(when (and ^boolean disable? (not (mf/ref-val disable-ref)))
|
||||
(rx/push! updates-s :update))
|
||||
(reset! disable* disable?)
|
||||
|
||||
(mf/set-ref-val! disable-ref disable?)
|
||||
nil)
|
||||
|
||||
(mf/with-effect []
|
||||
(fn []
|
||||
(when (and (some? @node-ref)
|
||||
^boolean @rendered?)
|
||||
(mf/unmount @node-ref)
|
||||
(reset! node-ref nil)
|
||||
(reset! rendered? false)
|
||||
(when (some? @observer*)
|
||||
(.disconnect @observer*)
|
||||
(reset! observer* nil)))))
|
||||
(when (and (some? (mf/ref-val node-ref))
|
||||
(true? (mf/ref-val rendered-ref)))
|
||||
(when-let [root (mf/ref-val root-ref)]
|
||||
;; NOTE: the unmount should be always scheduled to be
|
||||
;; executed asynchronously of the current flow (react
|
||||
;; rules).
|
||||
(ts/schedule #(mf/unmount! ^js root)))
|
||||
|
||||
[on-load-frame-dom
|
||||
@render-frame*
|
||||
(mf/set-ref-val! node-ref nil)
|
||||
(mf/set-ref-val! rendered-ref false)
|
||||
|
||||
(when-let [observer (mf/ref-val observer-ref)]
|
||||
(.disconnect ^js observer)
|
||||
(mf/set-ref-val! observer-ref nil)))))
|
||||
|
||||
[on-load-frame-dom render-frame?
|
||||
(mf/html
|
||||
[:& frame/frame-container {:bounds bounds :shape shape}
|
||||
|
||||
|
@ -251,18 +269,18 @@
|
|||
;; to be rendered on screen. Then we remove the
|
||||
;; svg and keep the bitmap one.
|
||||
;; This is the "buffer" that keeps the bitmap image.
|
||||
(when ^boolean @bitmap-uri*
|
||||
(when (some? bitmap-uri)
|
||||
[:image.thumbnail-bitmap
|
||||
{:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:href @bitmap-uri*
|
||||
:href bitmap-uri
|
||||
:style {:filter (when ^boolean debug? "sepia(1)")}
|
||||
:on-load on-bitmap-load}])
|
||||
|
||||
;; This is the "buffer" that keeps the SVG image.
|
||||
(when ^boolean @svg-uri*
|
||||
(when (some? svg-uri)
|
||||
[:image.thumbnail-canvas
|
||||
{:x x
|
||||
:y y
|
||||
|
@ -271,6 +289,6 @@
|
|||
:width width
|
||||
:height height
|
||||
:ref frame-image-ref
|
||||
:href @svg-uri*
|
||||
:href svg-uri
|
||||
:style {:filter (when ^boolean debug? "sepia(0.5)")}
|
||||
:on-load on-svg-load}])])]))
|
||||
|
|
|
@ -124,7 +124,10 @@
|
|||
(str/format " (%s)" (count file-typographies)))]]]]
|
||||
|
||||
[:div.color-palette-actions
|
||||
{:on-click #(swap! state assoc :show-menu true)}
|
||||
{:on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :show-menu true))}
|
||||
[:div.color-palette-actions-button i/actions]]
|
||||
|
||||
[:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide]
|
||||
|
@ -134,7 +137,7 @@
|
|||
[:div.color-palette-empty {:style {:position "absolute"
|
||||
:left "50%"
|
||||
:top "50%"
|
||||
:transform "translate(-50%, -50%)"}}
|
||||
:transform "translate(-50%, -50%)"}}
|
||||
(tr "workspace.libraries.colors.empty-typography-palette")]
|
||||
[:div.color-palette-inside
|
||||
(for [[idx item] (map-indexed vector current-typographies)]
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
selected))
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [wlocal wglobal selected layout file] :as props}]
|
||||
[{:keys [selected wglobal wlocal layout file] :as props}]
|
||||
(let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check
|
||||
;; that the new parameter is sent
|
||||
{:keys [edit-path
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
[app.main.ui.css-cursors :as cur]
|
||||
[app.main.ui.formats :refer [format-number]]))
|
||||
|
||||
(defn format-viewbox [vbox]
|
||||
(defn format-viewbox
|
||||
"Format a viewbox to a string"
|
||||
[vbox]
|
||||
(dm/str (format-number(:x vbox 0)) " "
|
||||
(format-number (:y vbox 0)) " "
|
||||
(format-number (:width vbox 0)) " "
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
|
||||
(l/setup! {:app :info})
|
||||
|
||||
(defonce app-root
|
||||
(let [el (dom/get-element "app")]
|
||||
(mf/create-root el)))
|
||||
|
||||
(declare ^:private render-single-object)
|
||||
(declare ^:private render-components)
|
||||
(declare ^:private render-objects)
|
||||
|
@ -48,7 +52,7 @@
|
|||
"objects" (render-objects params)
|
||||
"components" (render-components params)
|
||||
nil)]
|
||||
(mf/mount component (dom/get-element "app")))))
|
||||
(mf/render! app-root component))))
|
||||
|
||||
(defn ^:export init
|
||||
[]
|
||||
|
@ -57,7 +61,7 @@
|
|||
|
||||
(defn reinit
|
||||
[]
|
||||
(mf/unmount (dom/get-element "app"))
|
||||
(mf/unmount! app-root)
|
||||
(init-ui))
|
||||
|
||||
(defn ^:dev/after-load after-load
|
||||
|
@ -201,7 +205,7 @@
|
|||
[:& objects-svg
|
||||
{:file-id file-id
|
||||
:page-id page-id
|
||||
:share-id share-id
|
||||
:share-id share-id
|
||||
:object-ids (into #{} object-id)
|
||||
:render-embed? render-embed}]))))
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@
|
|||
(rx/mapcat #(wapi/create-image-bitmap % #js {:resizeWidth width
|
||||
:resizeQuality "medium"}))
|
||||
(rx/tap #(wapi/revoke-uri uri)))))
|
||||
|
||||
(rx/mapcat bitmap->blob))))
|
||||
|
||||
(defn- on-message
|
||||
|
|
|
@ -62,18 +62,21 @@
|
|||
|
||||
(defn- render-thumbnail
|
||||
[{:keys [page file-id revn] :as params}]
|
||||
(binding [fonts/loaded-hints (l/atom #{})]
|
||||
(let [objects (:objects page)
|
||||
frame (some->> page :thumbnail-frame-id (get objects))
|
||||
element (if frame
|
||||
(mf/element render/frame-svg #js {:objects objects :frame frame :show-thumbnails? true})
|
||||
(mf/element render/page-svg #js {:data page :thumbnails? true :render-embed? true}))
|
||||
data (rds/renderToStaticMarkup element)]
|
||||
|
||||
{:data data
|
||||
:fonts @fonts/loaded-hints
|
||||
:file-id file-id
|
||||
:revn revn})))
|
||||
(try
|
||||
(binding [fonts/loaded-hints (l/atom #{})]
|
||||
(let [objects (:objects page)
|
||||
frame (some->> page :thumbnail-frame-id (get objects))
|
||||
element (if frame
|
||||
(mf/element render/frame-svg #js {:objects objects :frame frame :show-thumbnails? true})
|
||||
(mf/element render/page-svg #js {:data page :thumbnails? true :render-embed? true}))
|
||||
data (rds/renderToStaticMarkup element)]
|
||||
{:data data
|
||||
:fonts @fonts/loaded-hints
|
||||
:file-id file-id
|
||||
:revn revn}))
|
||||
(catch :default cause
|
||||
(js/console.error "unexpected erorr on rendering thumbnail" cause)
|
||||
nil)))
|
||||
|
||||
(defmethod impl/handler :thumbnails/generate-for-file
|
||||
[{:keys [file-id revn features] :as message} _]
|
||||
|
@ -85,9 +88,7 @@
|
|||
(let [canvas (js/OffscreenCanvas. (.-width ^js ibpm) (.-height ^js ibpm))
|
||||
ctx (.getContext ^js canvas "bitmaprenderer")
|
||||
tp (ts/tpoint-ms)]
|
||||
|
||||
(.transferFromImageBitmap ^js ctx ibpm)
|
||||
|
||||
(->> (.convertToBlob ^js canvas #js {:type "image/png"})
|
||||
(p/fmap (fn [blob]
|
||||
{:result (wapi/create-uri blob)}))
|
||||
|
|
|
@ -4406,14 +4406,13 @@ randomfill@^1.0.3:
|
|||
randombytes "^2.0.5"
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
react-dom@~17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
react-dom@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-is@^16.13.1:
|
||||
version "16.13.1"
|
||||
|
@ -4437,13 +4436,12 @@ react-virtualized@^9.22.3:
|
|||
prop-types "^15.7.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react@~17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
read-pkg-up@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
@ -4757,13 +4755,12 @@ sax@^1.2.4, sax@~1.2.4:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
semver-greatest-satisfied-range@^1.1.0:
|
||||
version "1.1.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue