diff --git a/CHANGES.md b/CHANGES.md
index 8a7df1fc1..ca672dae1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -39,11 +39,12 @@
### :sparkles: New features
- Viewer role for team members [Taiga #1056 & #6590](https://tree.taiga.io/project/penpot/us/1056 & https://tree.taiga.io/project/penpot/us/6590)
-- File history versions management [Taiga](https://tree.taiga.io/project/penpot/us/187?milestone=411120)
+- File history versions management [Taiga #187](https://tree.taiga.io/project/penpot/us/187?milestone=411120)
- Rename selected layer via keyboard shortcut and context menu option [Taiga #8882](https://tree.taiga.io/project/penpot/us/8882)
### :bug: Bugs fixed
+- Fix problem with some texts desynchronization [Taiga #9379](https://tree.taiga.io/project/penpot/issue/9379)
## 2.3.3
diff --git a/backend/src/app/rpc/commands/files_thumbnails.clj b/backend/src/app/rpc/commands/files_thumbnails.clj
index 92c8d16b0..eb7bf3c16 100644
--- a/backend/src/app/rpc/commands/files_thumbnails.clj
+++ b/backend/src/app/rpc/commands/files_thumbnails.clj
@@ -50,8 +50,7 @@
" where file_id=? and tag=? and deleted_at is null")
res (db/exec! conn [sql file-id tag])]
(->> res
- (d/index-by :object-id (fn [row]
- (files/resolve-public-uri (:media-id row))))
+ (d/index-by :object-id :media-id)
(d/without-nils))))
(defn- get-object-thumbnails
@@ -62,8 +61,7 @@
" where file_id=? and deleted_at is null")
res (db/exec! conn [sql file-id])]
(->> res
- (d/index-by :object-id (fn [row]
- (files/resolve-public-uri (:media-id row))))
+ (d/index-by :object-id :media-id)
(d/without-nils))))
([conn file-id object-ids]
@@ -75,8 +73,7 @@
res (db/exec! conn [sql file-id ids])]
(->> res
- (d/index-by :object-id (fn [row]
- (files/resolve-public-uri (:media-id row))))
+ (d/index-by :object-id :media-id)
(d/without-nils)))))
(sv/defmethod ::get-file-object-thumbnails
@@ -127,8 +124,11 @@
(if-let [frame (-> frames first)]
(let [frame-id (:id frame)
object-id (thc/fmt-object-id (:id file) page-id frame-id "frame")
- frame (if-let [thumb (get thumbnails object-id)]
- (assoc frame :thumbnail thumb :shapes [])
+
+ frame (if-let [media-id (get thumbnails object-id)]
+ (-> frame
+ (assoc :thumbnail-id media-id)
+ (assoc :shapes []))
(dissoc frame :thumbnail))
children-ids
diff --git a/backend/test/backend_tests/rpc_file_test.clj b/backend/test/backend_tests/rpc_file_test.clj
index d6678be29..679d5221e 100644
--- a/backend/test/backend_tests/rpc_file_test.clj
+++ b/backend/test/backend_tests/rpc_file_test.clj
@@ -1090,8 +1090,7 @@
(t/is (contains? result :file-id))
(t/is (= (:id file) (:file-id result)))
- (t/is (str/starts-with? (get-in result [:page :objects frame1-id :thumbnail])
- "http://localhost:3449/assets/by-id/"))
+ (t/is (uuid? (get-in result [:page :objects frame1-id :thumbnail-id])))
(t/is (= [] (get-in result [:page :objects frame1-id :shapes]))))
;; Delete thumbnail data
diff --git a/frontend/playwright/ui/specs/versions.spec.js b/frontend/playwright/ui/specs/versions.spec.js
index 40fac7d22..f99ae148c 100644
--- a/frontend/playwright/ui/specs/versions.spec.js
+++ b/frontend/playwright/ui/specs/versions.spec.js
@@ -58,10 +58,11 @@ test("Save and restore version", async ({ page }) => {
await page.getByRole("textbox").press("Enter");
await page
- .locator("li")
- .filter({ hasText: "INIT" })
- .getByRole("button")
- .click();
+ .getByLabel("History", { exact: true })
+ .locator("div")
+ .nth(3)
+ .hover();
+ await page.getByRole("button", { name: "Open version menu" }).click();
await page.getByRole("button", { name: "Restore" }).click();
await workspacePage.mockRPC(
diff --git a/frontend/scripts/_helpers.js b/frontend/scripts/_helpers.js
index 95dce0ac3..c7671a361 100644
--- a/frontend/scripts/_helpers.js
+++ b/frontend/scripts/_helpers.js
@@ -237,13 +237,18 @@ async function renderTemplate(path, context = {}, partials = {}) {
return mustache.render(content, context, partials);
}
-const renderer = {
- link(href, title, text) {
- return `${text}`;
+const extension = {
+ useNewRenderer: true,
+ renderer: {
+ link(token) {
+ const href = token.href;
+ const text = token.text;
+ return `${text}`;
+ },
},
};
-marked.use({ renderer });
+marked.use(extension);
async function readTranslations() {
const langs = [
diff --git a/frontend/src/app/main/data/common.cljs b/frontend/src/app/main/data/common.cljs
index 576e6c656..ac83b6bea 100644
--- a/frontend/src/app/main/data/common.cljs
+++ b/frontend/src/app/main/data/common.cljs
@@ -12,7 +12,6 @@
[app.common.schema :as sm]
[app.common.types.components-list :as ctkl]
[app.common.types.team :as ctt]
- [app.config :as cf]
[app.main.data.modal :as modal]
[app.main.data.notifications :as ntf]
[app.main.features :as features]
@@ -75,15 +74,13 @@
(watch [_ _ _]
(case code
:upgrade-version
- (when (or (not= (:version params) (:full cf/version))
- (true? (:force params)))
- (rx/of (ntf/dialog
- :content (tr "notifications.by-code.upgrade-version")
- :controls :inline-actions
- :type :inline
- :level level
- :actions [{:label "Refresh" :callback force-reload!}]
- :tag :notification)))
+ (rx/of (ntf/dialog
+ :content (tr "notifications.by-code.upgrade-version")
+ :controls :inline-actions
+ :type :inline
+ :level level
+ :actions [{:label "Refresh" :callback force-reload!}]
+ :tag :notification))
:maintenance
(rx/of (ntf/dialog
diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs
index f309e7ea5..80f1fff92 100644
--- a/frontend/src/app/main/data/workspace.cljs
+++ b/frontend/src/app/main/data/workspace.cljs
@@ -199,18 +199,21 @@
;; Load libraries
(->> (rp/cmd! :get-file-libraries {:file-id file-id})
- (rx/mapcat identity)
- (rx/merge-map
- (fn [{:keys [id synced-at]}]
- (->> (rp/cmd! :get-file {:id id :features features})
- (rx/map #(assoc % :synced-at synced-at)))))
- (rx/merge-map fpmap/resolve-file)
- (rx/merge-map
- (fn [{:keys [id] :as file}]
- (->> (rp/cmd! :get-file-object-thumbnails {:file-id id :tag "component"})
- (rx/map #(assoc file :thumbnails %)))))
- (rx/reduce conj [])
- (rx/map libraries-fetched)))
+ (rx/mapcat (fn [libraries]
+ (rx/merge
+ (->> (rx/from libraries)
+ (rx/merge-map
+ (fn [{:keys [id synced-at]}]
+ (->> (rp/cmd! :get-file {:id id :features features})
+ (rx/map #(assoc % :synced-at synced-at)))))
+ (rx/merge-map fpmap/resolve-file)
+ (rx/reduce conj [])
+ (rx/map libraries-fetched))
+ (->> (rx/from libraries)
+ (rx/map :id)
+ (rx/mapcat (fn [file-id]
+ (rp/cmd! :get-file-object-thumbnails {:file-id file-id :tag "component"})))
+ (rx/map dwl/library-thumbnails-fetched)))))))
(rx/of (with-meta (workspace-initialized)
{:file-id file-id})))
diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs
index e04b4dfb2..5f4c56aa9 100644
--- a/frontend/src/app/main/data/workspace/libraries.cljs
+++ b/frontend/src/app/main/data/workspace/libraries.cljs
@@ -881,11 +881,9 @@
(rx/of
(dwu/start-undo-transaction undo-id)
(update-component shape-id undo-group)
- (sync-file current-file-id file-id :components (:component-id shape) undo-group)
- (update-component-thumbnail-sync state component-id file-id "frame")
- (update-component-thumbnail-sync state component-id file-id "component")
+ (sync-file current-file-id file-id :components component-id undo-group)
(when (not current-file?)
- (sync-file file-id file-id :components (:component-id shape) undo-group))
+ (sync-file file-id file-id :components component-id undo-group))
(dwu/commit-undo-transaction undo-id)))))))
(defn launch-component-sync
@@ -937,9 +935,9 @@
;; in the grid creating new rows/columns to make space
(let [file (wsh/get-file state file-id)
libraries (wsh/get-libraries state)
- page (wsh/lookup-page state)
- objects (wsh/lookup-page-objects state)
- parent (get objects (:parent-id shape))
+ page (wsh/lookup-page state)
+ objects (wsh/lookup-page-objects state)
+ parent (get objects (:parent-id shape))
;; If the target parent is a grid layout we need to pass the target cell
target-cell (when (ctl/grid-layout? parent)
diff --git a/frontend/src/app/main/data/workspace/thumbnails.cljs b/frontend/src/app/main/data/workspace/thumbnails.cljs
index a043c3811..0d2ef2239 100644
--- a/frontend/src/app/main/data/workspace/thumbnails.cljs
+++ b/frontend/src/app/main/data/workspace/thumbnails.cljs
@@ -168,7 +168,7 @@
(.error js/console cause)
(rx/empty)))
- (rx/tap #(l/trc :hint "thumbnail updated" :elapsed (dm/str (tp) "ms")))
+ (rx/tap #(l/dbg :hint "thumbnail updated" :elapsed (dm/str (tp) "ms")))
;; We cancel all the stream if user starts editing while
;; thumbnail is generating
diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs
index f8ad9fd07..4ac723f5c 100644
--- a/frontend/src/app/main/refs.cljs
+++ b/frontend/src/app/main/refs.cljs
@@ -13,6 +13,7 @@
[app.common.types.shape-tree :as ctt]
[app.common.types.shape.layout :as ctl]
[app.common.types.tokens-lib :as ctob]
+ [app.config :as cf]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.store :as st]
[app.main.ui.workspace.tokens.token-set :as wtts]
@@ -588,7 +589,8 @@
[object-id]
(l/derived
(fn [state]
- (dm/get-in state [:workspace-thumbnails object-id]))
+ (some-> (dm/get-in state [:workspace-thumbnails object-id])
+ (cf/resolve-media)))
st/state))
(def workspace-text-modifier
diff --git a/frontend/src/app/main/ui/shapes/frame.cljs b/frontend/src/app/main/ui/shapes/frame.cljs
index 3befcda74..b644b8def 100644
--- a/frontend/src/app/main/ui/shapes/frame.cljs
+++ b/frontend/src/app/main/ui/shapes/frame.cljs
@@ -135,7 +135,7 @@
bounds (mf/with-memo [bounds points]
(or bounds (gsb/get-frame-bounds shape)))
- thumb (:thumbnail shape)
+ thumb (cf/resolve-media (:thumbnail-id shape))
debug? (dbg/enabled? :thumbnails)
safari? (cf/check-browser? :safari)
@@ -171,7 +171,7 @@
{::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")]
- (when ^boolean (:thumbnail shape)
+ (when ^boolean (:thumbnail-id shape)
[:> frame-container props
[:> frame-thumbnail-image props]])))
diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs
index a65daafc6..67c3a0356 100644
--- a/frontend/src/app/main/ui/shapes/text/styles.cljs
+++ b/frontend/src/app/main/ui/shapes/text/styles.cljs
@@ -49,11 +49,16 @@
(defn generate-paragraph-styles
[_shape data]
- (let [line-height (:line-height data 1.2)
+ (let [line-height (:line-height data)
+ line-height
+ (if (and (some? line-height) (not= "" line-height))
+ line-height
+ (:line-height txt/default-text-attrs))
+
text-align (:text-align data "start")
base #js {;; Fix a problem when exporting HTML
:fontSize 0 ;;(str (:font-size data (:font-size txt/default-text-attrs)) "px")
- :lineHeight (:line-height data (:line-height txt/default-text-attrs))
+ :lineHeight line-height
:margin 0}]
(cond-> base
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
index 578d08af2..b8bf2959f 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs
@@ -269,17 +269,19 @@
(mf/defc component-item-thumbnail
"Component that renders the thumbnail image or the original SVG."
- {::mf/wrap-props false}
+ {::mf/props :obj}
[{:keys [file-id root-shape component container class]}]
- (let [page-id (:main-instance-page component)
- root-id (:main-instance-id component)
+ (let [page-id (:main-instance-page component)
+ root-id (:main-instance-id component)
+ retry (mf/use-state 0)
- retry (mf/use-state 0)
+ thumbnail-uri*
+ (mf/with-memo [file-id page-id root-id]
+ (let [object-id (thc/fmt-object-id file-id page-id root-id "component")]
+ (refs/workspace-thumbnail-by-id object-id)))
- thumbnail-uri* (mf/with-memo [file-id page-id root-id]
- (let [object-id (thc/fmt-object-id file-id page-id root-id "component")]
- (refs/workspace-thumbnail-by-id object-id)))
- thumbnail-uri (mf/deref thumbnail-uri*)
+ thumbnail-uri
+ (mf/deref thumbnail-uri*)
on-error
(mf/use-fn
diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
index 72a472841..8efffa844 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs
@@ -57,15 +57,6 @@
component)]
[root-shape container])))
-
- ;; NOTE: We don't schedule the thumbnail generation on idle right now
- ;; until we can queue and handle thumbnail batching properly.
-#_(mf/with-effect []
- (when-not (some? thumbnail-uri)
- (tm/schedule-on-idle
- #(st/emit! (dwl/update-component-thumbnail (:id component) file-id)))))
-
-
(mf/defc components-item
{::mf/wrap-props false}
[{:keys [component renaming listing-thumbs? selected
diff --git a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs
index 31ec42c84..b96e99924 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs
@@ -134,7 +134,8 @@
time (dt/timeago (:created-at entry) {:locale locale})]
[:span {:class (stl/css :date)} time])]]
- [:> icon-button* {:variant "ghost"
+ [:> icon-button* {:class (stl/css :version-entry-options)
+ :variant "ghost"
:aria-label (tr "workspace.versions.version-menu")
:on-click handle-open-menu
:icon "menu"}]]