mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 23:49:45 -05:00
🐛 Fixes problem with undo/redo
This commit is contained in:
parent
50321895e5
commit
28da2406d3
7 changed files with 70 additions and 222 deletions
|
@ -2,132 +2,43 @@
|
|||
// 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) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
// Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
// This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
// defined by the Mozilla Public License, v. 2.0.
|
||||
//
|
||||
// Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
.document-history {
|
||||
|
||||
.history-tabs {
|
||||
background-color: $color-gray-60;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
background: darken($color-gray-60, 12%);
|
||||
border-top-right-radius: $br-small;
|
||||
border-top-left-radius: $br-small;
|
||||
color: $color-gray-60;
|
||||
cursor: pointer;
|
||||
font-size: $fs14;
|
||||
font-weight: bold;
|
||||
justify-content: center;
|
||||
margin: $x-small $x-small 0 $x-small;
|
||||
padding: $x-small $small;
|
||||
text-align: center;
|
||||
width: 50%;
|
||||
|
||||
&.selected {
|
||||
background-color: $color-gray-50;
|
||||
color: $color-primary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.history-content {
|
||||
.history-toolbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
li {
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
font-size: $fs14;
|
||||
width: 100%;
|
||||
padding: $small;
|
||||
.history-toolbox-title {
|
||||
color: $color-gray-10;
|
||||
font-size: $fs14;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.page-actions {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
.undo-history {
|
||||
font-size: $fs12;
|
||||
color: $color-gray-10;
|
||||
|
||||
a {
|
||||
|
||||
svg {
|
||||
fill: $color-gray-60;
|
||||
height: 15px;
|
||||
margin-left: $x-small;
|
||||
width: 15px;
|
||||
|
||||
&:hover {
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.pin-icon {
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-60;
|
||||
height: 12px;
|
||||
margin-right: $small;
|
||||
width: 12px;
|
||||
|
||||
&:hover {
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
|
||||
}
|
||||
.undo-entry {
|
||||
max-height: 10rem;
|
||||
overflow: auto;
|
||||
margin: 0.5rem;
|
||||
|
||||
&.selected {
|
||||
|
||||
svg {
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
|
||||
border: 2px solid $color-primary;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $color-primary;
|
||||
}
|
||||
|
||||
&.current {
|
||||
color: $color-primary;
|
||||
font-weight: bold;
|
||||
|
||||
span {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
&::before {
|
||||
background-color: $color-primary;
|
||||
border-radius: 50%;
|
||||
content: "";
|
||||
height: 6px;
|
||||
flex-shrink: 0;
|
||||
margin: $x-small;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.undo-entry-change {
|
||||
background-color: #1F1F1F;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 0.5rem;
|
||||
border-color: $color-primary;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -383,10 +383,13 @@
|
|||
(fn [flags]
|
||||
(cond
|
||||
(contains? (set flags-to-toggle) :assets)
|
||||
(disj flags :sitemap :layers)
|
||||
(disj flags :sitemap :layers :document-history)
|
||||
|
||||
(contains? (set flags-to-toggle) :sitemap)
|
||||
(disj flags :assets)
|
||||
(disj flags :assets :document-history)
|
||||
|
||||
(contains? (set flags-to-toggle) :document-history)
|
||||
(disj flags :assets :sitemap :layers)
|
||||
|
||||
:else
|
||||
flags))))
|
||||
|
|
|
@ -271,7 +271,8 @@
|
|||
(ptk/reify ::append-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:workspace-undo :items] (fnil conj-undo-entry []) entry))))
|
||||
(let [state (update-in state [:workspace-undo :items] (fnil conj-undo-entry []) entry)]
|
||||
(assoc-in state [:workspace-undo :index] (dec (count (get-in state [:workspace-undo :items]))))))))
|
||||
|
||||
(def undo
|
||||
(ptk/reify ::undo
|
||||
|
@ -292,7 +293,7 @@
|
|||
(let [undo (:workspace-undo state)
|
||||
items (:items undo)
|
||||
index (or (:index undo) (dec (count items)))]
|
||||
(when-not (or (empty? items) (= index (dec items)))
|
||||
(when-not (or (empty? items) (= index (dec (count items))))
|
||||
(let [changes (get-in items [(inc index) :redo-changes])]
|
||||
(rx/of (materialize-undo changes (inc index))
|
||||
(commit-changes changes [] {:save-undo? false}))))))))
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
[app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
|
||||
[app.main.ui.workspace.scroll :as scroll]
|
||||
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-dialog]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport coordinates]]
|
||||
[app.util.dom :as dom]
|
||||
[beicon.core :as rx]
|
||||
|
@ -49,8 +48,6 @@
|
|||
:team-id (:team-id project)}])
|
||||
|
||||
[:section.workspace-content {:class classes}
|
||||
[:& history-dialog]
|
||||
|
||||
[:section.workspace-viewport
|
||||
(when (contains? layout :rules)
|
||||
[:*
|
||||
|
|
|
@ -105,7 +105,9 @@
|
|||
:on-click #(st/emit! (dw/toggle-layout-flags :assets))}
|
||||
i/library]
|
||||
[:li.tooltip.tooltip-right
|
||||
{:alt "History"}
|
||||
{:alt "History"
|
||||
:class (when (contains? layout :document-history) "selected")
|
||||
:on-click #(st/emit! (dw/toggle-layout-flags :document-history))}
|
||||
i/undo-history]
|
||||
[:li.tooltip.tooltip-right
|
||||
{:alt (t locale "workspace.toolbar.color-palette")
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
[:& sitemap {:file file
|
||||
:page-id page-id
|
||||
:layout layout}])
|
||||
#_(when (contains? layout :document-history)
|
||||
(when (contains? layout :document-history)
|
||||
[:& history-toolbox])
|
||||
(when (contains? layout :layers)
|
||||
[:& layers-toolbox])
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
;; 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) 2015-2019 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.history
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.data.history :as udh]
|
||||
[app.main.data.workspace :as dw]
|
||||
|
@ -15,102 +18,33 @@
|
|||
[app.main.store :as st]
|
||||
[app.util.data :refer [read-string]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer (tr)]
|
||||
[app.util.i18n :refer [t] :as i18n]
|
||||
[app.util.router :as r]
|
||||
[app.util.time :as dt]))
|
||||
[app.util.time :as dt]
|
||||
[okulary.core :as l]
|
||||
[app.main.store :as st]))
|
||||
|
||||
;; --- History Item (Component)
|
||||
(def workspace-undo
|
||||
(l/derived :workspace-undo st/state))
|
||||
|
||||
(mf/defc history-item
|
||||
[{:keys [item selected?] :as props}]
|
||||
(letfn [(on-select [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (udh/select (:version item))))
|
||||
(on-pinned [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [item (assoc item
|
||||
:label "no label"
|
||||
:pinned (not (:pinned item)))]
|
||||
(st/emit! (udh/update-history-item item))))]
|
||||
[:li {:class (when selected? "current")
|
||||
:on-click on-select}
|
||||
[:div.pin-icon {:on-click on-pinned
|
||||
:class (when (:pinned item) "selected")}
|
||||
i/pin]
|
||||
[:span (str "Version " (:version item)
|
||||
" (" (dt/timeago (:created-at item)) ")")]]))
|
||||
|
||||
;; --- History List (Component)
|
||||
|
||||
(mf/defc history-list
|
||||
[{:keys [history] :as props}]
|
||||
(let [items (reverse (sort-by :version (:items history)))
|
||||
show-more? (pos? (:min-version history))
|
||||
load-more #(st/emit! udh/load-more)]
|
||||
[:ul.history-content
|
||||
(for [item items]
|
||||
[:& history-item {:item item
|
||||
:key (:id item)
|
||||
:selected? (= (:selected history)
|
||||
(:version item))}])
|
||||
(when show-more?
|
||||
[:li {:on-click load-more}
|
||||
[:a.btn-primary.btn-small "view more"]])]))
|
||||
|
||||
;; --- History Pinned List (Component)
|
||||
|
||||
(mf/defc history-pinned-list
|
||||
[{:keys [history] :as props}]
|
||||
[:ul.history-content
|
||||
(for [item (reverse (sort-by :version (:pinned history)))]
|
||||
[:& history-item {:item item
|
||||
:key (:id item)
|
||||
:selected? (= (:selected history)
|
||||
(:version item))}])])
|
||||
|
||||
;; --- History Toolbox (Component)
|
||||
|
||||
(mf/defc history-toolbox
|
||||
[props]
|
||||
(let [history nil #_(mf/deref refs/history)
|
||||
section (mf/use-state :main)
|
||||
;; close #(st/emit! (dw/toggle-flag :history))
|
||||
close (constantly nil)
|
||||
main? (= @section :main)
|
||||
pinned? (= @section :pinned)
|
||||
show-main #(st/emit! (udh/select-section :main))
|
||||
show-pinned #(st/emit! (udh/select-section :pinned))]
|
||||
[:div.document-history.tool-window
|
||||
[:div.tool-window-bar
|
||||
[:div.tool-window-icon i/undo-history]
|
||||
[:span (tr "ds.settings.document-history")]
|
||||
[:div.tool-window-close {:on-click close} i/close]]
|
||||
[:div.tool-window-content
|
||||
[:ul.history-tabs
|
||||
[:li {:on-click #(reset! section :main)
|
||||
:class (when main? "selected")}
|
||||
(tr "ds.history.versions")]
|
||||
[:li {:on-click #(reset! section :pinned)
|
||||
:class (when pinned? "selected")}
|
||||
(tr "ds.history.pinned")]]
|
||||
(if (= @section :pinned)
|
||||
[:& history-pinned-list {:history history}]
|
||||
[:& history-list {:history history}])]]))
|
||||
|
||||
;; --- History Dialog
|
||||
|
||||
(mf/defc history-dialog
|
||||
[props]
|
||||
(let [history nil #_(mf/deref refs/history)
|
||||
version (:selected history)
|
||||
on-accept #(st/emit! udh/apply-selected)
|
||||
on-cancel #(st/emit! udh/deselect)]
|
||||
(when (or version (:deselecting history))
|
||||
[:div.message-version
|
||||
{:class (when (:deselecting history) "hide-message")}
|
||||
[:span (tr "history.alert-message" (or version "00"))
|
||||
[:div.message-action
|
||||
[:a.btn-transparent {:on-click on-accept} (tr "ds.accept")]
|
||||
[:a.btn-transparent {:on-click on-cancel} (tr "ds.cancel")]]]])))
|
||||
(mf/defc history-toolbox []
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
{:keys [items index]} (mf/deref workspace-undo)
|
||||
objects (mf/deref refs/workspace-page-objects)]
|
||||
[:div.history-toolbox
|
||||
[:div.history-toolbox-title "History"]
|
||||
(when (> (count items) 0)
|
||||
[:ul.undo-history
|
||||
[:*
|
||||
(when (or (nil? index) (>= index (count items))) [:hr.separator])
|
||||
(for [[idx-entry {:keys [redo-changes]}] (->> items (map-indexed vector) reverse)]
|
||||
[:*
|
||||
(when (= index idx-entry) [:hr.separator {:data-index index}])
|
||||
[:li.undo-entry {:key (str "entry-" idx-entry)}
|
||||
(for [[idx-change {:keys [type id operations]}] (map-indexed vector redo-changes)]
|
||||
[:div.undo-entry-change
|
||||
[:div.undo-entry-change-data (when type (str type)) " " (when id (str (get-in objects [id :name] (subs (str id) 0 8))))]
|
||||
(when operations
|
||||
[:div.undo-entry-change-data (str/join ", " (map (comp name :attr) operations))])])]])
|
||||
(when (= index -1) [:hr.separator])]])]))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue