mirror of
https://github.com/penpot/penpot.git
synced 2025-08-07 14:38:33 +02:00
Merge pull request #1947 from penpot/alotor-hotfix-1.13
Alotor hotfix 1.13
This commit is contained in:
commit
6a8f3c7283
15 changed files with 172 additions and 67 deletions
|
@ -9,7 +9,7 @@
|
||||||
[app.common.colors :as clr]
|
[app.common.colors :as clr]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
(def file-version 17)
|
(def file-version 18)
|
||||||
(def default-color clr/gray-20)
|
(def default-color clr/gray-20)
|
||||||
(def root uuid/zero)
|
(def root uuid/zero)
|
||||||
|
|
||||||
|
|
|
@ -400,5 +400,20 @@
|
||||||
(update :pages-index d/update-vals update-container)
|
(update :pages-index d/update-vals update-container)
|
||||||
(update :components d/update-vals update-container))))
|
(update :components d/update-vals update-container))))
|
||||||
|
|
||||||
|
;;Remove position-data to solve a bug with the text positioning
|
||||||
|
(defmethod migrate 18
|
||||||
|
[data]
|
||||||
|
(letfn [(update-object [object]
|
||||||
|
(cond-> object
|
||||||
|
(cph/text-shape? object)
|
||||||
|
(dissoc :position-data)))
|
||||||
|
|
||||||
|
(update-container [container]
|
||||||
|
(update container :objects d/update-vals update-object))]
|
||||||
|
|
||||||
|
(-> data
|
||||||
|
(update :pages-index d/update-vals update-container)
|
||||||
|
(update :components d/update-vals update-container))))
|
||||||
|
|
||||||
;; TODO: pending to do a migration for delete already not used fill
|
;; TODO: pending to do a migration for delete already not used fill
|
||||||
;; and stroke props. This should be done for >1.14.x version.
|
;; and stroke props. This should be done for >1.14.x version.
|
||||||
|
|
|
@ -195,13 +195,26 @@
|
||||||
(ptk/reify ::handle-file-change
|
(ptk/reify ::handle-file-change
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(let [changes-by-pages (group-by :page-id changes)
|
(let [position-data-operation?
|
||||||
|
(fn [{:keys [type attr]}]
|
||||||
|
(and (= :set type) (= attr :position-data)))
|
||||||
|
|
||||||
|
remove-update-position-data
|
||||||
|
(fn [change]
|
||||||
|
(cond-> change
|
||||||
|
(= :mod-obj (:type change))
|
||||||
|
(update :operations #(filterv (comp not position-data-operation?) %))))
|
||||||
|
|
||||||
process-page-changes
|
process-page-changes
|
||||||
(fn [[page-id changes]]
|
(fn [[page-id changes]]
|
||||||
(dch/update-indices page-id changes))]
|
(dch/update-indices page-id changes))
|
||||||
|
|
||||||
|
;; We remove `position-data` from the incomming message
|
||||||
|
changes (->> changes (mapv remove-update-position-data))
|
||||||
|
changes-by-pages (group-by :page-id changes)]
|
||||||
|
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (dwp/shapes-changes-persisted file-id msg))
|
(rx/of (dwp/shapes-changes-persisted file-id (assoc msg :changes changes)))
|
||||||
|
|
||||||
(when-not (empty? changes-by-pages)
|
(when-not (empty? changes-by-pages)
|
||||||
(rx/from (map process-page-changes changes-by-pages))))))))
|
(rx/from (map process-page-changes changes-by-pages))))))))
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defonce loaded (l/atom #{}))
|
(defonce loaded (l/atom #{}))
|
||||||
|
(defonce loading (l/atom {}))
|
||||||
|
|
||||||
(defn- create-link-element
|
(defn- create-link-element
|
||||||
[uri]
|
[uri]
|
||||||
|
@ -199,11 +200,34 @@
|
||||||
(p/create (fn [resolve]
|
(p/create (fn [resolve]
|
||||||
(ensure-loaded! id resolve))))
|
(ensure-loaded! id resolve))))
|
||||||
([id on-loaded]
|
([id on-loaded]
|
||||||
(if (contains? @loaded id)
|
(let [font (get @fontsdb id)]
|
||||||
(on-loaded id)
|
(cond
|
||||||
(when-let [font (get @fontsdb id)]
|
;; Font already loaded, we just continue
|
||||||
(load-font (assoc font ::on-loaded on-loaded))
|
(contains? @loaded id)
|
||||||
(swap! loaded conj id)))))
|
(on-loaded id)
|
||||||
|
|
||||||
|
;; Font is currently downloading. We attach the caller to the promise
|
||||||
|
(contains? @loading id)
|
||||||
|
(-> (get @loading id)
|
||||||
|
(p/then #(on-loaded id)))
|
||||||
|
|
||||||
|
;; First caller, we create the promise and then wait
|
||||||
|
:else
|
||||||
|
(let [on-load (fn [resolve]
|
||||||
|
(swap! loaded conj id)
|
||||||
|
(swap! loading dissoc id)
|
||||||
|
(on-loaded id)
|
||||||
|
(resolve id))
|
||||||
|
|
||||||
|
load-p (p/create
|
||||||
|
(fn [resolve _]
|
||||||
|
(-> font
|
||||||
|
(assoc ::on-loaded (partial on-load resolve))
|
||||||
|
(load-font))))]
|
||||||
|
|
||||||
|
(swap! loading assoc id load-p)
|
||||||
|
|
||||||
|
nil)))))
|
||||||
|
|
||||||
(defn ready
|
(defn ready
|
||||||
[cb]
|
[cb]
|
||||||
|
|
|
@ -73,8 +73,12 @@
|
||||||
;; Creates a style tag by replacing the urls with the data uri
|
;; Creates a style tag by replacing the urls with the data uri
|
||||||
style (replace-embeds fonts-css fonts-urls fonts-embed)]
|
style (replace-embeds fonts-css fonts-urls fonts-embed)]
|
||||||
|
|
||||||
(when (d/not-empty? style)
|
(cond
|
||||||
[:style {:data-loading loading?} style])))
|
(d/not-empty? style)
|
||||||
|
[:style {:data-loading loading?} style]
|
||||||
|
|
||||||
|
(d/not-empty? fonts)
|
||||||
|
[:style {:data-loading true}])))
|
||||||
|
|
||||||
(defn shape->fonts
|
(defn shape->fonts
|
||||||
[shape objects]
|
[shape objects]
|
||||||
|
|
|
@ -110,7 +110,10 @@
|
||||||
(let [font-variant (d/seek #(= font-variant-id (:id %)) (:variants font))]
|
(let [font-variant (d/seek #(= font-variant-id (:id %)) (:variants font))]
|
||||||
[(str/quote (or (:family font) (:font-family data)))
|
[(str/quote (or (:family font) (:font-family data)))
|
||||||
(or (:style font-variant) (:font-style data))
|
(or (:style font-variant) (:font-style data))
|
||||||
(or (:weight font-variant) (:font-weight data))]))]
|
(or (:weight font-variant) (:font-weight data))]))
|
||||||
|
|
||||||
|
base (-> base
|
||||||
|
(obj/set! "--font-id" font-id))]
|
||||||
|
|
||||||
(cond-> base
|
(cond-> base
|
||||||
(some? fills)
|
(some? fills)
|
||||||
|
|
|
@ -128,7 +128,8 @@
|
||||||
[:& (mf/provider ctx/render-ctx) {:value render-id}
|
[:& (mf/provider ctx/render-ctx) {:value render-id}
|
||||||
[:g.frame-container {:id (dm/str "frame-container-" (:id shape))
|
[:g.frame-container {:id (dm/str "frame-container-" (:id shape))
|
||||||
:key "frame-container"
|
:key "frame-container"
|
||||||
:ref on-frame-load}
|
:ref on-frame-load
|
||||||
|
:opacity (when (:hidden shape) 0)}
|
||||||
[:& ff/fontfaces-style {:fonts fonts}]
|
[:& ff/fontfaces-style {:fonts fonts}]
|
||||||
[:g.frame-thumbnail-wrapper {:id (dm/str "thumbnail-container-" (:id shape))}
|
[:g.frame-thumbnail-wrapper {:id (dm/str "thumbnail-container-" (:id shape))}
|
||||||
[:> frame/frame-thumbnail {:key (dm/str (:id shape))
|
[:> frame/frame-thumbnail {:key (dm/str (:id shape))
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
(fn []
|
(fn []
|
||||||
(when (and (some? @node-ref) @regenerate-thumbnail)
|
(when (and (some? @node-ref) @regenerate-thumbnail)
|
||||||
(let [loading-images? (some? (dom/query @node-ref "[data-loading='true']"))
|
(let [loading-images? (some? (dom/query @node-ref "[data-loading='true']"))
|
||||||
loading-fonts? (some? (dom/query (dm/str "#frame-container-" (:id shape) " style[data-loading='true']")))]
|
loading-fonts? (some? (dom/query (dm/str "#frame-container-" (:id shape) " > style[data-loading='true']")))]
|
||||||
(when (and (not loading-images?) (not loading-fonts?))
|
(when (and (not loading-images?) (not loading-fonts?))
|
||||||
(generate-thumbnail)
|
(generate-thumbnail)
|
||||||
(reset! regenerate-thumbnail false))))))
|
(reset! regenerate-thumbnail false))))))
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
[app.util.text-editor :as ted]
|
[app.util.text-editor :as ted]
|
||||||
[app.util.text-svg-position :as utp]
|
[app.util.text-svg-position :as utp]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
|
[promesa.core :as p]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(defn strip-position-data [shape]
|
(defn strip-position-data [shape]
|
||||||
|
@ -73,25 +74,25 @@
|
||||||
(st/emit! (dwt/resize-text id width height)))))
|
(st/emit! (dwt/resize-text id width height)))))
|
||||||
|
|
||||||
;; Update the position-data of every text fragment
|
;; Update the position-data of every text fragment
|
||||||
(let [position-data (utp/calc-position-data node)]
|
(p/let [position-data (utp/calc-position-data node)]
|
||||||
(st/emit! (dwt/update-position-data id position-data)))
|
(st/emit! (dwt/update-position-data id position-data)))
|
||||||
|
|
||||||
(st/emit! (dwt/clean-text-modifier id)))
|
(st/emit! (dwt/clean-text-modifier id)))
|
||||||
|
|
||||||
(defn- update-text-modifier
|
(defn- update-text-modifier
|
||||||
[{:keys [grow-type id]} node]
|
[{:keys [grow-type id]} node]
|
||||||
(let [position-data (utp/calc-position-data node)
|
(p/let [position-data (utp/calc-position-data node)
|
||||||
props {:position-data position-data}
|
props {:position-data position-data}
|
||||||
|
|
||||||
props
|
props
|
||||||
(if (contains? #{:auto-height :auto-width} grow-type)
|
(if (contains? #{:auto-height :auto-width} grow-type)
|
||||||
(let [{:keys [width height]} (-> (dom/query node ".paragraph-set") (dom/get-client-size))
|
(let [{:keys [width height]} (-> (dom/query node ".paragraph-set") (dom/get-client-size))
|
||||||
width (mth/ceil width)
|
width (mth/ceil width)
|
||||||
height (mth/ceil height)]
|
height (mth/ceil height)]
|
||||||
(if (and (not (mth/almost-zero? width)) (not (mth/almost-zero? height)))
|
(if (and (not (mth/almost-zero? width)) (not (mth/almost-zero? height)))
|
||||||
(assoc props :width width :height height)
|
(assoc props :width width :height height)
|
||||||
props))
|
props))
|
||||||
props)]
|
props)]
|
||||||
|
|
||||||
(st/emit! (dwt/update-text-modifier id props))))
|
(st/emit! (dwt/update-text-modifier id props))))
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
[app.util.globals :as globals]
|
[app.util.globals :as globals]
|
||||||
[app.util.timers :as timers]
|
[app.util.timers :as timers]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
|
[debug :refer [debug?]]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[rumext.alpha :as mf])
|
[rumext.alpha :as mf])
|
||||||
(:import goog.events.EventType))
|
(:import goog.events.EventType))
|
||||||
|
@ -269,7 +270,11 @@
|
||||||
|
|
||||||
;; We only allow active frames that are contained in the vbox
|
;; We only allow active frames that are contained in the vbox
|
||||||
(filter (partial inside-vbox vbox objects)))
|
(filter (partial inside-vbox vbox objects)))
|
||||||
all-frames)]
|
all-frames)
|
||||||
|
|
||||||
|
;; Debug only: Disable the thumbnails
|
||||||
|
new-active-frames
|
||||||
|
(if (debug? :disable-frame-thumbnails) (into #{} all-frames) new-active-frames)]
|
||||||
|
|
||||||
(when (not= @active-frames new-active-frames)
|
(when (not= @active-frames new-active-frames)
|
||||||
(reset! active-frames new-active-frames)))))))
|
(reset! active-frames new-active-frames)))))))
|
||||||
|
|
|
@ -135,35 +135,36 @@
|
||||||
(on-frame-leave (:id frame))))
|
(on-frame-leave (:id frame))))
|
||||||
text-pos-x (if (:use-for-thumbnail? frame) 15 0)]
|
text-pos-x (if (:use-for-thumbnail? frame) 15 0)]
|
||||||
|
|
||||||
[:*
|
(when (not (:hidden frame))
|
||||||
(when (:use-for-thumbnail? frame)
|
[:*
|
||||||
[:g {:transform (str (when (and selected? modifiers)
|
(when (:use-for-thumbnail? frame)
|
||||||
(str (:displacement modifiers) " "))
|
[:g {:transform (str (when (and selected? modifiers)
|
||||||
(text-transform label-pos zoom))}
|
(str (:displacement modifiers) " "))
|
||||||
[:svg {:x 0
|
(text-transform label-pos zoom))}
|
||||||
:y -9
|
[:svg {:x 0
|
||||||
:width 12
|
:y -9
|
||||||
:height 12
|
:width 12
|
||||||
:class "workspace-frame-icon"
|
:height 12
|
||||||
|
:class "workspace-frame-icon"
|
||||||
|
:style {:fill (when selected? "var(--color-primary-dark)")}
|
||||||
|
:visibility (if show-artboard-names? "visible" "hidden")}
|
||||||
|
[:use {:href "#icon-set-thumbnail"}]]])
|
||||||
|
[:text {:x text-pos-x
|
||||||
|
:y 0
|
||||||
|
:width width
|
||||||
|
:height 20
|
||||||
|
:class "workspace-frame-label"
|
||||||
|
:transform (str (when (and selected? modifiers)
|
||||||
|
(str (:displacement modifiers) " "))
|
||||||
|
(text-transform label-pos zoom))
|
||||||
:style {:fill (when selected? "var(--color-primary-dark)")}
|
:style {:fill (when selected? "var(--color-primary-dark)")}
|
||||||
:visibility (if show-artboard-names? "visible" "hidden")}
|
:visibility (if show-artboard-names? "visible" "hidden")
|
||||||
[:use {:href "#icon-set-thumbnail"}]]])
|
:on-mouse-down on-mouse-down
|
||||||
[:text {:x text-pos-x
|
:on-double-click on-double-click
|
||||||
:y 0
|
:on-context-menu on-context-menu
|
||||||
:width width
|
:on-pointer-enter on-pointer-enter
|
||||||
:height 20
|
:on-pointer-leave on-pointer-leave}
|
||||||
:class "workspace-frame-label"
|
(:name frame)]])))
|
||||||
:transform (str (when (and selected? modifiers)
|
|
||||||
(str (:displacement modifiers) " "))
|
|
||||||
(text-transform label-pos zoom))
|
|
||||||
:style {:fill (when selected? "var(--color-primary-dark)")}
|
|
||||||
:visibility (if show-artboard-names? "visible" "hidden")
|
|
||||||
:on-mouse-down on-mouse-down
|
|
||||||
:on-double-click on-double-click
|
|
||||||
:on-context-menu on-context-menu
|
|
||||||
:on-pointer-enter on-pointer-enter
|
|
||||||
:on-pointer-leave on-pointer-leave}
|
|
||||||
(:name frame)]]))
|
|
||||||
|
|
||||||
(mf/defc frame-titles
|
(mf/defc frame-titles
|
||||||
{::mf/wrap-props false
|
{::mf/wrap-props false
|
||||||
|
|
|
@ -548,3 +548,11 @@
|
||||||
(seq (.-children node)))]
|
(seq (.-children node)))]
|
||||||
(->> root-node
|
(->> root-node
|
||||||
(tree-seq branch? get-children))))
|
(tree-seq branch? get-children))))
|
||||||
|
|
||||||
|
(defn check-font? [font]
|
||||||
|
(let [fonts (.-fonts globals/document)]
|
||||||
|
(.check fonts font)))
|
||||||
|
|
||||||
|
(defn load-font [font]
|
||||||
|
(let [fonts (.-fonts globals/document)]
|
||||||
|
(.load fonts font)))
|
||||||
|
|
|
@ -9,9 +9,11 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.transit :as transit]
|
[app.common.transit :as transit]
|
||||||
|
[app.main.fonts :as fonts]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.text-position-data :as tpd]))
|
[app.util.text-position-data :as tpd]
|
||||||
|
[promesa.core :as p]))
|
||||||
|
|
||||||
(defn parse-text-nodes
|
(defn parse-text-nodes
|
||||||
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
"Given a text node retrieves the rectangles for everyone of its paragraphs and its text."
|
||||||
|
@ -27,6 +29,27 @@
|
||||||
(map parse-entry)
|
(map parse-entry)
|
||||||
(tpd/parse-text-nodes parent-node text-node))))
|
(tpd/parse-text-nodes parent-node text-node))))
|
||||||
|
|
||||||
|
(def load-promises (atom {}))
|
||||||
|
|
||||||
|
(defn load-font
|
||||||
|
[font]
|
||||||
|
(if (contains? @load-promises font)
|
||||||
|
(get @load-promises font)
|
||||||
|
(let [load-promise (dom/load-font font)]
|
||||||
|
(swap! load-promises assoc font load-promise)
|
||||||
|
load-promise)))
|
||||||
|
|
||||||
|
(defn resolve-font
|
||||||
|
[^js node]
|
||||||
|
|
||||||
|
(let [styles (js/getComputedStyle node)
|
||||||
|
font (.getPropertyValue styles "font")]
|
||||||
|
(if (dom/check-font? font)
|
||||||
|
(p/resolved font)
|
||||||
|
(let [font-id (.getPropertyValue styles "--font-id")]
|
||||||
|
(-> (fonts/ensure-loaded! font-id)
|
||||||
|
(p/then #(when (not (dom/check-font? font))
|
||||||
|
(load-font font))))))))
|
||||||
|
|
||||||
(defn calc-text-node-positions
|
(defn calc-text-node-positions
|
||||||
[base-node viewport zoom]
|
[base-node viewport zoom]
|
||||||
|
@ -58,22 +81,25 @@
|
||||||
:width (- (:x p2) (:x p1))
|
:width (- (:x p2) (:x p1))
|
||||||
:height (- (:y p2) (:y p1)))))
|
:height (- (:y p2) (:y p1)))))
|
||||||
|
|
||||||
text-nodes (dom/query-all base-node ".text-node, span[data-text]")]
|
text-nodes (dom/query-all base-node ".text-node, span[data-text]")
|
||||||
|
load-fonts (->> text-nodes (map resolve-font))]
|
||||||
(->> text-nodes
|
(-> (p/all load-fonts)
|
||||||
(mapcat
|
(p/then
|
||||||
(fn [parent-node]
|
(fn []
|
||||||
(let [direction (.-direction (js/getComputedStyle parent-node))]
|
(->> text-nodes
|
||||||
(->> (.-childNodes parent-node)
|
(mapcat
|
||||||
(mapcat #(parse-text-nodes parent-node direction %))))))
|
(fn [parent-node]
|
||||||
(mapv #(update % :position translate-rect))))))
|
(let [direction (.-direction (js/getComputedStyle parent-node))]
|
||||||
|
(->> (.-childNodes parent-node)
|
||||||
|
(mapcat #(parse-text-nodes parent-node direction %))))))
|
||||||
|
(mapv #(update % :position translate-rect)))))))))
|
||||||
|
|
||||||
(defn calc-position-data
|
(defn calc-position-data
|
||||||
[base-node]
|
[base-node]
|
||||||
(let [viewport (dom/get-element "render")
|
(let [viewport (dom/get-element "render")
|
||||||
zoom (or (get-in @st/state [:workspace-local :zoom]) 1)]
|
zoom (or (get-in @st/state [:workspace-local :zoom]) 1)]
|
||||||
(when (and (some? base-node) (some? viewport))
|
(when (and (some? base-node) (some? viewport))
|
||||||
(let [text-data (calc-text-node-positions base-node viewport zoom)]
|
(p/let [text-data (calc-text-node-positions base-node viewport zoom)]
|
||||||
(when (d/not-empty? text-data)
|
(when (d/not-empty? text-data)
|
||||||
(->> text-data
|
(->> text-data
|
||||||
(mapv (fn [{:keys [node position text direction]}]
|
(mapv (fn [{:keys [node position text direction]}]
|
||||||
|
|
|
@ -125,7 +125,8 @@
|
||||||
match-criteria?
|
match-criteria?
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(and (not (:hidden shape))
|
(and (not (:hidden shape))
|
||||||
(not (:blocked shape))
|
(or (= :frame (:type shape)) ;; We return frames even if blocked
|
||||||
|
(not (:blocked shape)))
|
||||||
(or (not frame-id) (= frame-id (:frame-id shape)))
|
(or (not frame-id) (= frame-id (:frame-id shape)))
|
||||||
(case (:type shape)
|
(case (:type shape)
|
||||||
:frame include-frames?
|
:frame include-frames?
|
||||||
|
|
|
@ -64,6 +64,9 @@
|
||||||
|
|
||||||
;; Disable thumbnail cache
|
;; Disable thumbnail cache
|
||||||
:disable-thumbnail-cache
|
:disable-thumbnail-cache
|
||||||
|
|
||||||
|
;; Disable frame thumbnails
|
||||||
|
:disable-frame-thumbnails
|
||||||
})
|
})
|
||||||
|
|
||||||
;; These events are excluded when we activate the :events flag
|
;; These events are excluded when we activate the :events flag
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue