diff --git a/backend/src/app/rpc/queries/fonts.clj b/backend/src/app/rpc/queries/fonts.clj index b25c780f5..117de3e91 100644 --- a/backend/src/app/rpc/queries/fonts.clj +++ b/backend/src/app/rpc/queries/fonts.clj @@ -8,12 +8,16 @@ (:require [app.common.spec :as us] [app.db :as db] + [app.rpc.queries.files :as files] + [app.rpc.queries.projects :as projects] [app.rpc.queries.teams :as teams] [app.util.services :as sv] [clojure.spec.alpha :as s])) ;; --- Query: Team Font Variants +;; TODO: deprecated, should be removed on 1.7.x + (s/def ::team-id ::us/uuid) (s/def ::profile-id ::us/uuid) (s/def ::team-font-variants @@ -27,3 +31,43 @@ {:team-id team-id :deleted-at nil}))) +;; --- Query: Font Variants + +(s/def ::file-id ::us/uuid) +(s/def ::project-id ::us/uuid) +(s/def ::font-variants + (s/and + (s/keys :req-un [::profile-id] + :opt-un [::team-id + ::file-id + ::project-id]) + (fn [o] + (or (contains? o :team-id) + (contains? o :file-id) + (contains? o :project-id))))) + +(sv/defmethod ::font-variants + [{:keys [pool] :as cfg} {:keys [profile-id team-id file-id project-id] :as params}] + (with-open [conn (db/open pool)] + (cond + (uuid? team-id) + (do + (teams/check-read-permissions! conn profile-id team-id) + (db/query conn :team-font-variant + {:team-id team-id + :deleted-at nil})) + + (uuid? project-id) + (let [project (db/get-by-id conn :project project-id {:columns [:id :team-id]})] + (projects/check-read-permissions! conn profile-id project-id) + (db/query conn :team-font-variant + {:team-id (:team-id project) + :deleted-at nil})) + + (uuid? file-id) + (let [file (db/get-by-id conn :file file-id {:columns [:id :project-id]}) + project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]})] + (files/check-read-permissions! conn profile-id file-id) + (db/query conn :team-font-variant + {:team-id (:team-id project) + :deleted-at nil}))))) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 0c7b8183d..5f57aaec3 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -356,8 +356,8 @@ ([shape {:keys [round-coords?] :or {round-coords? true}}] - (let [shape (apply-displacement shape) - center (gco/center-shape shape) + (let [shape (apply-displacement shape) + center (gco/center-shape shape) modifiers (:modifiers shape)] (if (and modifiers center) (let [transform (modifiers->transform center modifiers)] @@ -376,7 +376,7 @@ :y (- (:y new-selrect 0) (:y selrect 0)) :width (- (:width new-selrect 1) (:width selrect 1)) :height (- (:height new-selrect 1) (:height selrect 1))}] - + (cond-> group (and (some? svg-viewbox) (some? selrect) (some? new-selrect)) (update :svg-viewbox diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs index e6cbfe815..5acec3b8d 100644 --- a/frontend/src/app/main/data/fonts.cljs +++ b/frontend/src/app/main/data/fonts.cljs @@ -25,7 +25,7 @@ ;; General purpose events & IMPL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn team-fonts-loaded +(defn fonts-fetched [fonts] (letfn [;; Prepare font to the internal font database format. (prepare-font [[id [item :as items]]] @@ -74,8 +74,8 @@ (ptk/reify ::load-team-fonts ptk/WatchEvent (watch [_ state stream] - (->> (rp/query :team-font-variants {:team-id team-id}) - (rx/map team-fonts-loaded))))) + (->> (rp/query :font-variants {:team-id team-id}) + (rx/map fonts-fetched))))) (defn process-upload "Given a seq of blobs and the team id, creates a ready-to-use fonts diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index aa5e08c21..77ab79918 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -7,26 +7,26 @@ (ns app.main.exports "The main logic for SVG export functionality." (:require - [rumext.alpha :as mf] - [cuerdas.core :as str] - [app.common.uuid :as uuid] - [app.common.pages :as cp] - [app.common.math :as mth] - [app.common.geom.shapes :as gsh] [app.common.geom.align :as gal] - [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] - [app.util.timers :as ts] + [app.common.geom.point :as gpt] + [app.common.geom.shapes :as gsh] + [app.common.math :as mth] + [app.common.pages :as cp] + [app.common.uuid :as uuid] + [app.main.ui.shapes.circle :as circle] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.frame :as frame] - [app.main.ui.shapes.circle :as circle] + [app.main.ui.shapes.group :as group] [app.main.ui.shapes.image :as image] [app.main.ui.shapes.path :as path] [app.main.ui.shapes.rect :as rect] - [app.main.ui.shapes.text :as text] - [app.main.ui.shapes.group :as group] + [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.svg-raw :as svg-raw] - [app.main.ui.shapes.shape :refer [shape-container]])) + [app.main.ui.shapes.text :as text] + [app.util.timers :as ts] + [cuerdas.core :as str] + [rumext.alpha :as mf])) (def ^:private default-color "#E8E9EA") ;; $color-canvas diff --git a/frontend/src/app/main/repo.cljs b/frontend/src/app/main/repo.cljs index 36d935ffb..e2405a8d7 100644 --- a/frontend/src/app/main/repo.cljs +++ b/frontend/src/app/main/repo.cljs @@ -20,7 +20,7 @@ (cond (= 204 status) ;; We need to send "something" so the streams listening downstream can act - (rx/of :empty) + (rx/of nil) (= 502 status) (rx/throw {:type :bad-gateway}) diff --git a/frontend/src/app/main/ui/render.cljs b/frontend/src/app/main/ui/render.cljs index 1060de4d3..c56e85a98 100644 --- a/frontend/src/app/main/ui/render.cljs +++ b/frontend/src/app/main/ui/render.cljs @@ -12,11 +12,14 @@ [app.common.math :as mth] [app.common.pages :as cp] [app.common.uuid :as uuid] + [app.main.store :as st] + [app.main.data.fonts :as df] [app.main.exports :as exports] [app.main.repo :as repo] [app.main.ui.context :as muc] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.shapes.text.embed :refer [embed-fontfaces-style]] [beicon.core :as rx] [cljs.spec.alpha :as s] [cuerdas.core :as str] @@ -42,6 +45,9 @@ objects (reduce updt-fn objects mod-ids) object (get objects object-id) + txt-xfm (comp (map #(get objects %)) + (filter #(= :text (:type %)))) + txt-objs (into [] txt-xfm mod-ids) {:keys [width height]} (gsh/points->selrect (:points object)) @@ -72,6 +78,9 @@ ] [:& (mf/provider muc/embed-ctx) {:value true} + (when (seq txt-objs) + [:& embed-fontfaces-style {:shapes txt-objs}]) + [:svg {:id "screenshot" :view-box vbox :width width @@ -79,6 +88,7 @@ :version "1.1" :xmlnsXlink "http://www.w3.org/1999/xlink" :xmlns "http://www.w3.org/2000/svg"} + (case (:type object) :frame [:& frame-wrapper {:shape object :view-box vbox}] :group [:> shape-container {:shape object} @@ -97,7 +107,6 @@ (assoc objects (:id object) object)) objects)) - ;; NOTE: for now, it is ok download the entire file for render only ;; single page but in a future we need consider to add a specific ;; backend entry point for download only the data of single page. @@ -106,12 +115,19 @@ [{:keys [file-id page-id object-id] :as props}] (let [objects (mf/use-state nil)] (mf/use-effect - #(let [subs (->> (repo/query! :file {:id file-id}) - (rx/subs (fn [{:keys [data]}] - (let [objs (get-in data [:pages-index page-id :objects]) - objs (adapt-root-frame objs object-id)] - (reset! objects objs)))))] - (fn [] (rx/dispose! subs)))) + (mf/deps file-id page-id object-id) + (fn [] + (->> (rx/zip + (repo/query! :font-variants {:file-id file-id}) + (repo/query! :file {:id file-id})) + (rx/subs + (fn [[fonts {:keys [data]} :as kaka]] + (when (seq fonts) + (st/emit! (df/fonts-fetched fonts))) + (let [objs (get-in data [:pages-index page-id :objects]) + objs (adapt-root-frame objs object-id)] + (reset! objects objs))))) + (constantly nil))) (when @objects [:& object-svg {:objects @objects diff --git a/frontend/src/app/main/ui/shapes/text/embed.cljs b/frontend/src/app/main/ui/shapes/text/embed.cljs index dde62afd5..22999cd32 100644 --- a/frontend/src/app/main/ui/shapes/text/embed.cljs +++ b/frontend/src/app/main/ui/shapes/text/embed.cljs @@ -86,12 +86,6 @@ :weight weight})] (p/resolved result)))) -(defn- to-promise - [observable] - (p/create (fn [resolve reject] - (->> (rx/take 1 observable) - (rx/subs resolve reject))))) - (defn fetch-font-data "Parses the CSS and retrieves the font data as DataURI." [^string css] @@ -137,10 +131,10 @@ {::mf/wrap-props false ::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]} [props] - (let [shapes (obj/get props "shapes") - node {:children (->> shapes (map :content))} - fonts (-> node get-node-fonts memoize) - style (mf/use-state nil)] + (let [shapes (obj/get props "shapes") + node {:children (->> shapes (map :content))} + fonts (-> node get-node-fonts memoize) + style (mf/use-state nil)] (mf/use-effect (mf/deps fonts) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 8875ba6e5..b6744c346 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -102,23 +102,20 @@ {::mf/wrap [#(mf/memo' % check-frame-props) custom-deferred] ::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") - objects (unchecked-get props "objects") - thumbnail? (unchecked-get props "thumbnail?") + (let [shape (unchecked-get props "shape") + objects (unchecked-get props "objects") + thumbnail? (unchecked-get props "thumbnail?") - edition (mf/deref refs/selected-edition) + edition (mf/deref refs/selected-edition) embed-fonts? (mf/use-ctx muc/embed-ctx) - shape (gsh/transform-shape shape) - children (mapv #(get objects %) (:shapes shape)) - text-childs (->> objects - vals - (filterv #(and (= :text (:type %)) - (= (:id shape) (:frame-id %))))) + shape (gsh/transform-shape shape) + children (mapv #(get objects %) (:shapes shape)) + text-childs (->> (vals objects) + (filterv #(and (= :text (:type %)) + (= (:id shape) (:frame-id %))))) - ds-modifier (get-in shape [:modifiers :displacement]) - - rendered? (mf/use-state false) + rendered? (mf/use-state false) show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))