Merge branch 'staging' into develop

This commit is contained in:
Andrey Antukh 2022-01-26 12:16:50 +01:00
commit e1a88ae899
9 changed files with 110 additions and 51 deletions

View file

@ -2,6 +2,8 @@
## :rocket: Next ## :rocket: Next
### :boom: Breaking changes
### :sparkles: New features ### :sparkles: New features
- Add select layer option to context menu [Taiga #2474](https://tree.taiga.io/project/penpot/us/2474). - Add select layer option to context menu [Taiga #2474](https://tree.taiga.io/project/penpot/us/2474).
@ -11,6 +13,11 @@
- Create e2e tests for drawing basic shapes [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608). - Create e2e tests for drawing basic shapes [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608).
- Create firsts e2e test [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608). - Create firsts e2e test [Taiga #2608](https://tree.taiga.io/project/penpot/task/2608).
### :bug: Bugs fixed
### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!)
## 1.11.0-beta ## 1.11.0-beta
### :boom: Breaking changes ### :boom: Breaking changes
@ -85,6 +92,7 @@
- Fix auto hide header in viewer full screen [Taiga #2632](https://tree.taiga.io/project/penpot/issue/2632) - Fix auto hide header in viewer full screen [Taiga #2632](https://tree.taiga.io/project/penpot/issue/2632)
- Fix zoom in/out after fit or fill [Taiga #2630](https://tree.taiga.io/project/penpot/issue/2630) - Fix zoom in/out after fit or fill [Taiga #2630](https://tree.taiga.io/project/penpot/issue/2630)
- Normalize zoom levels in workspace and viewer [Taiga #2631](https://tree.taiga.io/project/penpot/issue/2631) - Normalize zoom levels in workspace and viewer [Taiga #2631](https://tree.taiga.io/project/penpot/issue/2631)
- Avoid empty names in projects, files and pages [Taiga #2594](https://tree.taiga.io/project/penpot/issue/2594)
### :arrow_up: Deps updates ### :arrow_up: Deps updates
@ -96,7 +104,7 @@
- Explain folders in components (by @candideu) [Penpot-docs #42](https://github.com/penpot/penpot-docs/pull/42). - Explain folders in components (by @candideu) [Penpot-docs #42](https://github.com/penpot/penpot-docs/pull/42).
- Readability improvements of user guide (by @PaulSchulz) [Penpot-docs #50](https://github.com/penpot/penpot-docs/pull/50). - Readability improvements of user guide (by @PaulSchulz) [Penpot-docs #50](https://github.com/penpot/penpot-docs/pull/50).
# 1.10.4-beta ## 1.10.4-beta
### :sparkles: Enhacements ### :sparkles: Enhacements
@ -108,7 +116,7 @@
- Minor fix on how file changes log is persisted. - Minor fix on how file changes log is persisted.
- Fix many issues on error reporting. - Fix many issues on error reporting.
# 1.10.3-beta ## 1.10.3-beta
### :sparkles: Enhacements ### :sparkles: Enhacements
@ -130,7 +138,7 @@
- Update log4j2 dependency. - Update log4j2 dependency.
# 1.10.2-beta ## 1.10.2-beta
### :bug: Bugs fixed ### :bug: Bugs fixed
@ -142,7 +150,7 @@
- Update log4j2 dependency. - Update log4j2 dependency.
# 1.10.1-beta ## 1.10.1-beta
### :bug: Bugs fixed ### :bug: Bugs fixed

View file

@ -95,7 +95,6 @@
(s/def ::color ::spec/color) (s/def ::color ::spec/color)
(s/def ::data ::spec/data) (s/def ::data ::spec/data)
(s/def ::media-object ::spec/media-object) (s/def ::media-object ::spec/media-object)
(s/def ::minimal-shape ::spec/minimal-shape)
(s/def ::page ::spec/page) (s/def ::page ::spec/page)
(s/def ::recent-color ::spec/recent-color) (s/def ::recent-color ::spec/recent-color)
(s/def ::shape-attrs ::spec/shape-attrs) (s/def ::shape-attrs ::spec/shape-attrs)

View file

@ -173,7 +173,6 @@
;; Page Data related ;; Page Data related
(s/def :internal.shape/blocked boolean?) (s/def :internal.shape/blocked boolean?)
(s/def :internal.shape/collapsed boolean?) (s/def :internal.shape/collapsed boolean?)
(s/def :internal.shape/content any?)
(s/def :internal.shape/fill-color string?) (s/def :internal.shape/fill-color string?)
(s/def :internal.shape/fill-opacity ::us/safe-number) (s/def :internal.shape/fill-opacity ::us/safe-number)
@ -277,17 +276,21 @@
:luminosity}) :luminosity})
(s/def ::shape-attrs (s/def ::shape-attrs
(s/keys :opt-un [:internal.shape/selrect (s/keys :req-un [::type ::name]
:opt-un [::id
::component-id
::component-file
::component-root?
::shape-ref
:internal.shape/selrect
:internal.shape/points :internal.shape/points
:internal.shape/blocked :internal.shape/blocked
:internal.shape/collapsed :internal.shape/collapsed
:internal.shape/content
:internal.shape/fill-color :internal.shape/fill-color
:internal.shape/fill-opacity :internal.shape/fill-opacity
:internal.shape/fill-color-gradient :internal.shape/fill-color-gradient
:internal.shape/fill-color-ref-file :internal.shape/fill-color-ref-file
:internal.shape/fill-color-ref-id :internal.shape/fill-color-ref-id
:internal.shape/hide-fill-on-export ;; only for frames
:internal.shape/font-family :internal.shape/font-family
:internal.shape/font-size :internal.shape/font-size
:internal.shape/font-style :internal.shape/font-style
@ -332,22 +335,50 @@
:internal.shape/opacity :internal.shape/opacity
:internal.shape/blend-mode])) :internal.shape/blend-mode]))
(s/def :internal.shape.text/type #{"root" "paragraph-set" "paragraph"})
(s/def :internal.shape.text/children
(s/coll-of :internal.shape.text/content
:kind vector?
:min-count 1))
;; shapes-group is handled differently (s/def :internal.shape.text/text string?)
(s/def :internal.shape.text/key string?)
(s/def ::minimal-shape (s/def :internal.shape.text/content
(s/keys :req-un [::type ::name] (s/or :container
:opt-un [::id])) (s/keys :req-un [:internal.shape.text/type
:internal.shape.text/children]
:opt-un [:internal.shape.text/key])
:content
(s/keys :req-un [:internal.shape.text/text])))
(s/def ::shape (s/def :internal.shape.path/command keyword?)
(s/and ::minimal-shape (s/def :internal.shape.path/params (s/map-of keyword? any?))
::shape-attrs (s/def :internal.shape.path/command-item
(s/keys :opt-un [::id (s/keys :req-un [:internal.shape.path/command
::component-id :internal.shape.path/params]))
::component-file
::component-root?
::shape-ref])))
(s/def :internal.shape.path/content
(s/coll-of :internal.shape.path/command-item :kind vector?))
(defmulti shape-spec :type)
(defmethod shape-spec :default [_]
(s/spec ::shape-attrs))
(defmethod shape-spec :text [_]
(s/and ::shape-attrs
(s/keys :opt-un [:internal.shape.text/content])))
(defmethod shape-spec :path [_]
(s/and ::shape-attrs
(s/keys :opt-un [:internal.shape.path/content])))
(defmethod shape-spec :frame [_]
(s/and ::shape-attrs
(s/keys :opt-un [:internal.shape/hide-fill-on-export])))
(s/def ::shape (s/multi-spec shape-spec :type))
(s/def :internal.page/objects (s/map-of uuid? ::shape)) (s/def :internal.page/objects (s/map-of uuid? ::shape))
(s/def ::page (s/def ::page
@ -356,7 +387,6 @@
::cto/options ::cto/options
:internal.page/objects])) :internal.page/objects]))
(s/def ::recent-color (s/def ::recent-color
(s/keys :opt-un [:internal.color/value (s/keys :opt-un [:internal.color/value
:internal.color/color :internal.color/color

View file

@ -1247,7 +1247,7 @@
(defn update-shape-flags (defn update-shape-flags
[ids {:keys [blocked hidden] :as flags}] [ids {:keys [blocked hidden] :as flags}]
(us/verify (s/coll-of ::us/uuid) ids) (us/verify (s/coll-of ::us/uuid) ids)
(s/assert ::shape-attrs flags) (us/assert ::shape-attrs flags)
(ptk/reify ::update-shape-flags (ptk/reify ::update-shape-flags
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
@ -1449,7 +1449,6 @@
(defn show-shape-context-menu (defn show-shape-context-menu
[{:keys [shape] :as params}] [{:keys [shape] :as params}]
(us/verify (s/nilable ::cp/minimal-shape) shape)
(ptk/reify ::show-shape-context-menu (ptk/reify ::show-shape-context-menu
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
@ -1858,7 +1857,7 @@
(defn paste-text (defn paste-text
[text] [text]
(s/assert string? text) (us/assert string? text)
(ptk/reify ::paste-text (ptk/reify ::paste-text
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
@ -1887,7 +1886,7 @@
(defn- paste-svg (defn- paste-svg
[text] [text]
(s/assert string? text) (us/assert string? text)
(ptk/reify ::paste-svg (ptk/reify ::paste-svg
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]

View file

@ -16,6 +16,7 @@
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[cuerdas.core :as str]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(mf/defc header (mf/defc header
@ -63,9 +64,11 @@
(if (:edition @local) (if (:edition @local)
[:& inline-edition {:content (:name project) [:& inline-edition {:content (:name project)
:on-end (fn [name] :on-end (fn [name]
(let [name (str/trim name)]
(when-not (str/empty? name)
(st/emit! (-> (dd/rename-project (assoc project :name name)) (st/emit! (-> (dd/rename-project (assoc project :name name))
(with-meta {::ev/origin "project"}))) (with-meta {::ev/origin "project"}))))
(swap! local assoc :edition false))}] (swap! local assoc :edition false)))}]
[:div.dashboard-title [:div.dashboard-title
[:h1 {:on-double-click on-edit} [:h1 {:on-double-click on-edit}
(:name project)]])) (:name project)]]))

View file

@ -18,6 +18,7 @@
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
[app.util.time :as dt] [app.util.time :as dt]
[cuerdas.core :as str]
[okulary.core :as l] [okulary.core :as l]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
@ -73,9 +74,11 @@
(mf/use-callback (mf/use-callback
(mf/deps project) (mf/deps project)
(fn [name] (fn [name]
(let [name (str/trim name)]
(when-not (str/empty? name)
(st/emit! (-> (dd/rename-project (assoc project :name name)) (st/emit! (-> (dd/rename-project (assoc project :name name))
(with-meta {::ev/origin "dashboard"}))) (with-meta {::ev/origin "dashboard"}))))
(swap! local assoc :edition? false))) (swap! local assoc :edition? false))))
on-file-created on-file-created
(mf/use-callback (mf/use-callback

View file

@ -46,8 +46,8 @@
(on-stop-edit) (on-stop-edit)
(swap! local assoc :edition false) (swap! local assoc :edition false)
(st/emit! (dw/end-rename-shape) (st/emit! (dw/end-rename-shape)
(when-not (str/empty? name) (when-not (str/empty? (str/trim name))
(dw/update-shape (:id shape) {:name name}))))) (dw/update-shape (:id shape) {:name (str/trim name)})))))
cancel-edit (fn [] cancel-edit (fn []
(on-stop-edit) (on-stop-edit)

View file

@ -18,6 +18,7 @@
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[cuerdas.core :as str]
[okulary.core :as l] [okulary.core :as l]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
@ -66,8 +67,9 @@
(mf/use-callback (mf/use-callback
(fn [event] (fn [event]
(let [target (dom/event->target event) (let [target (dom/event->target event)
name (dom/get-value target)] name (str/trim (dom/get-value target))]
(st/emit! (dw/rename-page id name)) (when-not (str/empty? name)
(st/emit! (dw/rename-page id name)))
(swap! local assoc :edition false)))) (swap! local assoc :edition false))))
on-key-down on-key-down

View file

@ -316,6 +316,11 @@
(->> (rx/of node) (->> (rx/of node)
(rx/observe-on :async)))) (rx/observe-on :async))))
(defn media-node? [node]
(and (cip/shape? node)
(cip/has-image? node)
(not (cip/close? node))))
(defn import-page (defn import-page
[context file [page-id page-name content]] [context file [page-id page-name content]]
(let [nodes (->> content cip/node-seq) (let [nodes (->> content cip/node-seq)
@ -326,18 +331,29 @@
(assoc :id (resolve page-id))) (assoc :id (resolve page-id)))
flows (->> (get-in page-data [:options :flows]) flows (->> (get-in page-data [:options :flows])
(mapv #(update % :starting-frame resolve))) (mapv #(update % :starting-frame resolve)))
guides (->> (get-in page-data [:options :guides]) page-data (d/assoc-in-when page-data [:options :flows] flows)
(d/mapm #(update %2 :frame-id resolve))) file (-> file (fb/add-page page-data))
page-data (-> page-data ;; Preprocess nodes to parallel upload the images. Store the result in a table
(d/assoc-in-when [:options :flows] flows) ;; old-node => node with image
(d/assoc-in-when [:options :guides] guides)) ;; that will be used in the second pass immediately
file (-> file (fb/add-page page-data))] pre-process-images
(->> (rx/from nodes)
(rx/filter media-node?)
(rx/merge-map
(fn [node]
(->> (resolve-media context file-id node)
(rx/map (fn [result] [node result])))))
(rx/reduce conj {}))]
(->> pre-process-images
(rx/flat-map
(fn [pre-proc]
(->> (rx/from nodes) (->> (rx/from nodes)
(rx/filter cip/shape?) (rx/filter cip/shape?)
(rx/merge-map (partial resolve-media context file-id)) (rx/map (fn [node] (or (get pre-proc node) node)))
(rx/reduce (partial process-import-node context) file) (rx/reduce (partial process-import-node context) file)
(rx/map (comp fb/close-page setup-interactions))))) (rx/map (comp fb/close-page setup-interactions))))))))
(defn import-component [context file node] (defn import-component [context file node]
(let [resolve (:resolve context) (let [resolve (:resolve context)
@ -357,7 +373,7 @@
(rx/filter cip/shape?) (rx/filter cip/shape?)
(rx/skip 1) (rx/skip 1)
(rx/skip-last 1) (rx/skip-last 1)
(rx/merge-map (partial resolve-media context file-id)) (rx/mapcat (partial resolve-media context file-id))
(rx/reduce (partial process-import-node context) file) (rx/reduce (partial process-import-node context) file)
(rx/map fb/finish-component)))) (rx/map fb/finish-component))))
@ -377,7 +393,6 @@
(fn [[page-id page-name]] (fn [[page-id page-name]]
(->> (get-file context :page page-id) (->> (get-file context :page page-id)
(rx/map (fn [page-data] [page-id page-name page-data]))))) (rx/map (fn [page-data] [page-id page-name page-data])))))
(rx/concat-reduce (partial import-page context) file)))) (rx/concat-reduce (partial import-page context) file))))
(defn process-library-colors (defn process-library-colors
@ -416,7 +431,7 @@
(let [resolve (:resolve context)] (let [resolve (:resolve context)]
(->> (get-file context :media-list) (->> (get-file context :media-list)
(rx/flat-map (comp d/kebab-keys cip/string->uuid)) (rx/flat-map (comp d/kebab-keys cip/string->uuid))
(rx/merge-map (rx/mapcat
(fn [[id media]] (fn [[id media]]
(let [media (assoc media :id (resolve id))] (let [media (assoc media :id (resolve id))]
(->> (get-file context :media id media) (->> (get-file context :media id media)