Created
October 30, 2014 18:16
-
-
Save loganlinn/0c9108079ce87ec23c13 to your computer and use it in GitHub Desktop.
minimal time-travel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns qcon.core | |
(:require | |
[qcon.state :as state] | |
[qcon.time-travel :as time-travel] | |
[om.core :as om :include-macros true] | |
[om-tools.dom :as dom :include-macros true] | |
[om-tools.core :refer-macros [defcomponent]])) | |
(defcomponent compose-view | |
[pending-item owner {:keys [on-submit]}] | |
(render [_] | |
(dom/form | |
{:on-submit (comp (constantly false) on-submit)} | |
(dom/input | |
{:type :text | |
:value (:text pending-item "") | |
:placeholder "Add an item" | |
:on-change #(om/update! pending-item :text (.. % -target -value))}) | |
(dom/input {:type "submit" :value "Add"})))) | |
(defcomponent items-view [items owner] | |
(render [_] | |
(dom/ol | |
(for [item items] | |
(dom/li (:text item)))))) | |
(defcomponent app-view [app owner] | |
(render [_] | |
(dom/div | |
(om/build compose-view (:pending-item app) | |
{:opts | |
{:on-submit | |
#(om/transact! app nil state/submit-pending time-travel/undoable-txn)}}) | |
(dom/button {:on-click time-travel/undo! | |
:disabled (not (time-travel/can-undo?))} | |
"Undo") | |
(dom/button {:on-click time-travel/redo! | |
:disabled (not (time-travel/can-redo?))} | |
"Redo") | |
(om/build items-view (:items app))))) | |
(defn main [] | |
(om/root app-view state/app-state | |
{:target (. js/document (getElementById "app")) | |
:tx-listen time-travel/handle-transaction})) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns qcon.state) | |
(defn init-state [] | |
{:items [] | |
:pending-item {}}) | |
(defonce app-state (atom (init-state))) | |
(defn submit-pending | |
"Returns state after moving pending item to items" | |
[state] | |
(let [pending-item (:pending-item state)] | |
(-> state | |
(update-in [:items] conj pending-item) | |
(update-in [:pending-item] empty)))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns qcon.time-travel | |
(:require | |
[qcon.state :as state])) | |
(defonce app-history (atom [@state/app-state])) | |
(defonce app-future (atom [])) | |
(def undoable-txn ::undoable) | |
(defn can-undo? [] (> (count @app-history) 1)) | |
(defn can-redo? [] (> (count @app-future) 0)) | |
(defn push-history! [new-state] | |
(when (not= (last @app-history) new-state) | |
(swap! app-history conj new-state))) | |
(defn undo! [] | |
(when (can-undo?) | |
(swap! app-future conj (last @app-history)) | |
(swap! app-history pop) | |
(reset! state/app-state (last @app-history)))) | |
(defn redo! [] | |
(when (can-redo?) | |
(reset! state/app-state (last @app-future)) | |
(push-history! (last @app-future)) | |
(swap! app-future pop))) | |
(defn handle-transaction | |
[{:keys [tag new-state]}] | |
(when (= tag undoable-txn) | |
(reset! app-future []) | |
(push-history! new-state))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment