From 5715e11d8f79849b03057faaf6582cf661dcf4cc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sun, 31 Jul 2016 00:26:50 +0300 Subject: [PATCH] Initial work on proper undo/redu functionality. That is based in in-memmory queue of more detailed changes instead of relying on history log that is not pretty detailed and requires explcit user confirmation on each Ctrl+Z action that is counterintuitive. --- src/uxbox/main/data/undo.cljs | 47 ++++++++++++++++++++++++++++++++ src/uxbox/main/state.cljs | 1 + src/uxbox/main/ui/workspace.cljs | 8 ++++-- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 src/uxbox/main/data/undo.cljs diff --git a/src/uxbox/main/data/undo.cljs b/src/uxbox/main/data/undo.cljs new file mode 100644 index 000000000..d67e9486e --- /dev/null +++ b/src/uxbox/main/data/undo.cljs @@ -0,0 +1,47 @@ +;; 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) 2016 Andrey Antukh + +(ns uxbox.main.data.undo + (:require [cuerdas.core :as str] + [promesa.core :as p] + [beicon.core :as rx] + [lentes.core :as l] + [uxbox.util.rstore :as rs] + [uxbox.util.router :as r] + [uxbox.main.repo :as rp] + [uxbox.util.i18n :refer (tr)] + [uxbox.util.schema :as sc] + [uxbox.main.data.pages :as udp] + [uxbox.main.state :as st] + [uxbox.util.datetime :as dt] + [uxbox.util.data :refer (without-keys + replace-by-id + index-by)])) + +(defrecord SaveUndoEntry [id] + rs/UpdateEvent + (-apply-update [_ state] + (let [page (udp/pack-page state id)] + (update-in state [:undo id :stack] (fnil conj []) page))) + + rs/EffectEvent + (-apply-effect [_ state] + (let [undo (get-in state [:undo id])] + (println (pr-str undo))))) + +(defn watch-page-changes + "A function that starts watching for `IPageUpdate` + events emited to the global event stream and just + reacts on them emiting an other event that just + persists the state of the page in an undo stack." + [id] + (letfn [(on-value [] + (rs/emit! (->SaveUndoEntry id)))] + (as-> rs/stream $ + (rx/filter #(satisfies? udp/IPageUpdate %) $) + (rx/debounce 500 $) + (rx/on-next $ on-value)))) + diff --git a/src/uxbox/main/state.cljs b/src/uxbox/main/state.cljs index 0af91c134..705d98c8d 100644 --- a/src/uxbox/main/state.cljs +++ b/src/uxbox/main/state.cljs @@ -30,6 +30,7 @@ :route nil :auth (:uxbox/auth storage nil) :clipboard #queue [] + :undo {} :profile nil :workspace nil :shapes-by-id {} diff --git a/src/uxbox/main/ui/workspace.cljs b/src/uxbox/main/ui/workspace.cljs index f84b2447c..b04faa5d1 100644 --- a/src/uxbox/main/ui/workspace.cljs +++ b/src/uxbox/main/ui/workspace.cljs @@ -14,6 +14,7 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.data.pages :as udp] [uxbox.main.data.history :as udh] + [uxbox.main.data.undo :as udu] [uxbox.util.dom :as dom] [uxbox.main.geom.point :as gpt] [uxbox.util.data :refer (classnames)] @@ -47,6 +48,7 @@ sub1 (scroll/watch-scroll-interactions own) sub2 (udp/watch-page-changes pageid) sub3 (udh/watch-page-changes) + sub4 (udu/watch-page-changes pageid) dom (mx/ref-node own "workspace-canvas")] ;; Set initial scroll position @@ -56,7 +58,8 @@ (assoc own ::sub1 sub1 ::sub2 sub2 - ::sub3 sub3))) + ::sub3 sub3 + ::sub4 sub4))) (defn- workspace-will-unmount [own] @@ -64,7 +67,8 @@ (.close (::sub1 own)) (.close (::sub2 own)) (.close (::sub3 own)) - (dissoc own ::sub1 ::sub2 ::sub3)) + (.close (::sub4 own)) + (dissoc own ::sub1 ::sub2 ::sub3 ::sub4)) (defn- workspace-did-remount [old-state state]