diff --git a/CHANGES.md b/CHANGES.md index 6d97886629..c6b6e4a41b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,12 @@ - To @ondrejkonec: for contributing to the code with: - Refactor CSS variables [Github #2948](https://github.com/penpot/penpot/pull/2948) +## 1.17.3 + +### :bug: Bugs fixed +- Fix copy and paste very nested inside itself [Taiga #4848](https://tree.taiga.io/project/penpot/issue/4848) +- Fix custom fonts not rendered correctly [Taiga #4874](https://tree.taiga.io/project/penpot/issue/4874) + ## 1.17.2 ### :bug: Bugs fixed @@ -29,10 +35,6 @@ - Fix correct behaviour for space-around and added space-evenly option - Fix duplicate with alt and undo only undo one step [Taiga #4746](https://tree.taiga.io/project/penpot/issue/4746) - Fix problem creating frames inside layout [Taiga #4844](https://tree.taiga.io/project/penpot/issue/4844) - -## 1.17.2 - -### :bug: Bugs fixed - Fix paste board inside itself [Taiga #4775](https://tree.taiga.io/project/penpot/issue/4775) - Fix middle button panning can drag guides [Taiga #4266](https://tree.taiga.io/project/penpot/issue/4266) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index d4e781d62a..04ee77b0a3 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -177,56 +177,64 @@ (watch [_ _ stream] (let [team-id (:team-id project) stoper (rx/filter (ptk/type? ::bundle-fetched) stream)] - (->> (rx/merge - ;; Initialize notifications & load team fonts + (->> (rx/concat + ;; Initialize notifications (rx/of (dwn/initialize team-id id) - (dwsl/initialize) - (df/load-team-fonts team-id)) + (dwsl/initialize)) - ;; Load all pages, independently if they are pointers or already - ;; resolved values. - (->> (rx/from (seq (:pages-index data))) - (rx/merge-map - (fn [[_ page :as kp]] - (if (t/pointer? page) - (resolve-pointer id kp) - (rx/of kp)))) - (rx/merge-map - (fn [[id page]] - (let [page (update page :objects ctst/start-page-index)] - (->> (uw/ask! {:cmd :initialize-page-index :page page}) - (rx/map (constantly [id page])))))) - (rx/reduce conj {}) - (rx/map (fn [pages-index] - (-> data - (assoc :pages-index pages-index) - (workspace-data-loaded))))) + ;; Load team fonts. We must ensure custom fonts are fully loadad before starting the workspace load + (rx/merge + (->> stream + (rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded)) + (rx/take 1) + (rx/ignore)) + (rx/of (df/load-team-fonts team-id))) - ;; Once workspace data is loaded, proceed asynchronously load - ;; the local library and all referenced libraries, without - ;; blocking the main workspace load process. - (->> stream - (rx/filter (ptk/type? ::workspace-data-loaded)) - (rx/take 1) - (rx/merge-map - (fn [_] - (rx/merge - (rx/of (workspace-initialized)) + (rx/merge + ;; Load all pages, independently if they are pointers or already + ;; resolved values. + (->> (rx/from (seq (:pages-index data))) + (rx/merge-map + (fn [[_ page :as kp]] + (if (t/pointer? page) + (resolve-pointer id kp) + (rx/of kp)))) + (rx/merge-map + (fn [[id page]] + (let [page (update page :objects ctst/start-page-index)] + (->> (uw/ask! {:cmd :initialize-page-index :page page}) + (rx/map (constantly [id page])))))) + (rx/reduce conj {}) + (rx/map (fn [pages-index] + (-> data + (assoc :pages-index pages-index) + (workspace-data-loaded))))) - (->> data - (filter (comp t/pointer? val)) - (resolve-pointers id) - (rx/map workspace-data-pointers-loaded)) + ;; Once workspace data is loaded, proceed asynchronously load + ;; the local library and all referenced libraries, without + ;; blocking the main workspace load process. + (->> stream + (rx/filter (ptk/type? ::workspace-data-loaded)) + (rx/take 1) + (rx/merge-map + (fn [_] + (rx/merge + (rx/of (workspace-initialized)) - (->> (rp/cmd! :get-file-libraries {:file-id id :features features}) - (rx/mapcat identity) - (rx/mapcat - (fn [{:keys [id data] :as file}] - (->> (filter (comp t/pointer? val) data) - (resolve-pointers id) - (rx/map #(update file :data merge %))))) - (rx/reduce conj []) - (rx/map libraries-fetched))))))) + (->> data + (filter (comp t/pointer? val)) + (resolve-pointers id) + (rx/map workspace-data-pointers-loaded)) + + (->> (rp/cmd! :get-file-libraries {:file-id id :features features}) + (rx/mapcat identity) + (rx/mapcat + (fn [{:keys [id data] :as file}] + (->> (filter (comp t/pointer? val) data) + (resolve-pointers id) + (rx/map #(update file :data merge %))))) + (rx/reduce conj []) + (rx/map libraries-fetched)))))))) (rx/take-until stoper))))))) @@ -429,7 +437,7 @@ name (cp/generate-unique-name unames (:name page)) no_thumbnails_objects (->> (:objects page) - (d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?)))) + (d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?)))) page (-> page (assoc :name name :id id :objects no_thumbnails_objects)) @@ -1103,13 +1111,13 @@ qparams {:page-id page-id}] ;; qparams {:page-id page-id :layout :assets}] (rx/merge - (rx/of (rt/nav :workspace pparams qparams)) - (->> stream - (rx/filter (ptk/type? ::dwv/initialize-viewport)) - (rx/take 1) - (rx/mapcat #(do - (on-page-selected) - (rx/of (dws/select-shapes (lks/set shape-id))))))))))))) + (rx/of (rt/nav :workspace pparams qparams)) + (->> stream + (rx/filter (ptk/type? ::dwv/initialize-viewport)) + (rx/take 1) + (rx/mapcat #(do + (on-page-selected) + (rx/of (dws/select-shapes (lks/set shape-id))))))))))))) (defn go-to-component [component-id] @@ -1444,9 +1452,17 @@ (and (= 1 (count selected)) (= :frame (get-in objects [(first selected) :type]))))) -(defn same-frame-from-selected? [state frame-id] - (let [selected (wsh/lookup-selected state)] - (contains? frame-id (first selected)))) +(defn get-tree-root-shapes [tree] + ;; This fn gets a map of shapes and finds what shapes are parent of the rest + (let [shapes-in-tree (vals tree) + shape-ids (keys tree) + parent-ids (set (map #(:parent-id %) shapes-in-tree))] + (->> shape-ids + (filter #(contains? parent-ids %))))) + +(defn any-same-frame-from-selected? [state frame-ids] + (let [selected (first (wsh/lookup-selected state))] + (< 0 (count (filter #(= % selected) frame-ids))))) (defn frame-same-size? [paste-obj frame-obj] @@ -1495,22 +1511,27 @@ item)) (calculate-paste-position [state mouse-pos in-viewport?] - (let [page-objects (wsh/lookup-page-objects state) - selected-objs (map #(get paste-objects %) selected) - first-selected-obj (first selected-objs) - page-selected (wsh/lookup-selected state) - wrapper (gsh/selection-rect selected-objs) - orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper)) - frame-id (first page-selected) - frame-object (get page-objects frame-id) - base (cph/get-base-shape page-objects page-selected) - index (cph/get-position-on-parent page-objects (:id base))] + (let [page-objects (wsh/lookup-page-objects state) + selected-objs (map #(get paste-objects %) selected) + first-selected-obj (first selected-objs) + page-selected (wsh/lookup-selected state) + wrapper (gsh/selection-rect selected-objs) + orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper)) + frame-id (first page-selected) + frame-object (get page-objects frame-id) + base (cph/get-base-shape page-objects page-selected) + index (cph/get-position-on-parent page-objects (:id base)) + tree-root (get-tree-root-shapes paste-objects) + only-one-root-shape? (and + (< 1 (count paste-objects)) + (= 1 (count tree-root)))] (cond (selected-frame? state) - (if (or (same-frame-from-selected? state (first (vals paste-objects))) - (frame-same-size? paste-objects frame-object)) + (if (or (any-same-frame-from-selected? state (keys paste-objects)) + (and only-one-root-shape? + (frame-same-size? paste-objects (first tree-root)))) ;; Paste next to selected frame, if selected is itself or of the same size as the copied (let [selected-frame-obj (get page-objects (first page-selected)) parent-id (:parent-id base) @@ -1548,6 +1569,7 @@ ;; - Respect the distance of the object to the right and bottom in the original frame (gpt/point paste-x paste-y))] [frame-id frame-id delta])) + (empty? page-selected) (let [frame-id (ctst/top-nested-frame page-objects mouse-pos) delta (gpt/subtract mouse-pos orig-pos)] @@ -1840,8 +1862,8 @@ (dwm/create-shapes-img pos media-obj))] (->> (rx/concat - (rx/of (update-remove-graphics index)) - (rx/map process-shapes shapes)) + (rx/of (update-remove-graphics index)) + (rx/map process-shapes shapes)) (rx/catch #(do (log/error :msg (str "Error removing " (:name media-obj)) :hint (ex-message %) @@ -1875,15 +1897,15 @@ (ctst/generate-shape-grid media-points start-pos grid-gap)] (rx/concat - (rx/of (modal/show {:type :remove-graphics-dialog :file-name file-name}) - (initialize-remove-graphics (count media))) - (when new-page? - (rx/of (dch/commit-changes (-> (pcb/empty-changes it) - (pcb/set-save-undo? false) - (pcb/add-page (:id page) page))))) - (rx/mapcat (partial remove-graphic it file-data' page) - (rx/from (d/enumerate (d/zip media shape-grid)))) - (rx/of (complete-remove-graphics))))))) + (rx/of (modal/show {:type :remove-graphics-dialog :file-name file-name}) + (initialize-remove-graphics (count media))) + (when new-page? + (rx/of (dch/commit-changes (-> (pcb/empty-changes it) + (pcb/set-save-undo? false) + (pcb/add-page (:id page) page))))) + (rx/mapcat (partial remove-graphic it file-data' page) + (rx/from (d/enumerate (d/zip media shape-grid)))) + (rx/of (complete-remove-graphics))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Read only diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 9fcfa4b0e8..60e74eaa07 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -236,6 +236,13 @@ (-> shape (assoc :layout-item-h-sizing :auto :layout-item-v-sizing :auto)))) + ;; Set the children to fixed to remove strange interactions + (dwc/update-shapes + selected + (fn [shape] + (-> shape + (assoc :layout-item-h-sizing :fix + :layout-item-v-sizing :fix)))) (ptk/data-event :layout/update [new-shape-id]) (dws/delete-shapes page-id selected) @@ -257,6 +264,13 @@ (merge flex-params) (assoc :layout-item-h-sizing :auto :layout-item-v-sizing :auto)))) + ;; Set the children to fixed to remove strange interactions + (dwc/update-shapes + selected + (fn [shape] + (-> shape + (assoc :layout-item-h-sizing :fix + :layout-item-v-sizing :fix)))) (ptk/data-event :layout/update [new-shape-id]) (dwu/commit-undo-transaction undo-id))))))))