mirror of
https://github.com/penpot/penpot.git
synced 2025-05-15 01:47:07 +02:00
🎉 Make components-v2 an optional feature
This commit is contained in:
parent
1ef37281e6
commit
a5bf1c03e7
40 changed files with 495 additions and 296 deletions
|
@ -16,6 +16,7 @@
|
|||
[app.main.sentry :as sentry]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui :as ui]
|
||||
[app.main.ui.alert]
|
||||
[app.main.ui.confirm]
|
||||
[app.main.ui.modal :refer [modal]]
|
||||
[app.main.ui.routes :as rt]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.main.data.fonts :as df]
|
||||
[app.main.data.media :as di]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
|
@ -718,12 +719,13 @@
|
|||
(-deref [_] {:project-id project-id})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [it _ _]
|
||||
(watch [it state _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)
|
||||
name (name (gensym (str (tr "dashboard.new-file-prefix") " ")))
|
||||
params (assoc params :name name)]
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
params (assoc params :name name :components-v2 components-v2)]
|
||||
|
||||
(->> (rp/mutation! :create-file params)
|
||||
(rx/tap on-success)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.router :as rt]
|
||||
|
@ -100,9 +101,15 @@
|
|||
(us/assert ::fetch-bundle-params params)
|
||||
(ptk/reify ::fetch-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params' (cond-> {:file-id file-id}
|
||||
(uuid? share-id) (assoc :share-id share-id))]
|
||||
(watch [_ state _]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
params' (cond-> {:file-id file-id}
|
||||
(uuid? share-id)
|
||||
(assoc :share-id share-id)
|
||||
|
||||
:always
|
||||
(assoc :components-v2 components-v2))]
|
||||
|
||||
(->> (rp/query :view-only-bundle params')
|
||||
(rx/mapcat
|
||||
(fn [{:keys [fonts] :as bundle}]
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
process-page-changes
|
||||
(fn [[page-id _changes]]
|
||||
(update-indices page-id redo-changes))]
|
||||
|
||||
(rx/concat
|
||||
(rx/from (map process-page-changes changes-by-pages))
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
|
@ -283,7 +284,7 @@
|
|||
|
||||
(defn- add-component2
|
||||
"This is the second step of the component creation."
|
||||
[selected]
|
||||
[selected components-v2]
|
||||
(ptk/reify ::add-component2
|
||||
IDeref
|
||||
(-deref [_] {:num-shapes (count selected)})
|
||||
|
@ -296,7 +297,7 @@
|
|||
shapes (dwg/shapes-for-grouping objects selected)]
|
||||
(when-not (empty? shapes)
|
||||
(let [[group _ changes]
|
||||
(dwlh/generate-add-component it shapes objects page-id file-id)]
|
||||
(dwlh/generate-add-component it shapes objects page-id file-id components-v2)]
|
||||
(when-not (empty? (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dws/select-shapes (d/ordered-set (:id group)))))))))))
|
||||
|
@ -310,10 +311,11 @@
|
|||
(ptk/reify ::add-component
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))]
|
||||
(rx/of (add-component2 selected))))))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(rx/of (add-component2 selected components-v2))))))
|
||||
|
||||
(defn rename-component
|
||||
"Rename the component with the given id, in the current file library."
|
||||
|
@ -357,8 +359,12 @@
|
|||
unames (into #{} (map :name) all-components)
|
||||
new-name (ctst/generate-unique-name unames (:name component))
|
||||
|
||||
main-instance-page (wsh/lookup-page state (:main-instance-page component))
|
||||
main-instance-shape (ctn/get-shape main-instance-page (:main-instance-id component))
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
main-instance-page (when components-v2
|
||||
(wsh/lookup-page state (:main-instance-page component)))
|
||||
main-instance-shape (when components-v2
|
||||
(ctn/get-shape main-instance-page (:main-instance-id component)))
|
||||
|
||||
[new-component-shape new-component-shapes
|
||||
new-main-instance-shape new-main-instance-shapes]
|
||||
|
@ -606,7 +612,11 @@
|
|||
"Synchronize the given file from the given library. Walk through all
|
||||
shapes in all pages in the file that use some color, typography or
|
||||
component of the library, and copy the new values to the shapes. Do
|
||||
it also for shapes inside components of the local file library."
|
||||
it also for shapes inside components of the local file library.
|
||||
|
||||
If it's known that only one asset has changed, you can give its
|
||||
type and id, and only shapes that use it will be synced, thus avoiding
|
||||
a lot of unneeded checks."
|
||||
([file-id library-id]
|
||||
(sync-file file-id library-id nil nil))
|
||||
([file-id library-id asset-type asset-id]
|
||||
|
@ -752,8 +762,10 @@
|
|||
[]
|
||||
(ptk/reify ::watch-component-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(let [stopper
|
||||
(watch [_ state stream]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
stopper
|
||||
(->> stream
|
||||
(rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %))
|
||||
(= ::watch-component-changes (ptk/type %)))))
|
||||
|
@ -775,16 +787,16 @@
|
|||
components-changed (reduce #(into %1 (ch/components-changed data %2))
|
||||
#{}
|
||||
changes)]
|
||||
(js/console.log "components-changed" (clj->js components-changed))
|
||||
(when (d/not-empty? components-changed)
|
||||
(apply st/emit!
|
||||
(map #(update-component-sync % (:id data))
|
||||
components-changed)))))]
|
||||
|
||||
(->> change-str
|
||||
(rx/with-latest-from workspace-data-str)
|
||||
(rx/map check-changes)
|
||||
(rx/take-until stopper))))))
|
||||
(when components-v2
|
||||
(->> change-str
|
||||
(rx/with-latest-from workspace-data-str)
|
||||
(rx/map check-changes)
|
||||
(rx/take-until stopper)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Backend interactions
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
"If there is exactly one id, and it's a group, use it as root. Otherwise,
|
||||
create a group that contains all ids. Then, make a component with it,
|
||||
and link all shapes to their corresponding one in the component."
|
||||
[it shapes objects page-id file-id]
|
||||
[it shapes objects page-id file-id components-v2]
|
||||
(if (and (= (count shapes) 1)
|
||||
(:component-id (first shapes)))
|
||||
[(first shapes) (pcb/empty-changes it)]
|
||||
|
@ -77,7 +77,7 @@
|
|||
(dwg/prepare-create-group it objects page-id shapes name true))
|
||||
|
||||
[new-shape new-shapes updated-shapes]
|
||||
(ctn/make-component-shape group objects file-id)
|
||||
(ctn/make-component-shape group objects file-id components-v2)
|
||||
|
||||
changes (-> changes
|
||||
(pcb/add-component (:id new-shape)
|
||||
|
@ -106,13 +106,14 @@
|
|||
|
||||
|
||||
[new-instance-shape new-instance-shapes]
|
||||
(ctn/make-component-instance main-instance-page
|
||||
{:id (:id new-component-shape)
|
||||
:name (:name new-component-shape)
|
||||
:objects (d/index-by :id new-component-shapes)}
|
||||
(:component-file main-instance-shape)
|
||||
position
|
||||
false)]
|
||||
(when (and (some? main-instance-page) (some? main-instance-shape))
|
||||
(ctn/make-component-instance main-instance-page
|
||||
{:id (:id new-component-shape)
|
||||
:name (:name new-component-shape)
|
||||
:objects (d/index-by :id new-component-shapes)}
|
||||
(:component-file main-instance-shape)
|
||||
position
|
||||
false))]
|
||||
|
||||
[new-component-shape new-component-shapes
|
||||
new-instance-shape new-instance-shapes]))
|
||||
|
@ -254,7 +255,6 @@
|
|||
(and (if (nil? component-id)
|
||||
(ctk/uses-library-components? shape library-id)
|
||||
(ctk/instance-of? shape library-id component-id))
|
||||
(not (:main-instance? shape)) ; not need to sync the main instance (avoid infinite loop)
|
||||
(or (:component-root? shape) (not page?)))) ; avoid nested components inside pages
|
||||
|
||||
(defmethod uses-assets? :colors
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
[app.config :as cf]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
[app.util.time :as dt]
|
||||
[beicon.core :as rx]
|
||||
|
@ -124,8 +127,7 @@
|
|||
(rx/map persist-synchronous-changes)
|
||||
(rx/take-until (rx/delay 100 stoper))
|
||||
(rx/finalize (fn []
|
||||
(log/debug :hint "finalize persistence: synchronous save loop"))))
|
||||
)))))
|
||||
(log/debug :hint "finalize persistence: synchronous save loop")))))))))
|
||||
|
||||
(defn persist-changes
|
||||
[file-id changes]
|
||||
|
@ -134,12 +136,14 @@
|
|||
(ptk/reify ::persist-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [sid (:session-id state)
|
||||
file (get state :workspace-file)
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes-with-metadata (into [] changes)}]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
sid (:session-id state)
|
||||
file (get state :workspace-file)
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes-with-metadata (into [] changes)
|
||||
:components-v2 components-v2}]
|
||||
|
||||
(when (= file-id (:id params))
|
||||
(->> (rp/mutation :update-file params)
|
||||
|
@ -175,13 +179,15 @@
|
|||
(ptk/reify ::persist-synchronous-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [sid (:session-id state)
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
sid (:session-id state)
|
||||
file (get-in state [:workspace-libraries file-id])
|
||||
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes changes}]
|
||||
:changes changes
|
||||
:components-v2 components-v2}]
|
||||
|
||||
(when (:id params)
|
||||
(->> (rp/mutation :update-file params)
|
||||
|
@ -261,8 +267,9 @@
|
|||
(ptk/reify ::fetch-bundle
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rx/zip (rp/query :file-raw {:id file-id})
|
||||
(let [share-id (-> state :viewer-local :share-id)
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(->> (rx/zip (rp/query :file-raw {:id file-id :components-v2 components-v2})
|
||||
(rp/query :team-users {:file-id file-id})
|
||||
(rp/query :project {:id project-id})
|
||||
(rp/query :file-libraries {:file-id file-id})
|
||||
|
@ -276,8 +283,16 @@
|
|||
:file-comments-users file-comments-users}))
|
||||
(rx/mapcat (fn [{:keys [project] :as bundle}]
|
||||
(rx/of (ptk/data-event ::bundle-fetched bundle)
|
||||
(df/load-team-fonts (:team-id project))))))))))
|
||||
|
||||
(df/load-team-fonts (:team-id project)))))
|
||||
(rx/catch (fn [err]
|
||||
(if (and (= (:type err) :restriction)
|
||||
(= (:code err) :feature-disabled))
|
||||
(let [team-id (:current-team-id state)]
|
||||
(rx/of (modal/show
|
||||
{:type :alert
|
||||
:message (tr "errors.components-v2")
|
||||
:on-accept #(st/emit! (rt/nav :dashboard-projects {:team-id team-id}))})))
|
||||
(rx/throw err)))))))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
|
@ -24,6 +23,7 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.features :as features]
|
||||
[app.main.streams :as ms]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
|
@ -148,7 +148,7 @@
|
|||
ids (cph/clean-loops objects ids)
|
||||
lookup (d/getf objects)
|
||||
|
||||
local-library {file-id {:data file}}
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
|
@ -221,23 +221,16 @@
|
|||
(into (d/ordered-set) (find-all-empty-parents #{}))
|
||||
|
||||
components-to-delete
|
||||
(reduce (fn [components id]
|
||||
(let [shape (get objects id)
|
||||
|
||||
component
|
||||
(when (and (:component-id shape) (:component-file shape))
|
||||
;; Only local components may have main instances
|
||||
(cph/get-component local-library (:component-file shape) (:component-id shape)))
|
||||
|
||||
main-instance?
|
||||
(when component
|
||||
(ctk/is-main-instance? (:id shape) (:id page) component))]
|
||||
|
||||
(if main-instance?
|
||||
(conj components (:component-id shape))
|
||||
components)))
|
||||
[]
|
||||
(into ids all-children))
|
||||
(if components-v2
|
||||
(reduce (fn [components id]
|
||||
(let [shape (get objects id)]
|
||||
(if (and (= (:component-file shape) file-id) ;; Main instances should exist only in local file
|
||||
(:main-instance? shape)) ;; but check anyway
|
||||
(conj components (:component-id shape))
|
||||
components)))
|
||||
[]
|
||||
(into ids all-children))
|
||||
[])
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-page page)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.features
|
||||
(ns app.main.features
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as log]
|
||||
|
@ -15,9 +15,9 @@
|
|||
|
||||
(log/set-level! :debug)
|
||||
|
||||
(def features-list #{:auto-layout})
|
||||
(def features-list #{:auto-layout :components-v2})
|
||||
|
||||
(defn toggle-feature
|
||||
(defn- toggle-feature
|
||||
[feature]
|
||||
(ptk/reify ::toggle-feature
|
||||
ptk/UpdateEvent
|
||||
|
@ -41,6 +41,13 @@
|
|||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(st/emit! (toggle-feature feature)))
|
||||
|
||||
(defn active-feature?
|
||||
([feature]
|
||||
(active-feature? @st/state feature))
|
||||
([state feature]
|
||||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(contains? (get state :features) feature)))
|
||||
|
||||
(def features
|
||||
(l/derived :features st/state))
|
||||
|
78
frontend/src/app/main/ui/alert.cljs
Normal file
78
frontend/src/app/main/ui/alert.cljs
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.alert
|
||||
(:require
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
[app.util.keyboard :as k]
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(mf/defc alert-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :alert}
|
||||
[{:keys [message
|
||||
scd-message
|
||||
title
|
||||
on-accept
|
||||
hint
|
||||
accept-label
|
||||
accept-style] :as props}]
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
|
||||
on-accept (or on-accept identity)
|
||||
message (or message (t locale "ds.alert-title"))
|
||||
accept-label (or accept-label (tr "ds.alert-ok"))
|
||||
accept-style (or accept-style :danger)
|
||||
title (or title (t locale "ds.alert-title"))
|
||||
|
||||
accept-fn
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))]
|
||||
|
||||
(mf/with-effect
|
||||
(letfn [(on-keydown [event]
|
||||
(when (k/enter? event)
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))]
|
||||
(->> (events/listen js/document EventType.KEYDOWN on-keydown)
|
||||
(partial events/unlistenByKey))))
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal-container.alert-dialog
|
||||
[:div.modal-header
|
||||
[:div.modal-header-title
|
||||
[:h2 title]]
|
||||
[:div.modal-close-button
|
||||
{:on-click accept-fn} i/close]]
|
||||
|
||||
[:div.modal-content
|
||||
(when (and (string? message) (not= message ""))
|
||||
[:h3 message])
|
||||
(when (and (string? scd-message) (not= scd-message ""))
|
||||
[:h3 scd-message])
|
||||
(when (string? hint)
|
||||
[:p hint])]
|
||||
|
||||
[:div.modal-footer
|
||||
[:div.action-buttons
|
||||
[:input.accept-button
|
||||
{:class (dom/classnames
|
||||
:danger (= accept-style :danger)
|
||||
:primary (= accept-style :primary))
|
||||
:type "button"
|
||||
:value accept-label
|
||||
:on-click accept-fn}]]]]]))
|
|
@ -25,3 +25,4 @@
|
|||
(def scroll-ctx (mf/create-context nil))
|
||||
(def active-frames-ctx (mf/create-context nil))
|
||||
(def render-thumbnails (mf/create-context nil))
|
||||
(def components-v2 (mf/create-context nil))
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.math :as mth]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.features :as features]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -36,9 +37,11 @@
|
|||
(defn ask-for-thumbnail
|
||||
"Creates some hooks to handle the files thumbnails cache"
|
||||
[file]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)}))
|
||||
(let [components-v2 (features/active-feature? :components-v2)]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)
|
||||
:components-v2 components-v2})))
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.main.data.messages :as msg]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
|
@ -114,13 +115,12 @@
|
|||
(mf/defc workspace
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [project-id file-id page-id layout-name] :as props}]
|
||||
(let [file (mf/deref refs/workspace-file)
|
||||
project (mf/deref refs/workspace-project)
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
libraries (mf/deref refs/workspace-libraries)
|
||||
local-library (mf/deref refs/workspace-local-library)
|
||||
(let [file (mf/deref refs/workspace-file)
|
||||
project (mf/deref refs/workspace-project)
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
|
||||
components-v2 (features/use-feature :components-v2)
|
||||
|
||||
background-color (:background-color wglobal)]
|
||||
|
||||
|
@ -148,9 +148,7 @@
|
|||
[:& (mf/provider ctx/current-team-id) {:value (:team-id project)}
|
||||
[:& (mf/provider ctx/current-project-id) {:value (:id project)}
|
||||
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
||||
[:& (mf/provider ctx/libraries) {:value (assoc libraries
|
||||
(:id local-library)
|
||||
{:data local-library})}
|
||||
[:& (mf/provider ctx/components-v2) {:value components-v2}
|
||||
[:section#workspace {:style {:background-color background-color}}
|
||||
(when (not (:hide-ui layout))
|
||||
[:& header {:file file
|
||||
|
@ -169,5 +167,3 @@
|
|||
:layout layout}]
|
||||
[:& workspace-loader])]]]]]]))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
|
@ -87,7 +86,7 @@
|
|||
(when (seq (:touched shape)) " *")])))
|
||||
|
||||
(mf/defc layer-item
|
||||
[{:keys [index page item selected objects] :as props}]
|
||||
[{:keys [index item selected objects] :as props}]
|
||||
(let [id (:id item)
|
||||
blocked? (:blocked item)
|
||||
hidden? (:hidden item)
|
||||
|
@ -103,11 +102,10 @@
|
|||
container? (or (cph/frame-shape? item)
|
||||
(cph/group-shape? item))
|
||||
|
||||
libraries (mf/use-ctx ctx/libraries)
|
||||
component (when (and (:component-id item) (:component-file item))
|
||||
(cph/get-component libraries (:component-file item) (:component-id item)))
|
||||
main-instance? (when component
|
||||
(ctk/is-main-instance? (:id item) (:id page) component))
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
main-instance? (if components-v2
|
||||
(:main-instance? item)
|
||||
true)
|
||||
|
||||
toggle-collapse
|
||||
(mf/use-fn
|
||||
|
@ -277,8 +275,7 @@
|
|||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& layer-item
|
||||
{:page page
|
||||
:item item
|
||||
{:item item
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
|
@ -299,9 +296,8 @@
|
|||
{::mf/wrap [#(mf/memo % =)
|
||||
#(mf/throttle % 200)]}
|
||||
[{:keys [objects] :as props}]
|
||||
(let [page (mf/deref refs/workspace-page)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected (hooks/use-equal-memo selected)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
selected (hooks/use-equal-memo selected)
|
||||
root (get objects uuid/zero)]
|
||||
[:ul.element-list
|
||||
[:& hooks/sortable-container {}
|
||||
|
@ -315,8 +311,7 @@
|
|||
:objects objects
|
||||
:key id}]
|
||||
[:& layer-item
|
||||
{:page page
|
||||
:item obj
|
||||
{:item obj
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
|
@ -326,16 +321,14 @@
|
|||
{::mf/wrap [#(mf/memo % =)
|
||||
#(mf/throttle % 200)]}
|
||||
[{:keys [objects] :as props}]
|
||||
(let [page (mf/deref refs/workspace-page)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
selected (hooks/use-equal-memo selected)
|
||||
root (get objects uuid/zero)]
|
||||
[:ul.element-list
|
||||
(for [[index id] (d/enumerate (:shapes root))]
|
||||
(when-let [obj (get objects id)]
|
||||
[:& layer-item
|
||||
{:page page
|
||||
:item obj
|
||||
{:item obj
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.component
|
||||
(:require
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -19,13 +17,12 @@
|
|||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(def component-attrs [:component-id :component-file :shape-ref])
|
||||
(def component-attrs [:component-id :component-file :shape-ref :main-instance?])
|
||||
|
||||
(mf/defc component-menu
|
||||
[{:keys [ids values shape-name] :as props}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
current-page-id (mf/use-ctx ctx/current-page-id)
|
||||
libraries (mf/use-ctx ctx/libraries)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
|
||||
id (first ids)
|
||||
local (mf/use-state {:menu-open false})
|
||||
|
@ -33,10 +30,9 @@
|
|||
component-id (:component-id values)
|
||||
library-id (:component-file values)
|
||||
show? (some? component-id)
|
||||
|
||||
component (when (and component-id library-id)
|
||||
(cph/get-component libraries library-id component-id))
|
||||
main-instance? (ctk/is-main-instance? id current-page-id component)
|
||||
main-instance? (if components-v2
|
||||
(:main-instance? values)
|
||||
true)
|
||||
|
||||
on-menu-click
|
||||
(mf/use-callback
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.frame
|
||||
(:require
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.features :as features]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs-shape fill-menu]]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.features :as features]
|
||||
[app.main.render :as render]
|
||||
[app.main.repo :as repo]
|
||||
[app.main.store :as st]
|
||||
|
@ -99,22 +100,24 @@
|
|||
|
||||
(mf/defc object-svg
|
||||
[{:keys [page-id file-id object-id render-embed?]}]
|
||||
(let [fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id object-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)}))))))
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id object-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)}))))))
|
||||
|
||||
{:keys [objects object]} (use-resource fetch-state)]
|
||||
|
||||
|
@ -124,8 +127,8 @@
|
|||
(when object
|
||||
(dom/set-page-style!
|
||||
{:size (str/concat
|
||||
(mth/ceil (:width object)) "px "
|
||||
(mth/ceil (:height object)) "px")})))
|
||||
(mth/ceil (:width object)) "px "
|
||||
(mth/ceil (:height object)) "px")})))
|
||||
|
||||
(when objects
|
||||
[:& render/object-svg
|
||||
|
@ -135,17 +138,19 @@
|
|||
|
||||
(mf/defc objects-svg
|
||||
[{:keys [page-id file-id object-ids render-embed?]}]
|
||||
(let [fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second)))))
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second)))))
|
||||
|
||||
objects (use-resource fetch-state)]
|
||||
|
||||
|
|
|
@ -48,11 +48,12 @@
|
|||
(= :request-body-too-large code)))
|
||||
|
||||
(defn- request-data-for-thumbnail
|
||||
[file-id revn]
|
||||
[file-id revn components-v2]
|
||||
(let [path "api/rpc/query/file-data-for-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn
|
||||
:strip-frames-with-thumbnails true}
|
||||
:strip-frames-with-thumbnails true
|
||||
:components-v2 components-v2}
|
||||
request {:method :get
|
||||
:uri (u/join (cfg/get-public-uri) path)
|
||||
:credentials "include"
|
||||
|
@ -107,18 +108,18 @@
|
|||
(rx/map (constantly params)))))
|
||||
|
||||
(defmethod impl/handler :thumbnails/generate
|
||||
[{:keys [file-id revn] :as message}]
|
||||
[{:keys [file-id revn components-v2] :as message}]
|
||||
(letfn [(on-result [{:keys [data props]}]
|
||||
{:data data
|
||||
:fonts (:fonts props)})
|
||||
|
||||
(on-cache-miss [_]
|
||||
(->> (request-data-for-thumbnail file-id revn)
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(rx/map render-thumbnail)
|
||||
(rx/mapcat persist-thumbnail)))]
|
||||
|
||||
(if (debug? :disable-thumbnail-cache)
|
||||
(->> (request-data-for-thumbnail file-id revn)
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(rx/map render-thumbnail))
|
||||
(->> (request-thumbnail file-id revn)
|
||||
(rx/catch not-found? on-cache-miss)
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
;; This namespace is only to export the functions for toggle features
|
||||
(ns features
|
||||
(:require
|
||||
[app.main.ui.features :as features]))
|
||||
[app.main.features :as features]))
|
||||
|
||||
(defn ^:export autolayout []
|
||||
(features/toggle-feature! :auto-layout))
|
||||
|
||||
(defn ^:export components-v2 []
|
||||
(features/toggle-feature! :components-v2))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue