mirror of
https://github.com/penpot/penpot.git
synced 2026-09-08 13:09:22 +00:00
✨ Make deleted fonts fixer to run with more granular stragegy
Instead of running it on all the file, only run it to local library and the current page, reducing considerably the overhead of analyzing the whole file on each file load. It stills executes for page each time the page is loaded, and add some kind of local cache for not doing repeated work each time page loads is pending to be implemented in other commit.
This commit is contained in:
parent
27e311277a
commit
f32112544e
@ -42,7 +42,6 @@
|
|||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.drawing :as dwd]
|
[app.main.data.workspace.drawing :as dwd]
|
||||||
[app.main.data.workspace.edition :as dwe]
|
[app.main.data.workspace.edition :as dwe]
|
||||||
[app.main.data.workspace.fix-broken-shapes :as fbs]
|
|
||||||
[app.main.data.workspace.fix-deleted-fonts :as fdf]
|
[app.main.data.workspace.fix-deleted-fonts :as fdf]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.guides :as dwgu]
|
[app.main.data.workspace.guides :as dwgu]
|
||||||
@ -232,8 +231,7 @@
|
|||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(rx/of (dp/check-open-plugin)
|
(rx/of (dp/check-open-plugin)
|
||||||
(fdf/fix-deleted-fonts)
|
(fdf/fix-deleted-fonts-for-local-library file-id)))))
|
||||||
(fbs/fix-broken-shapes)))))
|
|
||||||
|
|
||||||
(defn- bundle-fetched
|
(defn- bundle-fetched
|
||||||
[{:keys [file file-id thumbnails] :as bundle}]
|
[{:keys [file file-id thumbnails] :as bundle}]
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
;; 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) KALEIDOS INC
|
|
||||||
|
|
||||||
(ns app.main.data.workspace.fix-broken-shapes
|
|
||||||
(:require
|
|
||||||
[app.main.data.changes :as dch]
|
|
||||||
[app.main.data.helpers :as dsh]
|
|
||||||
[beicon.v2.core :as rx]
|
|
||||||
[potok.v2.core :as ptk]))
|
|
||||||
|
|
||||||
(defn- generate-broken-link-changes
|
|
||||||
[attr {:keys [objects id] :as container}]
|
|
||||||
(let [base {:type :fix-obj :fix :broken-children attr id}
|
|
||||||
contains? (partial contains? objects)
|
|
||||||
xform (comp
|
|
||||||
;; FIXME: Ensure all obj have id field (this is needed
|
|
||||||
;; because some bug adds an ephimeral shape with id ZERO,
|
|
||||||
;; with a single attr `:shapes` having a vector of ids
|
|
||||||
;; pointing to not existing shapes). That happens on
|
|
||||||
;; components. THIS IS A WORKAOURD
|
|
||||||
(map (fn [[id obj]]
|
|
||||||
(if (some? (:id obj))
|
|
||||||
obj
|
|
||||||
(assoc obj :id id))))
|
|
||||||
|
|
||||||
;; Remove all valid shapes
|
|
||||||
(remove (fn [obj]
|
|
||||||
(every? contains? (:shapes obj))))
|
|
||||||
|
|
||||||
(map (fn [obj]
|
|
||||||
(assoc base :id (:id obj)))))]
|
|
||||||
|
|
||||||
(sequence xform objects)))
|
|
||||||
|
|
||||||
(defn fix-broken-shapes
|
|
||||||
[]
|
|
||||||
(ptk/reify ::fix-broken-shapes
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [it state _]
|
|
||||||
(let [fdata (dsh/lookup-file-data state)
|
|
||||||
changes (concat
|
|
||||||
(mapcat (partial generate-broken-link-changes :page-id)
|
|
||||||
(vals (:pages-index fdata)))
|
|
||||||
(mapcat (partial generate-broken-link-changes :component-id)
|
|
||||||
(vals (:components fdata))))]
|
|
||||||
|
|
||||||
(if (seq changes)
|
|
||||||
(rx/of (dch/commit-changes
|
|
||||||
{:origin it
|
|
||||||
:redo-changes (vec changes)
|
|
||||||
:undo-changes []
|
|
||||||
:save-undo? false}))
|
|
||||||
(rx/empty))))))
|
|
||||||
@ -14,8 +14,9 @@
|
|||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
;; This event will update the file so the texts with non existing custom fonts try to be fixed.
|
;; This event will update the file so the texts with non existing
|
||||||
;; This can happen when:
|
;; custom fonts try to be fixed. This can happen when:
|
||||||
|
;;
|
||||||
;; - Exporting/importing files to different teams or penpot instances
|
;; - Exporting/importing files to different teams or penpot instances
|
||||||
;; - Moving files from one team to another in the same instance
|
;; - Moving files from one team to another in the same instance
|
||||||
;; - Custom fonts are explicitly deleted in the team area
|
;; - Custom fonts are explicitly deleted in the team area
|
||||||
@ -23,112 +24,99 @@
|
|||||||
(defn- calculate-alternative-font-id
|
(defn- calculate-alternative-font-id
|
||||||
[value]
|
[value]
|
||||||
(let [fonts (deref fonts/fontsdb)]
|
(let [fonts (deref fonts/fontsdb)]
|
||||||
(->> (vals fonts)
|
(reduce-kv (fn [_ _ font]
|
||||||
(filter #(= (:family %) value))
|
(if (= (:family font) value)
|
||||||
(first)
|
(reduced (:id font))
|
||||||
:id)))
|
nil))
|
||||||
|
nil
|
||||||
|
fonts)))
|
||||||
|
|
||||||
(defn- has-invalid-font-family?
|
(defn- has-invalid-font-family?
|
||||||
[node]
|
[node]
|
||||||
(let [fonts (deref fonts/fontsdb)
|
(let [fonts (deref fonts/fontsdb)
|
||||||
font-family (:font-family node)
|
font-family (:font-family node)]
|
||||||
alternative-font-id (calculate-alternative-font-id font-family)]
|
|
||||||
(and (some? font-family)
|
(and (some? font-family)
|
||||||
(nil? (get fonts (:font-id node)))
|
(nil? (get fonts (:font-id node))))))
|
||||||
(some? alternative-font-id))))
|
|
||||||
|
|
||||||
(defn- should-fix-deleted-font-shape?
|
(defn- shape-has-invalid-font-family??
|
||||||
[shape]
|
[shape]
|
||||||
(let [text-nodes (txt/node-seq txt/is-text-node? (:content shape))]
|
(and (cfh/text-shape? shape)
|
||||||
(and (cfh/text-shape? shape)
|
(some has-invalid-font-family?
|
||||||
(some has-invalid-font-family? text-nodes))))
|
(txt/node-seq txt/is-text-node? (:content shape)))))
|
||||||
|
|
||||||
(defn- should-fix-deleted-font-component?
|
|
||||||
[component]
|
|
||||||
(let [xf (comp (map val)
|
|
||||||
(filter should-fix-deleted-font-shape?))]
|
|
||||||
(first (sequence xf (:objects component)))))
|
|
||||||
|
|
||||||
(defn- fix-deleted-font
|
(defn- fix-deleted-font
|
||||||
[node]
|
[node]
|
||||||
(let [alternative-font-id (calculate-alternative-font-id (:font-family node))]
|
(if-let [alternative-font-id (calculate-alternative-font-id (:font-family node))]
|
||||||
(cond-> node
|
(assoc node :font-id alternative-font-id)
|
||||||
(some? alternative-font-id) (assoc :font-id alternative-font-id))))
|
node))
|
||||||
|
|
||||||
(defn- fix-deleted-font-shape
|
(defn- fix-shape-content
|
||||||
[shape]
|
[shape]
|
||||||
(let [transform (partial txt/transform-nodes has-invalid-font-family? fix-deleted-font)]
|
(txt/transform-nodes has-invalid-font-family? fix-deleted-font
|
||||||
(update shape :content transform)))
|
(:content shape)))
|
||||||
|
|
||||||
(defn- fix-deleted-font-component
|
(defn- fix-typography
|
||||||
[component]
|
|
||||||
(update component
|
|
||||||
:objects
|
|
||||||
(fn [objects]
|
|
||||||
(update-vals objects fix-deleted-font-shape))))
|
|
||||||
|
|
||||||
(defn fix-deleted-font-typography
|
|
||||||
[typography]
|
[typography]
|
||||||
(let [alternative-font-id (calculate-alternative-font-id (:font-family typography))]
|
(if-let [alternative-font-id (calculate-alternative-font-id (:font-family typography))]
|
||||||
(cond-> typography
|
(assoc typography :font-id alternative-font-id)
|
||||||
(some? alternative-font-id) (assoc :font-id alternative-font-id))))
|
typography))
|
||||||
|
|
||||||
(defn- generate-deleted-font-shape-changes
|
(defn- generate-page-changes
|
||||||
[{:keys [objects id]}]
|
[{:keys [objects id]}]
|
||||||
(sequence
|
(reduce-kv (fn [changes shape-id shape]
|
||||||
(comp (map val)
|
(if (shape-has-invalid-font-family?? shape)
|
||||||
(filter should-fix-deleted-font-shape?)
|
(conj changes {:type :mod-obj
|
||||||
(map (fn [shape]
|
:id shape-id
|
||||||
{:type :mod-obj
|
:page-id id
|
||||||
:id (:id shape)
|
:operations [{:type :set
|
||||||
:page-id id
|
:attr :content
|
||||||
:operations [{:type :set
|
:val (fix-shape-content shape)}
|
||||||
:attr :content
|
{:type :set
|
||||||
:val (:content (fix-deleted-font-shape shape))}
|
:attr :position-data
|
||||||
{:type :set
|
:val nil}]})
|
||||||
:attr :position-data
|
changes))
|
||||||
:val nil}]})))
|
[]
|
||||||
objects))
|
objects))
|
||||||
|
|
||||||
(defn- generate-deleted-font-components-changes
|
(defn- generate-library-changes
|
||||||
[fdata]
|
[fdata]
|
||||||
(sequence
|
(reduce-kv (fn [changes _ typography]
|
||||||
(comp (map val)
|
(if (has-invalid-font-family? typography)
|
||||||
(filter should-fix-deleted-font-component?)
|
(conj changes {:type :mod-typography
|
||||||
(map (fn [component]
|
:typography (fix-typography typography)})
|
||||||
{:type :mod-component
|
changes))
|
||||||
:id (:id component)
|
[]
|
||||||
:objects (-> (fix-deleted-font-component component) :objects)})))
|
(:typographies fdata)))
|
||||||
(:components fdata)))
|
|
||||||
|
|
||||||
(defn- generate-deleted-font-typography-changes
|
(defn fix-deleted-fonts-for-local-library
|
||||||
[fdata]
|
"Looks the file local library for deleted fonts and emit changes if
|
||||||
(sequence
|
invalid but fixable typographyes found."
|
||||||
(comp (map val)
|
[file-id]
|
||||||
(filter has-invalid-font-family?)
|
(ptk/reify ::fix-deleted-fonts-for-local-library
|
||||||
(map (fn [typography]
|
|
||||||
{:type :mod-typography
|
|
||||||
:typography (fix-deleted-font-typography typography)})))
|
|
||||||
(:typographies fdata)))
|
|
||||||
|
|
||||||
(defn fix-deleted-fonts
|
|
||||||
[]
|
|
||||||
(ptk/reify ::fix-deleted-fonts
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [fdata (dsh/lookup-file-data state)
|
(let [fdata (dsh/lookup-file-data state file-id)]
|
||||||
pages (:pages-index fdata)
|
(when-let [changes (-> (generate-library-changes fdata)
|
||||||
|
(not-empty))]
|
||||||
shape-changes (mapcat generate-deleted-font-shape-changes (vals pages))
|
|
||||||
components-changes (generate-deleted-font-components-changes fdata)
|
|
||||||
typography-changes (generate-deleted-font-typography-changes fdata)
|
|
||||||
changes (concat shape-changes
|
|
||||||
components-changes
|
|
||||||
typography-changes)]
|
|
||||||
(if (seq changes)
|
|
||||||
(rx/of (dwc/commit-changes
|
(rx/of (dwc/commit-changes
|
||||||
{:origin it
|
{:origin it
|
||||||
:redo-changes (vec changes)
|
:redo-changes changes
|
||||||
:undo-changes []
|
:undo-changes []
|
||||||
:save-undo? false}))
|
:save-undo? false})))))))
|
||||||
(rx/empty))))))
|
|
||||||
|
;; FIXME: would be nice to not execute this code twice per page in the
|
||||||
|
;; same working session, maybe some local memoization can improve that
|
||||||
|
|
||||||
|
(defn fix-deleted-fonts-for-page
|
||||||
|
[file-id page-id]
|
||||||
|
(ptk/reify ::fix-deleted-fonts-for-page
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [it state _]
|
||||||
|
(let [page (dsh/lookup-page state file-id page-id)]
|
||||||
|
(when-let [changes (-> (generate-page-changes page)
|
||||||
|
(not-empty))]
|
||||||
|
(rx/of (dwc/commit-changes
|
||||||
|
{:origin it
|
||||||
|
:redo-changes changes
|
||||||
|
:undo-changes []
|
||||||
|
:save-undo? false})))))))
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.persistence :as-alias dps]
|
[app.main.data.persistence :as-alias dps]
|
||||||
[app.main.data.workspace.drawing :as dwd]
|
[app.main.data.workspace.drawing :as dwd]
|
||||||
|
[app.main.data.workspace.fix-deleted-fonts :as fdf]
|
||||||
[app.main.data.workspace.layout :as layout]
|
[app.main.data.workspace.layout :as layout]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.data.workspace.thumbnails :as dwth]
|
[app.main.data.workspace.thumbnails :as dwth]
|
||||||
@ -104,6 +105,7 @@
|
|||||||
(if (dsh/lookup-page state file-id page-id)
|
(if (dsh/lookup-page state file-id page-id)
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (initialize-page* file-id page-id)
|
(rx/of (initialize-page* file-id page-id)
|
||||||
|
(fdf/fix-deleted-fonts-for-page file-id page-id)
|
||||||
(dwth/watch-state-changes file-id page-id)
|
(dwth/watch-state-changes file-id page-id)
|
||||||
(dwl/watch-component-changes))
|
(dwl/watch-component-changes))
|
||||||
(let [profile (:profile state)
|
(let [profile (:profile state)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user