diff --git a/CHANGES.md b/CHANGES.md
index e475213f0..7374f17af 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -58,6 +58,10 @@
- Fix ungroup does not work for typographies [Taiga #4195](https://tree.taiga.io/project/penpot/issue/4195)
- Fix inviting to non existing users can fail [Taiga #4108](https://tree.taiga.io/project/penpot/issue/4108)
- Fix components marked as touched when moved [Taiga #4061](https://tree.taiga.io/project/penpot/task/4061)
+- Fix boards grouped shouldn't show the title [Taiga #4251](https://tree.taiga.io/project/penpot/issue/4251)
+- Fix gradient handlers are under resize handlers[Taiga #4298](https://tree.taiga.io/project/penpot/issue/4298)
+- Fix grid not syncing immediately in multiuser [Taiga #4339](https://tree.taiga.io/project/penpot/issue/4339)
+- Fix custom font upload fails silently for unsupported formats [Taiga #4279](https://tree.taiga.io/project/penpot/issue/4280)
### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!)
@@ -72,6 +76,8 @@
- Fix artboard border radius [Taiga #4291](https://tree.taiga.io/project/penpot/issue/4291)
- Fix copied & pasted layer is not visible [Taiga #4283](https://tree.taiga.io/project/penpot/issue/4283)
+- Fix notification to newsletter is shown in all cases [Taiga #4367](https://tree.taiga.io/project/penpot/issue/4367)
+- Fix comments section is not scrolling by mouse wheel [Taiga #4305](https://tree.taiga.io/project/penpot/issue/4305)
## 1.15.4-beta
diff --git a/backend/src/app/rpc/commands/binfile.clj b/backend/src/app/rpc/commands/binfile.clj
index 013beac9f..8144b7464 100644
--- a/backend/src/app/rpc/commands/binfile.clj
+++ b/backend/src/app/rpc/commands/binfile.clj
@@ -634,7 +634,7 @@
params {:id file-id'
:project-id project-id
- :name (str "Imported: " (:name file))
+ :name (:name file)
:revn (:revn file)
:is-shared (:is-shared file)
:data (blob/encode data)
diff --git a/frontend/resources/images/icons/actions.svg b/frontend/resources/images/icons/actions.svg
index 7e71052a5..30eedf85b 100644
--- a/frontend/resources/images/icons/actions.svg
+++ b/frontend/resources/images/icons/actions.svg
@@ -1 +1,3 @@
-
\ No newline at end of file
+
diff --git a/frontend/resources/styles/main/partials/dashboard-grid.scss b/frontend/resources/styles/main/partials/dashboard-grid.scss
index 64341c9bb..367531338 100644
--- a/frontend/resources/styles/main/partials/dashboard-grid.scss
+++ b/frontend/resources/styles/main/partials/dashboard-grid.scss
@@ -43,6 +43,13 @@
text-align: initial;
}
+ &.dragged {
+ border-radius: $br-small;
+ border: 2px solid lighten($color-gray-20, 15%);
+ text-align: initial;
+ max-height: 160px;
+ }
+
&.placeholder {
min-width: 115px;
max-width: 115px;
@@ -127,6 +134,9 @@
width: 100%;
white-space: nowrap;
max-width: 260px;
+ &::first-letter {
+ text-transform: capitalize;
+ }
@media #{$bp-max-1366} {
max-width: 230px;
}
diff --git a/frontend/resources/styles/main/partials/viewer.scss b/frontend/resources/styles/main/partials/viewer.scss
index 784141c4b..97d6c77d0 100644
--- a/frontend/resources/styles/main/partials/viewer.scss
+++ b/frontend/resources/styles/main/partials/viewer.scss
@@ -25,6 +25,12 @@
}
}
+.viewer-loader {
+ svg#loader-pencil {
+ fill: $color-gray-50;
+ }
+}
+
.viewer-section {
height: calc(100vh - 48px);
grid-row: 1 / span 2;
diff --git a/frontend/src/app/main/data/fonts.cljs b/frontend/src/app/main/data/fonts.cljs
index c46cc6577..b9ac00443 100644
--- a/frontend/src/app/main/data/fonts.cljs
+++ b/frontend/src/app/main/data/fonts.cljs
@@ -12,8 +12,11 @@
[app.common.media :as cm]
[app.common.spec :as us]
[app.common.uuid :as uuid]
+ [app.main.data.messages :as dm]
[app.main.fonts :as fonts]
[app.main.repo :as rp]
+ [app.main.store :as st]
+ [app.util.i18n :refer [tr]]
[app.util.storage :refer [storage]]
[app.util.webapi :as wa]
[beicon.core :as rx]
@@ -133,17 +136,35 @@
{:data data
:name (.-name blob)
:type (parse-mtype data)}))
- (rx/mapcat (fn [{:keys [type] :as font}]
- (if type
+ (rx/catch (fn []
+ (rx/of {:error (.-name blob)})))
+ (rx/mapcat (fn [{:keys [type, error] :as font}]
+ (if (or type error)
(rx/of font)
(rx/empty))))))]
- (->> (rx/from blobs)
- (rx/mapcat read-blob)
- (rx/map parse-font)
- (rx/filter some?)
- (rx/map prepare)
- (rx/reduce join {}))))
+ (let [fonts (->> (rx/from blobs)
+ (rx/mapcat read-blob))
+ errors (->> fonts
+ (rx/filter #(some? (:error %)))
+ (rx/reduce (fn [acc font]
+ (conj acc (str "'" (:error font) "'")))
+ []))]
+
+ (rx/subscribe errors
+ #(when
+ (not-empty %)
+ (st/emit!
+ (dm/error
+ (if (> (count %) 1)
+ (tr "errors.bad-font-plural" (str/join ", " %))
+ (tr "errors.bad-font" (first %)))))))
+ (->> fonts
+ (rx/filter #(nil? (:error %)))
+ (rx/map parse-font)
+ (rx/filter some?)
+ (rx/map prepare)
+ (rx/reduce join {})))))
(defn- calculate-family-to-id-mapping
[existing]
diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs
index 46617ec06..7ecf800c8 100644
--- a/frontend/src/app/main/data/workspace/path/edition.cljs
+++ b/frontend/src/app/main/data/workspace/path/edition.cljs
@@ -204,7 +204,8 @@
(watch [_ state stream]
(let [id (get-in state [:workspace-local :edition])
current-move (get-in state [:workspace-local :edit-path id :current-move])]
- (if (= same-event current-move)
+ ;; id can be null if we just selected the tool but we didn't start drawing
+ (if (and id (= same-event current-move))
(let [points (get-in state [:workspace-local :edit-path id :selected-points] #{})
move-events (->> stream
diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs
index 421a5dba2..f5b2ec567 100644
--- a/frontend/src/app/main/data/workspace/persistence.cljs
+++ b/frontend/src/app/main/data/workspace/persistence.cljs
@@ -12,6 +12,7 @@
[app.common.pages.changes-spec :as pcs]
[app.common.spec :as us]
[app.common.types.file :as ctf]
+ [app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.main.data.dashboard :as dd]
@@ -219,14 +220,23 @@
(ptk/reify ::changes-persisted
ptk/UpdateEvent
(update [_ state]
- (if (= file-id (:current-file-id state))
- (-> state
- (update-in [:workspace-file :revn] max revn)
- (update :workspace-data cp/process-changes changes))
- (-> state
- (update-in [:workspace-libraries file-id :revn] max revn)
- (update-in [:workspace-libraries file-id :data]
- cp/process-changes changes))))))
+ (let [changes (group-by :page-id changes)]
+ (if (= file-id (:current-file-id state))
+ (-> state
+ (update-in [:workspace-file :revn] max revn)
+ (update :workspace-data (fn [file]
+ (loop [fdata file
+ entries (seq changes)]
+ (if-let [[page-id changes] (first entries)]
+ (recur (-> fdata
+ (cp/process-changes changes)
+ (ctst/update-object-indices page-id))
+ (rest entries))
+ fdata)))))
+ (-> state
+ (update-in [:workspace-libraries file-id :revn] max revn)
+ (update-in [:workspace-libraries file-id :data]
+ cp/process-changes changes)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs
index 286224208..80e05287b 100644
--- a/frontend/src/app/main/ui/dashboard/fonts.cljs
+++ b/frontend/src/app/main/ui/dashboard/fonts.cljs
@@ -303,8 +303,7 @@
[:div.table-field.search-input
[:input {:placeholder (tr "labels.search-font")
:default-value ""
- :on-change on-change
- }]]]
+ :on-change on-change}]]]
(cond
(seq fonts)
diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs
index 83df57226..0a5c23994 100644
--- a/frontend/src/app/main/ui/dashboard/grid.cljs
+++ b/frontend/src/app/main/ui/dashboard/grid.cljs
@@ -163,7 +163,7 @@
(let [locale (mf/deref i18n/locale)
time (dt/timeago modified-at {:locale locale})]
[:span.date
- (str (tr "ds.updated-at" time))]))
+ time]))
(defn create-counter-element
[_element file-count]
@@ -390,12 +390,13 @@
(mf/defc line-grid-row
[{:keys [files selected-files dragging? limit] :as props}]
- (let [limit (if dragging? (dec limit) limit)]
+ (let [elements limit
+ limit (if dragging? (dec limit) limit)]
[:div.grid-row.no-wrap
- {:style {:grid-template-columns (dm/str "repeat(" limit ", 1fr)")}}
+ {:style {:grid-template-columns (dm/str "repeat(" elements ", 1fr)")}}
(when dragging?
- [:div.grid-item])
+ [:div.grid-item.dragged])
(for [item (take limit files)]
[:& grid-item
{:id (:id item)
diff --git a/frontend/src/app/main/ui/onboarding/newsletter.cljs b/frontend/src/app/main/ui/onboarding/newsletter.cljs
index 358ab0783..27dd432ae 100644
--- a/frontend/src/app/main/ui/onboarding/newsletter.cljs
+++ b/frontend/src/app/main/ui/onboarding/newsletter.cljs
@@ -30,9 +30,10 @@
(mf/use-callback
(mf/deps @newsletter-updates @newsletter-news)
(fn []
- (st/emit! (dm/success message)
- (modal/show {:type :onboarding-team})
- (du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))]
+ (st/emit! (when (or @newsletter-updates @newsletter-news)
+ (dm/success message))
+ (modal/show {:type :onboarding-team})
+ (du/update-profile-props {:newsletter-updates @newsletter-updates :newsletter-news @newsletter-news}))))]
[:div.modal-overlay
[:div.modal-container.onboarding.newsletter.animated.fadeInDown
diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs
index 99762cf73..ce5eb322a 100644
--- a/frontend/src/app/main/ui/viewer.cljs
+++ b/frontend/src/app/main/ui/viewer.cljs
@@ -534,9 +534,11 @@
(fn []
(st/emit! (dv/finalize props)))))
- (when-let [data (mf/deref refs/viewer-data)]
+ (if-let [data (mf/deref refs/viewer-data)]
(let [key (str (get-in data [:file :id]))]
- [:& viewer {:params props :data data :key key}])))
+ [:& viewer {:params props :data data :key key}])
+ [:div.loader-content.viewer-loader
+ i/loader-pencil]))
(mf/defc breaking-change-notice
[]
diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs
index 46ad6bdb9..2d2be20f9 100644
--- a/frontend/src/app/main/ui/workspace/viewport.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport.cljs
@@ -96,7 +96,6 @@
;; REFS
viewport-ref (mf/use-ref nil)
- overlays-ref (mf/use-ref nil)
;; VARS
disable-paste (mf/use-var false)
@@ -184,7 +183,7 @@
disabled-guides? (or drawing-tool transform)]
- (hooks/setup-dom-events viewport-ref overlays-ref zoom disable-paste in-viewport?)
+ (hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
(hooks/setup-viewport-size viewport-ref)
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing?)
(hooks/setup-keyboard alt? mod? space?)
@@ -194,7 +193,7 @@
(hooks/setup-active-frames base-objects hover-ids selected active-frames zoom transform vbox)
[:div.viewport
- [:div.viewport-overlays {:ref overlays-ref}
+ [:div.viewport-overlays
;; The behaviour inside a foreign object is a bit different that in plain HTML so we wrap
;; inside a foreign object "dummy" so this awkward behaviour is take into account
[:svg {:style {:top 0 :left 0 :position "fixed" :width "100%" :height "100%" :opacity 0}}
@@ -337,11 +336,6 @@
:on-frame-leave on-frame-leave
:on-frame-select on-frame-select}])
- (when show-gradient-handlers?
- [:& gradients/gradient-handlers
- {:id (first selected)
- :zoom zoom}])
-
(when show-draw-area?
[:& drawarea/draw-area
{:shape drawing-obj
@@ -441,4 +435,9 @@
:zoom zoom
:objects objects-modified
:current-transform transform
- :hover-disabled? hover-disabled?}])])]]]))
+ :hover-disabled? hover-disabled?}])])
+
+ (when show-gradient-handlers?
+ [:& gradients/gradient-handlers
+ {:id (first selected)
+ :zoom zoom}])]]]))
diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs
index f0a5658cd..bbf0c740b 100644
--- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs
@@ -359,18 +359,16 @@
pt (utils/translate-point-to-viewport viewport zoom raw-pt)]
(rx/push! move-stream pt)))))
-(defn on-mouse-wheel [viewport-ref overlays-ref zoom]
+(defn on-mouse-wheel [viewport-ref zoom]
(mf/use-callback
(mf/deps zoom)
(fn [event]
(let [viewport (mf/ref-val viewport-ref)
- overlays (mf/ref-val overlays-ref)
event (.getBrowserEvent ^js event)
target (dom/get-target event)
mod? (kbd/mod? event)]
- (when (or (dom/is-child? viewport target)
- (dom/is-child? overlays target))
+ (when (dom/is-child? viewport target)
(dom/prevent-default event)
(dom/stop-propagation event)
(let [pt (->> (dom/get-client-position event)
diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs
index 4d28abb2a..c9071afc8 100644
--- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs
@@ -31,11 +31,11 @@
[rumext.v2 :as mf])
(:import goog.events.EventType))
-(defn setup-dom-events [viewport-ref overlays-ref zoom disable-paste in-viewport?]
+(defn setup-dom-events [viewport-ref zoom disable-paste in-viewport?]
(let [on-key-down (actions/on-key-down)
on-key-up (actions/on-key-up)
on-mouse-move (actions/on-mouse-move viewport-ref zoom)
- on-mouse-wheel (actions/on-mouse-wheel viewport-ref overlays-ref zoom)
+ on-mouse-wheel (actions/on-mouse-wheel viewport-ref zoom)
on-paste (actions/on-paste disable-paste in-viewport?)]
(mf/use-layout-effect
(mf/deps on-key-down on-key-up on-mouse-move on-mouse-wheel on-paste)
diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
index 9b0447b0a..1d85295f6 100644
--- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs
@@ -167,7 +167,7 @@
[:g.frame-titles
(for [frame frames]
- (when (= (:frame-id frame) uuid/zero)
+ (when (= (:parent-id frame) uuid/zero)
[:& frame-title {:key (dm/str "frame-title-" (:id frame))
:frame frame
:selected? (contains? selected (:id frame))
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index 111305408..c60ec067c 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -337,7 +337,7 @@ msgstr "Export Penpot %s files"
#: src/app/main/ui/export.cljs
msgid "dashboard.export-multiple.selected"
-msgstr "%s de %s elements selected"
+msgstr "%s of %s elements selected"
#: src/app/main/ui/workspace/header.cljs
msgid "dashboard.export-shapes"
@@ -4563,4 +4563,13 @@ msgid "workspace.updates.update"
msgstr "Update"
msgid "workspace.viewport.click-to-close-path"
-msgstr "Click to close the path"
\ No newline at end of file
+msgstr "Click to close the path"
+
+msgid "errors.profile-blocked"
+msgstr "The profile is blocked"
+
+msgid "errors.bad-font"
+msgstr "The font %s could not be loaded"
+
+msgid "errors.bad-font-plural"
+msgstr "The fonts %s could not be loaded"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 2fe5b5bbe..9c0c2ea1f 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -4778,4 +4778,13 @@ msgid "workspace.updates.update"
msgstr "Actualizar"
msgid "workspace.viewport.click-to-close-path"
-msgstr "Pulsar para cerrar la ruta"
\ No newline at end of file
+msgstr "Pulsar para cerrar la ruta"
+
+msgid "errors.profile-blocked"
+msgstr "El perfil esta blockeado"
+
+msgid "errors.bad-font"
+msgstr "No se ha podido cargar la fuente %s"
+
+msgid "errors.bad-font-plural"
+msgstr "No se han podido cargar las fuentes %s"