mirror of
https://github.com/penpot/penpot.git
synced 2025-02-15 03:28:25 -05:00
🐛 Fix undo on page relocate/sorting.
This commit is contained in:
parent
c4947d3737
commit
e7b4010eba
9 changed files with 89 additions and 33 deletions
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
;; Auxiliary functions to help create a set of changes (undo + redo)
|
;; Auxiliary functions to help create a set of changes (undo + redo)
|
||||||
|
|
||||||
(defn empty-changes [origin page-id]
|
(defn empty-changes
|
||||||
|
[origin page-id]
|
||||||
(let [changes {:redo-changes []
|
(let [changes {:redo-changes []
|
||||||
:undo-changes []
|
:undo-changes []
|
||||||
:origin origin}]
|
:origin origin}]
|
||||||
|
@ -165,3 +166,11 @@
|
||||||
(update :undo-changes #(as-> % $
|
(update :undo-changes #(as-> % $
|
||||||
(reduce add-undo-change-parent $ ids)
|
(reduce add-undo-change-parent $ ids)
|
||||||
(reduce add-undo-change-shape $ ids))))))
|
(reduce add-undo-change-shape $ ids))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn move-page
|
||||||
|
[chdata index prev-index]
|
||||||
|
(let [page-id (::page-id (meta chdata))]
|
||||||
|
(-> chdata
|
||||||
|
(update :redo-changes conj {:type :mov-page :id page-id :index index})
|
||||||
|
(update :undo-changes conj {:type :mov-page :id page-id :index prev-index}))))
|
||||||
|
|
|
@ -213,11 +213,16 @@
|
||||||
(defn insert-at-index
|
(defn insert-at-index
|
||||||
[objects index ids]
|
[objects index ids]
|
||||||
(let [[before after] (split-at index objects)
|
(let [[before after] (split-at index objects)
|
||||||
p? (set ids)]
|
p? (complement (set ids))
|
||||||
(d/concat []
|
before' (filterv p? before)
|
||||||
(remove p? before)
|
after' (filterv p? after)]
|
||||||
ids
|
|
||||||
(remove p? after))))
|
(if (and (not= (count before) (count before'))
|
||||||
|
(pos? (count after')))
|
||||||
|
(let [before' (conj before' (first after'))
|
||||||
|
after' (into [] (rest after'))]
|
||||||
|
(d/concat [] before' ids after'))
|
||||||
|
(d/concat [] before' ids after'))))
|
||||||
|
|
||||||
(defn append-at-the-end
|
(defn append-at-the-end
|
||||||
[prev-ids ids]
|
[prev-ids ids]
|
||||||
|
|
50
common/test/app/common/pages_helpers_test.cljc
Normal file
50
common/test/app/common/pages_helpers_test.cljc
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.common.pages-helpers-test
|
||||||
|
(:require
|
||||||
|
[clojure.test :as t]
|
||||||
|
[clojure.pprint :refer [pprint]]
|
||||||
|
[app.common.pages.helpers :as cph]))
|
||||||
|
|
||||||
|
(t/deftest insert-at-index
|
||||||
|
;; insert different object
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 1 [:c :d])
|
||||||
|
[:a :c :d :b]))
|
||||||
|
|
||||||
|
;; insert on the start
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 0 [:c])
|
||||||
|
[:c :a :b]))
|
||||||
|
|
||||||
|
;; insert on the end 1
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 2 [:c])
|
||||||
|
[:a :b :c]))
|
||||||
|
|
||||||
|
;; insert on the end with not existing index
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 10 [:c])
|
||||||
|
[:a :b :c]))
|
||||||
|
|
||||||
|
;; insert existing in a contiguos index
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 1 [:a])
|
||||||
|
[:b :a]))
|
||||||
|
|
||||||
|
;; insert existing in the same index
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b] 0 [:a])
|
||||||
|
[:a :b]))
|
||||||
|
|
||||||
|
;; insert existing in other index case 1
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b :c] 2 [:a])
|
||||||
|
[:b :c :a]))
|
||||||
|
|
||||||
|
;; insert existing in other index case 2
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b :c :d] 0 [:d])
|
||||||
|
[:d :a :b :c]))
|
||||||
|
|
||||||
|
;; insert existing in other index case 3
|
||||||
|
(t/is (= (cph/insert-at-index [:a :b :c :d] 1 [:a])
|
||||||
|
[:b :a :c :d]))
|
||||||
|
|
||||||
|
)
|
|
@ -574,7 +574,7 @@
|
||||||
|
|
||||||
;; After
|
;; After
|
||||||
|
|
||||||
(t/is (= [shape-4-id shape-3-id group-1-id]
|
(t/is (= [shape-4-id group-1-id shape-3-id]
|
||||||
(get-in res [:pages-index page-id :objects cp/root :shapes])))
|
(get-in res [:pages-index page-id :objects cp/root :shapes])))
|
||||||
|
|
||||||
;; (pprint (get-in data [:pages-index page-id :objects cp/root]))
|
;; (pprint (get-in data [:pages-index page-id :objects cp/root]))
|
||||||
|
|
|
@ -81,8 +81,6 @@
|
||||||
(when-not (contains? ids ctid)
|
(when-not (contains? ids ctid)
|
||||||
(swap! storage dissoc ::current-team-id)))))))
|
(swap! storage dissoc ::current-team-id)))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn fetch-teams
|
(defn fetch-teams
|
||||||
[]
|
[]
|
||||||
(ptk/reify ::fetch-teams
|
(ptk/reify ::fetch-teams
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.pages.spec :as spec]
|
[app.common.pages.spec :as spec]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
@ -350,16 +351,16 @@
|
||||||
|
|
||||||
;; TODO: properly handle positioning on undo.
|
;; TODO: properly handle positioning on undo.
|
||||||
|
|
||||||
|
;; TODO: for some reason, the page-id here in some circumstances is `nil`
|
||||||
(defn delete-page
|
(defn delete-page
|
||||||
[id]
|
[id]
|
||||||
(ptk/reify ::delete-page
|
(ptk/reify ::delete-page
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page (get-in state [:workspace-data :pages-index id])
|
(let [page (get-in state [:workspace-data :pages-index id])
|
||||||
rchg {:type :del-page
|
rchg {:type :del-page :id id}
|
||||||
:id id}
|
uchg {:type :add-page :page page}]
|
||||||
uchg {:type :add-page
|
|
||||||
:page page}]
|
|
||||||
(rx/of (dch/commit-changes {:redo-changes [rchg]
|
(rx/of (dch/commit-changes {:redo-changes [rchg]
|
||||||
:undo-changes [uchg]
|
:undo-changes [uchg]
|
||||||
:origin it})
|
:origin it})
|
||||||
|
@ -1114,17 +1115,11 @@
|
||||||
(ptk/reify ::relocate-pages
|
(ptk/reify ::relocate-pages
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [cidx (-> (get-in state [:workspace-data :pages])
|
(let [prev-index (-> (get-in state [:workspace-data :pages])
|
||||||
(d/index-of id))
|
(d/index-of id))
|
||||||
rchg {:type :mov-page
|
changes (-> (pcb/empty-changes it id)
|
||||||
:id id
|
(pcb/move-page index prev-index))]
|
||||||
:index index}
|
(rx/of (dch/commit-changes changes))))))
|
||||||
uchg {:type :mov-page
|
|
||||||
:id id
|
|
||||||
:index cidx}]
|
|
||||||
(rx/of (dch/commit-changes {:redo-changes [rchg]
|
|
||||||
:undo-changes [uchg]
|
|
||||||
:origin it}))))))
|
|
||||||
|
|
||||||
;; --- Shape / Selection Alignment and Distribution
|
;; --- Shape / Selection Alignment and Distribution
|
||||||
|
|
||||||
|
|
|
@ -114,20 +114,20 @@
|
||||||
:changes changes}))))
|
:changes changes}))))
|
||||||
|
|
||||||
(defn commit-changes
|
(defn commit-changes
|
||||||
[{:keys [redo-changes undo-changes origin save-undo? file-id]
|
[{:keys [redo-changes undo-changes origin save-undo? file-id] :or {save-undo? true}}]
|
||||||
:or {save-undo? true}}]
|
|
||||||
|
|
||||||
(log/debug :msg "commit-changes"
|
(log/debug :msg "commit-changes"
|
||||||
:js/redo-changes redo-changes
|
:js/redo-changes redo-changes
|
||||||
:js/undo-changes undo-changes)
|
:js/undo-changes undo-changes)
|
||||||
|
(let [error (volatile! nil)
|
||||||
|
strace (.-stack (ex-info "" {}))]
|
||||||
|
|
||||||
(let [error (volatile! nil)]
|
|
||||||
(ptk/reify ::commit-changes
|
(ptk/reify ::commit-changes
|
||||||
cljs.core/IDeref
|
cljs.core/IDeref
|
||||||
(-deref [_]
|
(-deref [_]
|
||||||
{:file-id file-id
|
{:file-id file-id
|
||||||
:hint-events @st/last-events
|
:hint-events @st/last-events
|
||||||
:hint-origin (ptk/type origin)
|
:hint-origin (ptk/type origin)
|
||||||
|
:hint-strace strace
|
||||||
:changes redo-changes})
|
:changes redo-changes})
|
||||||
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -135,7 +135,6 @@
|
||||||
(let [current-file-id (get state :current-file-id)
|
(let [current-file-id (get state :current-file-id)
|
||||||
file-id (or file-id current-file-id)
|
file-id (or file-id current-file-id)
|
||||||
path (if (= file-id current-file-id)
|
path (if (= file-id current-file-id)
|
||||||
|
|
||||||
[:workspace-data]
|
[:workspace-data]
|
||||||
[:workspace-libraries file-id :data])]
|
[:workspace-libraries file-id :data])]
|
||||||
(try
|
(try
|
||||||
|
|
|
@ -70,7 +70,8 @@
|
||||||
(accumulate-undo-entry state entry)
|
(accumulate-undo-entry state entry)
|
||||||
(add-undo-entry state entry)))))
|
(add-undo-entry state entry)))))
|
||||||
|
|
||||||
(defonce empty-tx {:undo-changes [] :redo-changes []})
|
(def empty-tx
|
||||||
|
{:undo-changes [] :redo-changes []})
|
||||||
|
|
||||||
(defn start-undo-transaction []
|
(defn start-undo-transaction []
|
||||||
(ptk/reify ::start-undo-transaction
|
(ptk/reify ::start-undo-transaction
|
||||||
|
|
|
@ -82,10 +82,9 @@
|
||||||
|
|
||||||
on-drop
|
on-drop
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps id)
|
(mf/deps id index)
|
||||||
(fn [side {:keys [id] :as data}]
|
(fn [side {:keys [id] :as data}]
|
||||||
(let [index (if (= :bot side) (inc index) index)]
|
(st/emit! (dw/relocate-page id index))))
|
||||||
(st/emit! (dw/relocate-page id index)))))
|
|
||||||
|
|
||||||
on-duplicate
|
on-duplicate
|
||||||
(fn [_]
|
(fn [_]
|
||||||
|
|
Loading…
Add table
Reference in a new issue