From 4943a2df937074c16d201fb4c1d374251a158e35 Mon Sep 17 00:00:00 2001 From: Stefan Wagner Date: Fri, 15 May 2020 10:47:56 +0200 Subject: [PATCH] Switch to javascript version --- env/dev/clj/tales/middleware.clj | 22 ---- env/dev/clj/tales/repl.clj | 31 ----- env/dev/cljs/tales/cards.cljs | 17 --- env/dev/cljs/tales/dev.cljs | 9 -- env/prod/cljs/tales/prod.cljs | 7 - project.clj | 87 +------------ resources/public/css/site.css | 139 -------------------- resources/public/css/site.min.css | 1 - src/clj/tales/handler.clj | 2 - src/clj/tales/web.clj | 26 ---- src/cljs/tales/animation.cljs | 83 ------------ src/cljs/tales/core.cljs | 20 --- src/cljs/tales/db.cljs | 44 ------- src/cljs/tales/effects.cljs | 41 ------ src/cljs/tales/events/core.cljs | 15 --- src/cljs/tales/events/project.cljs | 97 -------------- src/cljs/tales/events/slide.cljs | 124 ------------------ src/cljs/tales/events/view.cljs | 104 --------------- src/cljs/tales/geometry.cljs | 61 --------- src/cljs/tales/image.cljs | 46 ------- src/cljs/tales/interceptors.cljs | 11 -- src/cljs/tales/keybind.cljs | 29 ----- src/cljs/tales/routes.cljs | 20 --- src/cljs/tales/subs/core.cljs | 19 --- src/cljs/tales/subs/project.cljs | 12 -- src/cljs/tales/subs/slide.cljs | 14 -- src/cljs/tales/subs/view.cljs | 95 -------------- src/cljs/tales/ticker.cljs | 48 ------- src/cljs/tales/util/async.cljs | 9 -- src/cljs/tales/util/css.cljs | 15 --- src/cljs/tales/util/dom.cljs | 27 ---- src/cljs/tales/util/drag.cljs | 30 ----- src/cljs/tales/util/events.cljs | 55 -------- src/cljs/tales/util/transform.cljs | 10 -- src/cljs/tales/views/core.cljs | 16 --- src/cljs/tales/views/editor.cljs | 112 ---------------- src/cljs/tales/views/loader.cljs | 52 -------- src/cljs/tales/views/presenter.cljs | 8 -- src/cljs/tales/views/preview.cljs | 79 ------------ src/cljs/tales/views/project.cljs | 43 ------- src/cljs/tales/views/slide.cljs | 71 ----------- src/cljs/tales/views/stage.cljs | 119 ----------------- test/cljs/tales/doo_runner.cljs | 16 --- test/cljs/tales/events/core_test.cljs | 14 -- test/cljs/tales/events/project_test.cljs | 148 ---------------------- test/cljs/tales/events/slide_test.cljs | 155 ----------------------- test/cljs/tales/events/view_test.cljs | 80 ------------ test/cljs/tales/geometry_test.cljs | 69 ---------- test/cljs/tales/helper.cljs | 20 --- test/cljs/tales/views_test.cljs | 26 ---- 50 files changed, 6 insertions(+), 2392 deletions(-) delete mode 100644 env/dev/clj/tales/middleware.clj delete mode 100644 env/dev/clj/tales/repl.clj delete mode 100644 env/dev/cljs/tales/cards.cljs delete mode 100644 env/dev/cljs/tales/dev.cljs delete mode 100644 env/prod/cljs/tales/prod.cljs delete mode 100644 resources/public/css/site.css delete mode 100644 resources/public/css/site.min.css delete mode 100644 src/cljs/tales/animation.cljs delete mode 100644 src/cljs/tales/core.cljs delete mode 100644 src/cljs/tales/db.cljs delete mode 100644 src/cljs/tales/effects.cljs delete mode 100644 src/cljs/tales/events/core.cljs delete mode 100644 src/cljs/tales/events/project.cljs delete mode 100644 src/cljs/tales/events/slide.cljs delete mode 100644 src/cljs/tales/events/view.cljs delete mode 100644 src/cljs/tales/geometry.cljs delete mode 100644 src/cljs/tales/image.cljs delete mode 100644 src/cljs/tales/interceptors.cljs delete mode 100644 src/cljs/tales/keybind.cljs delete mode 100644 src/cljs/tales/routes.cljs delete mode 100644 src/cljs/tales/subs/core.cljs delete mode 100644 src/cljs/tales/subs/project.cljs delete mode 100644 src/cljs/tales/subs/slide.cljs delete mode 100644 src/cljs/tales/subs/view.cljs delete mode 100644 src/cljs/tales/ticker.cljs delete mode 100644 src/cljs/tales/util/async.cljs delete mode 100644 src/cljs/tales/util/css.cljs delete mode 100644 src/cljs/tales/util/dom.cljs delete mode 100644 src/cljs/tales/util/drag.cljs delete mode 100644 src/cljs/tales/util/events.cljs delete mode 100644 src/cljs/tales/util/transform.cljs delete mode 100644 src/cljs/tales/views/core.cljs delete mode 100644 src/cljs/tales/views/editor.cljs delete mode 100644 src/cljs/tales/views/loader.cljs delete mode 100644 src/cljs/tales/views/presenter.cljs delete mode 100644 src/cljs/tales/views/preview.cljs delete mode 100644 src/cljs/tales/views/project.cljs delete mode 100644 src/cljs/tales/views/slide.cljs delete mode 100644 src/cljs/tales/views/stage.cljs delete mode 100644 test/cljs/tales/doo_runner.cljs delete mode 100644 test/cljs/tales/events/core_test.cljs delete mode 100644 test/cljs/tales/events/project_test.cljs delete mode 100644 test/cljs/tales/events/slide_test.cljs delete mode 100644 test/cljs/tales/events/view_test.cljs delete mode 100644 test/cljs/tales/geometry_test.cljs delete mode 100644 test/cljs/tales/helper.cljs delete mode 100644 test/cljs/tales/views_test.cljs diff --git a/env/dev/clj/tales/middleware.clj b/env/dev/clj/tales/middleware.clj deleted file mode 100644 index fcb2a9c..0000000 --- a/env/dev/clj/tales/middleware.clj +++ /dev/null @@ -1,22 +0,0 @@ -(ns tales.middleware - (:require [prone.middleware :refer [wrap-exceptions]] - [ring.middleware.defaults :refer - [api-defaults site-defaults wrap-defaults]] - [ring.middleware.json :refer [wrap-json-body wrap-json-response]] - [ring.middleware.multipart-params :refer [wrap-multipart-params]] - [ring.middleware.params :refer [wrap-params]] - [ring.middleware.reload :refer [wrap-reload]])) - -(defn wrap-web-middleware [handler] - (-> handler - (wrap-defaults site-defaults) - wrap-exceptions - wrap-reload)) - -(defn wrap-api-middleware [handler] - (-> handler - wrap-json-response - (wrap-defaults api-defaults) - (wrap-json-body {:keywords? true}) - wrap-exceptions - wrap-reload)) diff --git a/env/dev/clj/tales/repl.clj b/env/dev/clj/tales/repl.clj deleted file mode 100644 index 62ad72d..0000000 --- a/env/dev/clj/tales/repl.clj +++ /dev/null @@ -1,31 +0,0 @@ -(ns tales.repl - (:use figwheel-sidecar.repl-api) - (:require [tales.handler :refer [app]] - [ring.server.standalone :refer [serve]] - [ring.middleware - [file :refer [wrap-file]] - [content-type :refer [wrap-content-type]] - [not-modified :refer [wrap-not-modified]]])) - -(defonce server (atom nil)) - -(defn get-handler [] - (-> #'app - (wrap-file "resources") - wrap-content-type - wrap-not-modified)) - -(defn start-server - "used for starting the server in development mode from REPL" - [& [port]] - (let [port (if port (Integer/parseInt port) 3000)] - (reset! server - (serve (get-handler) - {:port port - :auto-reload? true - :join? false})) - (println (str "You can view the site at http://localhost:" port)))) - -(defn stop-server [] - (.stop @server) - (reset! server nil)) diff --git a/env/dev/cljs/tales/cards.cljs b/env/dev/cljs/tales/cards.cljs deleted file mode 100644 index 44709b1..0000000 --- a/env/dev/cljs/tales/cards.cljs +++ /dev/null @@ -1,17 +0,0 @@ -(ns tales.cards - (:require-macros [devcards.core :refer [defcard defcard-rg deftest]]) - (:require [reagent.core :as reagent :refer [atom]] - [tales.views.editor :as editor] - [tales.views.project :as project] - [devcards.core :as dc])) - -(defcard-rg editor-page-card - [editor/page]) - -(defcard-rg project-page-card - [project/page]) - -(reagent/render [:div] (.getElementById js/document "app")) - -;; remember to run 'lein figwheel devcards' and then browse to -;; http://localhost:3449/cards diff --git a/env/dev/cljs/tales/dev.cljs b/env/dev/cljs/tales/dev.cljs deleted file mode 100644 index c1dc2f2..0000000 --- a/env/dev/cljs/tales/dev.cljs +++ /dev/null @@ -1,9 +0,0 @@ -(ns ^:figwheel-no-load tales.dev - (:require [tales.core :as core] - [devtools.core :as devtools])) - -(devtools/install!) - -(enable-console-print!) - -(core/init!) diff --git a/env/prod/cljs/tales/prod.cljs b/env/prod/cljs/tales/prod.cljs deleted file mode 100644 index e5607ed..0000000 --- a/env/prod/cljs/tales/prod.cljs +++ /dev/null @@ -1,7 +0,0 @@ -(ns tales.prod - (:require [tales.core :as core])) - -;;ignore println statements in prod -(set! *print-fn* (fn [& _])) - -(core/init!) diff --git a/project.clj b/project.clj index bf4f6fc..76c787b 100644 --- a/project.clj +++ b/project.clj @@ -14,19 +14,9 @@ [hiccup "1.0.5"] [me.raynes/fs "1.4.6"] [yogthos/config "1.1.1"] - [org.clojure/clojurescript "1.10.339" :scope "provided"] - [reagent "0.8.1"] - [reagent-utils "0.3.1"] - [re-frame "0.10.6"] - [day8.re-frame/http-fx "0.1.6"] - [day8.re-frame/test "0.1.5"] - [secretary "1.2.3"] - [thi.ng/geom "1.0.0-RC3"] [venantius/accountant "0.2.4"]] - :plugins [[lein-asset-minifier "0.2.7" :exclusions [org.clojure/clojure]] - [lein-cljsbuild "1.1.7"] - [lein-environ "1.1.0"] + :plugins [[lein-environ "1.1.0"] [me.arrdem/lein-git-version "2.0.8"]] :git-version {:status-to-version @@ -50,83 +40,18 @@ :main tales.server :clean-targets ^{:protect false} [:target-path - [:cljsbuild :builds :app :compiler :output-dir] - [:cljsbuild :builds :app :compiler :output-to]] + [:builds :app :compiler :output-dir] + [:builds :app :compiler :output-to]] :source-paths ["src/clj" "src/cljc"] :test-paths ["spec/clj" "test/clj"] - :resource-paths ["resources" "target/cljsbuild"] - - :minify-assets {:assets {"resources/public/css/site.min.css" "resources/public/css/site.css"}} - - :cljsbuild {:builds {:min {:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"] - :compiler {:output-to "target/cljsbuild/public/js/app.js" - :output-dir "target/cljsbuild/public/js" - :source-map "target/cljsbuild/public/js/app.js.map" - :optimizations :advanced - :pretty-print false}} - :app {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"] - :figwheel {:on-jsload "tales.core/mount-root"} - :compiler {:main "tales.dev" - :asset-path "/js/out" - :output-to "target/cljsbuild/public/js/app.js" - :output-dir "target/cljsbuild/public/js/out" - :source-map true - :optimizations :none - :pretty-print true - :closure-defines {"re_frame.trace.trace_enabled_QMARK_" true} - :preloads [day8.re-frame-10x.preload]}} - :test {:source-paths ["src/cljs" "src/cljc" "test/cljs"] - :compiler {:main tales.doo-runner - :asset-path "/js/out" - :output-to "target/test.js" - :output-dir "target/cljstest/public/js/out" - :optimizations :none - :pretty-print true}} - :devcards {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"] - :figwheel {:devcards true} - :compiler {:main "tales.cards" - :asset-path "js/devcards_out" - :output-to "target/cljsbuild/public/js/app_devcards.js" - :output-dir "target/cljsbuild/public/js/devcards_out" - :source-map-timestamp true - :optimizations :none - :pretty-print true}}}} + :resource-paths ["resources"] :doo {:build "test" :alias {:default [:chrome]}} - :figwheel {:http-server-root "public" - :server-logfile false - :server-port 3449 - :nrepl-port 7002 - :nrepl-middleware ["cemerick.piggieback/wrap-cljs-repl"] - :css-dirs ["resources/public/css"] - :ring-handler tales.handler/app} - - - - :profiles {:dev {:repl-options {:init-ns tales.repl - :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]} - :dependencies [[binaryage/devtools "0.9.10"] - [ring/ring-mock "0.3.2"] - [ring/ring-devel "1.7.0"] - [prone "1.6.1"] - [figwheel-sidecar "0.5.17"] - [org.clojure/tools.nrepl "0.2.13"] - [com.cemerick/piggieback "0.2.2"] - [speclj "3.3.2"] - [devcards "0.2.6" :exclusions [cljsjs/react]] - [pjstadig/humane-test-output "0.8.3"] - [day8.re-frame/re-frame-10x "0.3.3"]] - :source-paths ["env/dev/clj"] - :plugins [[lein-figwheel "0.5.17"] - [lein-doo "0.1.10"]] - :injections [(require 'pjstadig.humane-test-output) - (pjstadig.humane-test-output/activate!)] - :env {:dev true}} - :uberjar {:source-paths ["env/prod/clj"] - :prep-tasks ["compile" ["cljsbuild" "once" "min"]] + :profiles {:uberjar {:source-paths ["env/prod/clj"] + :prep-tasks ["compile"] :env {:production true} :aot :all :omit-source true}}) diff --git a/resources/public/css/site.css b/resources/public/css/site.css deleted file mode 100644 index 5f647c1..0000000 --- a/resources/public/css/site.css +++ /dev/null @@ -1,139 +0,0 @@ -*, *:before, *:after { - box-sizing: border-box; -} - -html { - height: 100%; -} - -.body-container { - background-color: #f5f5f5; - color: #4d4d4d; - font-family: 'Helvetica Neue', Verdana, Helvetica, Arial, sans-serif; - font-weight: 300; - height: 100%; -} - -h1, h2, h3 { - font-weight: 300; -} - -a { - text-decoration: none; - color: #09f; -} - -a:hover { - text-decoration: underline; -} - -#app { - border-top: 1px solid transparent; - height: 100%; -} - -#projects { - max-width: 640px; - margin: 0 auto; -} - -#projects > header { - text-align: center; -} - -#projects ul { - list-style: none; - padding: 0; - height: 200px; - display: flex; - flex-direction: column; - flex-wrap: wrap; - overflow: auto; -} - -#projects ul > li { - display: block; -} - -#projects ul > li > a { - display: block; - padding: 10px; - text-decoration: none; -} - -#projects ul > li > a:hover { - background-color: #eaeaea; - text-decoration: none; -} - -input#new-project { - border: 1px solid #d9d9d9; - box-sizing: border-box; - font-size: 1.2em; - font-weight: inherit; - padding: 16px; - width: 100%; - margin: 24px 0; - -} - -input#new-project::placeholder { - color: #aaa; - text-align: center; -} - -#editor, #presenter { - display: flex; - flex-direction: column; - height: 100%; - max-height: 100%; -} - -#editor > header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 20px; -} - -#editor > main, #presenter > main { - width: 100%; - flex: 1; - display: flex; - flex-direction: row; - justify-content: center; - align-items: stretch; -} - -#editor > main > #workspace { - width: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -#editor > main > #navigator { - width: 100%; - height: 100%; -} - -.slide-preview-list { - display: flex; - flex-direction: row; - overflow: auto; - margin: 4px 2px; -} - -.slide-preview-list > .slide-preview-list-item { - box-sizing: content-box; - display: flex; - align-items: center; - justify-content: center; - margin: 0 2px; -} - -.slide-preview-list > .slide-preview-list-item:hover { - border-color: #3388ff !important; - cursor: pointer; -} diff --git a/resources/public/css/site.min.css b/resources/public/css/site.min.css deleted file mode 100644 index d245162..0000000 --- a/resources/public/css/site.min.css +++ /dev/null @@ -1 +0,0 @@ -*,*:before,*:after{box-sizing:border-box}html{height:100%}.body-container{background-color:#f5f5f5;color:#4d4d4d;font-family:'Helvetica Neue',Verdana,Helvetica,Arial,sans-serif;font-weight:300;height:100%}h1,h2,h3{font-weight:300}a{text-decoration:none;color:#09f}a:hover{text-decoration:underline}#app{border-top:1px solid transparent;height:100%}#projects{max-width:640px;margin:0 auto}#projects>header{text-align:center}#projects ul{list-style:none;padding:0;height:200px;display:flex;flex-direction:column;flex-wrap:wrap;overflow:auto}#projects ul>li{display:block}#projects ul>li>a{display:block;padding:10px;text-decoration:none}#projects ul>li>a:hover{background-color:#eaeaea;text-decoration:none}input#new-project{border:1px solid #d9d9d9;box-sizing:border-box;font-size:1.2em;font-weight:inherit;padding:16px;width:100%;margin:24px 0}input#new-project::placeholder{color:#aaa;text-align:center}#editor,#presenter{display:flex;flex-direction:column;height:100%;max-height:100%}#editor>header{display:flex;justify-content:space-between;align-items:center;padding:0 20px}#editor>main,#presenter>main{width:100%;flex:1;display:flex;flex-direction:row;justify-content:center;align-items:stretch}#editor>main>#workspace{width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center}#editor>main>#navigator{width:100%;height:100%}.slide-preview-list{display:flex;flex-direction:row;overflow:auto;margin:4px 2px}.slide-preview-list>.slide-preview-list-item{box-sizing:content-box;display:flex;align-items:center;justify-content:center;margin:0 2px}.slide-preview-list>.slide-preview-list-item:hover{border-color:#38f!important;cursor:pointer} \ No newline at end of file diff --git a/src/clj/tales/handler.clj b/src/clj/tales/handler.clj index 98fdd03..663f579 100644 --- a/src/clj/tales/handler.clj +++ b/src/clj/tales/handler.clj @@ -24,14 +24,12 @@ (wrap-web-middleware (routes (GET "/" [] (web/loading-page)) - (GET "/v2" [] (web/loading-page-v2)) (context "/editor/:slug" [slug] (GET "/" [] (web/loading-page)) (files "/" {:root (str (fs/file *project-dir* slug))})) (context "/presenter/:slug" [slug] (GET "/" [] (web/loading-page)) (files "/" {:root (str (fs/file *project-dir* slug))})) - (GET "/cards" [] (web/cards-page)) (resources "/") (not-found "Not Found")))) diff --git a/src/clj/tales/web.clj b/src/clj/tales/web.clj index 134a848..44f7c66 100644 --- a/src/clj/tales/web.clj +++ b/src/clj/tales/web.clj @@ -2,26 +2,7 @@ (:require [config.core :refer [env]] [hiccup.page :refer [include-js include-css html5]])) -(defn head [] - [:head - [:meta {:charset "utf-8"}] - [:meta {:name "viewport" - :content "width=device-width, initial-scale=1"}] - (include-css "/vendor/normalize/normalize.css") - (include-css (if (env :dev) "/css/site.css" "/css/site.min.css"))]) - -(defn assets [] - (include-js "/js/app.js")) - (defn loading-page [] - (html5 - (head) - [:body {:class "body-container"} - [:div#app - [:p "Please wait..."]] - (assets)])) - -(defn loading-page-v2 [] (html5 [:head [:meta {:charset "utf-8"}] @@ -33,10 +14,3 @@ [:div#app] (include-js "/js/tales.js") [:script "tales.init();"]])) - -(defn cards-page [] - (html5 - (head) - [:body - [:div#app] - (include-js "/js/app_devcards.js")])) diff --git a/src/cljs/tales/animation.cljs b/src/cljs/tales/animation.cljs deleted file mode 100644 index 53d0d9a..0000000 --- a/src/cljs/tales/animation.cljs +++ /dev/null @@ -1,83 +0,0 @@ -(ns tales.animation - (:require [thi.ng.geom.core :as g] - [thi.ng.geom.vector :as gv] - [thi.ng.math.core :as m])) - -(defn linear - "Linearly interpolates between `a` and `b` relative to `t` in `duration`." - [a b duration t] - (let [t (/ t duration) - c (- b a)] - (cond - (<= t 0) a - (>= t 1) b - :else (+ a (* c t))))) - -(def ^:private easings {:linear linear}) - -(defn create-anim-fn [a b duration easing] - "Creates a function `fn [t]` which returns a value for time `t` relative to - `a`, `b` and `duration`." - (if (fn? easing) - (easing a b duration) - (partial (get easings easing) a b duration))) - -(defn- cosh [x] (/ (+ (Math/pow Math/E x) (Math/pow Math/E (- x))) 2)) -(defn- sinh [x] (/ (- (Math/pow Math/E x) (Math/pow Math/E (- x))) 2)) -(defn- tanh [x] (/ (sinh x) (cosh x))) - -(defn- b [w0 w1 u1 rho i] - (let [w (if (= i 1) w1 w0) - n1 (- (Math/pow w1 2) (Math/pow w0 2)) - n2 (* (Math/pow -1 i) (Math/pow rho 4) (Math/pow u1 2)) - d (* 2 w u1 (Math/pow rho 2))] - (/ (+ n1 n2) d))) - -(defn- r [b] - (Math/log (- (Math/sqrt (+ (Math/pow b 2) 1)) b))) - -(defn- S [r0 r1 rho] - (/ (- r1 r0) rho)) - -(defn- S= [w0 w1 rho] - (/ (Math/abs (Math/log (/ w1 w0))) rho)) - -(defn- u [w0 r0 rho s] - (let [a (* w0 (cosh r0) (tanh (+ (* rho s) r0))) - b (* w0 (sinh r0))] - (/ (- a b) (Math/pow rho 2)))) - -(defn- w [w0 r0 rho s] - (/ (* w0 (cosh r0)) (cosh (+ (* rho s) r0)))) - -(defn- w= [w0 k rho s] - (* w0 (Math/exp (* k rho s)))) - -(defn smooth-efficient [c0 w0 c1 w1 V rho] - "Implementation of \"Smooth and efficient zooming and panning\", - Jarke J. van Wijk and Wim A. A. Nuij, TU Eindhoven, Netherlands." - (if (= c0 c1) - (let [S (S= w0 w1 rho) - duration (* 1000 S V) - tick-fn (fn [t] - (let [t (/ t 1000) - s (Math/min (* V t) S) - k (if (< w1 w0) -1 1) - ws (w= w0 k rho s)] - [c0 ws]))] - [duration tick-fn]) - (let [u1 (g/dist (gv/vec2 c0) c1) - b0 (b w0 w1 u1 rho 0) - b1 (b w0 w1 u1 rho 1) - r0 (r b0) - r1 (r b1) - S (S r0 r1 rho) - duration (* 1000 S V) - tick-fn (fn [t] - (let [t (/ t 1000) - s (Math/min (* V t) S) - us (u w0 r0 rho s) - ws (w w0 r0 rho s) - pos (m/mix (gv/vec2 c0) c1 (/ us u1))] - [pos ws]))] - [duration tick-fn]))) diff --git a/src/cljs/tales/core.cljs b/src/cljs/tales/core.cljs deleted file mode 100644 index 574c25b..0000000 --- a/src/cljs/tales/core.cljs +++ /dev/null @@ -1,20 +0,0 @@ -(ns tales.core - (:require [reagent.core :as reagent] - [re-frame.core :as rf :refer [dispatch dispatch-sync subscribe]] - [tales.effects] - [tales.events.core] - [tales.routes :as routes] - [tales.subs.core] - [tales.ticker] - [tales.keybind] - [tales.util.dom :as dom] - [tales.views.core :as views])) - -(defn mount-root [] - (rf/clear-subscription-cache!) - (reagent/render [views/main-page] (dom/element-by-id "app"))) - -(defn init! [] - (dispatch-sync [:initialise-db]) - (routes/init!) - (mount-root)) diff --git a/src/cljs/tales/db.cljs b/src/cljs/tales/db.cljs deleted file mode 100644 index e46d858..0000000 --- a/src/cljs/tales/db.cljs +++ /dev/null @@ -1,44 +0,0 @@ -(ns tales.db - (:require [cljs.spec.alpha :as s])) - -(defn- ^boolean real? - "Returns true if `x` is a real number" - [x] (and (number? x) (js/isFinite x))) - -(s/def ::vec2 (s/tuple real? real?)) -(s/def ::point ::vec2) - -(s/def ::position ::point) -(s/def ::scale (s/and real? pos?)) -(s/def ::camera (s/keys :req-un [::position ::scale])) - -(s/def ::size (s/nilable ::vec2)) -(s/def ::viewport (s/keys :req-un [::size])) - -(s/def ::db (s/keys :req-un [::camera ::viewport])) - -(def default-db - {:projects {} - :project nil - :active-page nil - :active-slide nil - :camera {:position [0 0] - :scale 1} - :viewport {:size nil} - :tick {:handlers {} :paused? true} - :keybindings {:editor {"Enter" :slide/fly-to - " " :slide/next - "ArrowLeft" :slide/prev - "ArrowRight" :slide/next - "PageUp" :slide/prev - "PageDown" :slide/next - "Ctrl+ArrowLeft" :slide/swap-prev - "Ctrl+ArrowRight" :slide/swap-next - "Meta+ArrowLeft" :slide/swap-prev - "Meta+ArrowRight" :slide/swap-next - "Delete" :slide/delete} - :presenter {" " :slide/fly-to-next - "ArrowLeft" :slide/fly-to-prev - "ArrowRight" :slide/fly-to-next - "PageUp" :slide/fly-to-prev - "PageDown" :slide/fly-to-next}}}) diff --git a/src/cljs/tales/effects.cljs b/src/cljs/tales/effects.cljs deleted file mode 100644 index 25273d8..0000000 --- a/src/cljs/tales/effects.cljs +++ /dev/null @@ -1,41 +0,0 @@ -(ns tales.effects - (:require [accountant.core :as accountant] - [re-frame.core :refer [dispatch reg-fx]] - [re-frame.db :refer [app-db]] - [tales.animation :as anim :refer [easings]] - [tales.image :as image] - [tales.ticker :as ticker :refer [PTickHandler]])) - -(reg-fx :navigate - (fn [url] - (accountant/navigate! url))) - -(reg-fx :determine-image-dimensions - (fn [{project :project file :file}] - (image/dimensions file - #(dispatch [:project/update (assoc project :dimensions %)])))) - -(defn ^:private now [] - (.getTime (js/Date.))) - -(defn animate-db [{:keys [id path from to duration easing] - :or {easing :linear}}] - (if id - (let [anim-fn (anim/create-anim-fn from to duration easing) - handler (reify PTickHandler - (init-state [_ db] - (assoc-in db [:animation id] {:start (now)})) - (tick [_ db] - (let [start (get-in db [:animation id :start]) - t (- (now) start)] - (when (>= t duration) (ticker/remove-handler id)) - (assoc-in db (flatten path) (anim-fn t)))))] - (ticker/add-handler id handler)) - (.error js/console :error "animate: no animation id provided."))) - -(reg-fx - :animate-db - (fn [value] - (let [seq-animation-maps (if (sequential? value) value [value])] - (doseq [animation-map seq-animation-maps] - (animate-db animation-map))))) diff --git a/src/cljs/tales/events/core.cljs b/src/cljs/tales/events/core.cljs deleted file mode 100644 index c6a8cd5..0000000 --- a/src/cljs/tales/events/core.cljs +++ /dev/null @@ -1,15 +0,0 @@ -(ns tales.events.core - (:require [day8.re-frame.http-fx] - [re-frame.core :refer [reg-event-db reg-event-fx trim-v]] - [tales.db :as db] - [tales.events.project] - [tales.events.slide] - [tales.events.view])) - -(reg-event-db :initialise-db - (fn [] db/default-db)) - -(reg-event-db :activate-page - [trim-v] - (fn [db [active-page]] - (assoc db :active-page active-page))) diff --git a/src/cljs/tales/events/project.cljs b/src/cljs/tales/events/project.cljs deleted file mode 100644 index 3c23a55..0000000 --- a/src/cljs/tales/events/project.cljs +++ /dev/null @@ -1,97 +0,0 @@ -(ns tales.events.project - (:require [ajax.core :as ajax] - [re-frame.core :refer [reg-event-db reg-event-fx trim-v]] - [tales.routes :refer [editor-path]])) - - -(defn open [{db :db} [slug]] - {:db (assoc-in db [:loading? :project] true) - :http-xhrio {:method :get - :uri (str "/api/tales/" slug) - :format (ajax/json-request-format) - :response-format (ajax/json-response-format {:keywords? true}) - :on-success [:project/open-success] - :on-failure [:api-request-error :project]}}) - -(defn open-success [{:keys [db]} [response]] - (let [project (js->clj response)] - {:db (-> db - (assoc-in [:loading? :project] false) - (dissoc :errors) - (assoc-in [:projects (:slug project)] project) - (assoc :project project))})) - -(defn get-all [{db :db}] - {:db (assoc-in db [:loading? :projects] true) - :http-xhrio {:method :get - :uri "/api/tales/" - :format (ajax/json-request-format) - :response-format (ajax/json-response-format {:keywords? true}) - :on-success [:project/get-all-success] - :on-failure [:api-request-error :projects]}}) - -(defn get-all-success [db [response]] - (let [projects (js->clj response) - slugs (map #(:slug %) projects)] - (-> db - (assoc-in [:loading? :projects] false) - (dissoc :errors) - (assoc :projects (zipmap slugs projects))))) - -(defn add [{db :db} [project]] - {:db (assoc-in db [:loading? :project] true) - :http-xhrio {:method :post - :uri "/api/tales/" - :params project - :format (ajax/json-request-format) - :response-format (ajax/json-response-format {:keywords? true}) - :on-success [:project/change-success] - :on-failure [:api-request-error :project]}}) - -(defn change [{db :db} [project]] - {:db (assoc-in db [:loading? :project] true) - :http-xhrio {:method :put - :uri (str "/api/tales/" (:slug project)) - :params project - :format (ajax/json-request-format) - :response-format (ajax/json-response-format {:keywords? true}) - :on-success [:project/change-success] - :on-failure [:api-request-error :project]}}) - -(defn update-image [{db :db} [{project :project file :file}]] - {:db (assoc-in db [:loading? :project] true) - :determine-image-dimensions {:project project :file file} - :http-xhrio {:method :put - :uri (str "/api/tales/" (:slug project) "/image") - :body file - :headers {:content-type (.-type file)} - :response-format (ajax/json-response-format {:keywords? true}) - :on-success [:project/change-success] - :on-failure [:api-request-error :project]}}) - -(defn change-success [{:keys [db]} [response]] - (let [project (js->clj response)] - {:db (-> db - (assoc-in [:loading? :project] false) - (dissoc :errors) - (assoc-in [:projects (:slug project)] project)) - :navigate (editor-path {:slug (:slug project)})})) - -(defn api-request-error [{:keys [db]} [request-type response]] - (let [errors (get-in response [:response :errors])] - {:db (assoc-in db [:errors request-type] errors) - :dispatch [:complete-request request-type]})) - -(defn complete-request [db [request-type]] - (assoc-in db [:loading? request-type] false)) - -(reg-event-fx :project/open [trim-v] open) -(reg-event-fx :project/open-success [trim-v] open-success) -(reg-event-fx :project/get-all get-all) -(reg-event-db :project/get-all-success [trim-v] get-all-success) -(reg-event-fx :project/add [trim-v] add) -(reg-event-fx :project/update [trim-v] change) -(reg-event-fx :project/update-image [trim-v] update-image) -(reg-event-fx :project/change-success [trim-v] change-success) -(reg-event-fx :api-request-error [trim-v] api-request-error) -(reg-event-db :complete-request [trim-v] complete-request) \ No newline at end of file diff --git a/src/cljs/tales/events/slide.cljs b/src/cljs/tales/events/slide.cljs deleted file mode 100644 index ff33b2e..0000000 --- a/src/cljs/tales/events/slide.cljs +++ /dev/null @@ -1,124 +0,0 @@ -(ns tales.events.slide - (:require [re-frame.core :refer [reg-event-db reg-event-fx trim-v]])) - -(defn- drop-nth [n coll] - (concat - (take n coll) - (drop (inc n) coll))) - -(defn- swap [v i1 i2] - (assoc v i2 (v i1) i1 (v i2))) - -(defn next-slide [slides n] - (if n - (mod (inc n) (count slides)) - 0)) - -(defn prev-slide [slides n] - (if n - (mod (dec n) (count slides)) - (dec (count slides)))) - -(reg-event-fx :slide/add - [trim-v] - (fn [{db :db} [slide]] - (let [project (:project db) - slides (:slides project)] - {:dispatch [:project/update - (assoc project - :slides (conj slides slide))]}))) - -(reg-event-fx :slide/update - [trim-v] - (fn [{db :db} [slide]] - (let [project (:project db) - slides (:slides project) - idx (:active-slide db)] - (if-not (nil? idx) - {:dispatch [:project/update - (assoc project - :slides (assoc slides idx slide))]})))) - -(reg-event-fx :slide/delete - [trim-v] - (fn [{db :db} [idx]] - (let [project (:project db) - slides (:slides project) - idx (or idx (:active-slide db))] - (if-not (nil? idx) - {:dispatch [:project/update - (assoc project - :slides (drop-nth idx slides))]})))) - -(reg-event-db :slide/activate - [trim-v] - (fn [db [idx]] - (assoc db :active-slide idx))) - -(reg-event-fx :slide/next - [trim-v] - (fn [{db :db} _] - (let [project (:project db) - slides (:slides project) - idx (:active-slide db)] - {:dispatch [:slide/activate (next-slide slides idx)]}))) - -(reg-event-fx :slide/prev - [trim-v] - (fn [{db :db} _] - (let [project (:project db) - slides (:slides project) - idx (:active-slide db)] - {:dispatch [:slide/activate (prev-slide slides idx)]}))) - -(reg-event-fx :slide/swap - [trim-v] - (fn [{db :db} [idx1 idx2]] - (let [project (:project db) - slides (:slides project) - slides-count (- (count slides) 1)] - (if (and (<= 0 idx1 slides-count) (<= 0 idx2 slides-count)) - {:db (assoc db :active-slide idx2) - :dispatch [:project/update - (assoc-in project [:slides] - (swap slides idx1 idx2))]})))) - -(reg-event-fx :slide/swap-next - [trim-v] - (fn [{db :db} [idx]] - (let [idx (or idx (:active-slide db))] - {:dispatch [:slide/swap idx (+ idx 1)]}))) - -(reg-event-fx :slide/swap-prev - [trim-v] - (fn [{db :db} [idx]] - (let [idx (or idx (:active-slide db))] - {:dispatch [:slide/swap idx (- idx 1)]}))) - -(reg-event-fx :slide/fly-to - [trim-v] - (fn [{db :db} _] - (if-let [idx (:active-slide db)] - (let [project (:project db) - slides (:slides project)] - {:dispatch [:camera/fly-to-rect (get-in slides [idx :rect])]})))) - -(reg-event-fx :slide/fly-to-next - [trim-v] - (fn [{db :db} _] - (let [project (:project db) - slides (:slides project) - idx (:active-slide db) - next-idx (next-slide slides idx)] - {:db (assoc db :active-slide next-idx) - :dispatch [:camera/fly-to-rect (get-in slides [next-idx :rect])]}))) - -(reg-event-fx :slide/fly-to-prev - [trim-v] - (fn [{db :db} _] - (let [project (:project db) - slides (:slides project) - idx (:active-slide db) - prev-idx (prev-slide slides idx)] - {:db (assoc db :active-slide prev-idx) - :dispatch [:camera/fly-to-rect (get-in slides [prev-idx :rect])]}))) diff --git a/src/cljs/tales/events/view.cljs b/src/cljs/tales/events/view.cljs deleted file mode 100644 index 9fa640a..0000000 --- a/src/cljs/tales/events/view.cljs +++ /dev/null @@ -1,104 +0,0 @@ -(ns tales.events.view - (:require [re-frame.core :refer [reg-event-db reg-event-fx trim-v]] - [tales.animation :as anim] - [tales.interceptors :refer [check-db-interceptor]] - [tales.geometry :as geometry] - [thi.ng.math.core :as m] - [thi.ng.geom.core :as g] - [thi.ng.geom.matrix :as gm] - [thi.ng.geom.vector :as gv])) - -(reg-event-db :viewport/set-size - [check-db-interceptor trim-v] - (fn [db [size]] - (assoc-in db [:viewport :size] size))) - -(reg-event-fx :camera/setup - [trim-v] - (fn [{db :db} _] - (let [poster-dimensions (get-in db [:project :dimensions])] - {:dispatch [:camera/fit-rect poster-dimensions]}))) - -(reg-event-db :camera/destroy - [check-db-interceptor trim-v] - (fn [db _] - (dissoc db :camera))) - -(reg-event-db :camera/move-to - [check-db-interceptor trim-v] - (fn [db [position]] - (assoc-in db [:camera :position] position))) - -(reg-event-db :camera/set-scale - [check-db-interceptor trim-v] - (fn [db [scale position]] - (let [position (or position [0 0]) - old-position (get-in db [:camera :position]) - old-scale (get-in db [:camera :scale]) - s (/ scale old-scale) - moved-by-scale (-> (gv/vec2 position) - (m/- (m/* (gv/vec2 position) s))) - [x y] (-> (gv/vec2 old-position) - (m/* s) - (m/+ moved-by-scale))] - (-> db - (assoc-in [:camera :position] [x y]) - (assoc-in [:camera :scale] scale))))) - -(reg-event-fx :camera/zoom-in - [trim-v] - (fn [{db :db} [position]] - (let [scale (get-in db [:camera :scale])] - {:dispatch [:camera/set-scale (/ scale 2) position]}))) - -(reg-event-fx :camera/zoom-out - [trim-v] - (fn [{db :db} [position]] - (let [scale (get-in db [:camera :scale])] - {:dispatch [:camera/set-scale (* scale 2) position]}))) - -(defn- rect-scale [[aw ah] viewport-size] - (let [scale (-> {:size viewport-size} - (gm/ortho) - (g/transform-vector (gv/vec3 [aw ah] 0)) - (m/div 2))] - (apply Math/max scale))) - -(reg-event-db :camera/fit-rect - [check-db-interceptor trim-v] - (fn [db [rect]] - (let [viewport-size (get-in db [:viewport :size]) - rect-center (geometry/rect-center rect) - rect [(:width rect) (:height rect)] - new-scale (rect-scale rect viewport-size)] - (-> db - (assoc-in [:camera :position] [(:x rect-center) (:y rect-center)]) - (assoc-in [:camera :scale] new-scale))))) - -(reg-event-fx :camera/fly-to-rect - [check-db-interceptor trim-v] - (fn [{db :db} [rect]] - (let [viewport-size (get-in db [:viewport :size]) - rect-center (geometry/rect-center rect) - rect [(:width rect) (:height rect)] - c0 (get-in db [:camera :position]) - w0 (get-in db [:camera :scale]) - c1 [(:x rect-center) (:y rect-center)] - w1 (rect-scale rect viewport-size) - [duration easing] (anim/smooth-efficient c0 w0 c1 w1 1 1.42)] - {:animate-db [{:id :camera/position - :path [:camera :position] - :from c0 - :to c1 - :duration duration - :easing #(fn [t] - (let [[pos _] (easing t)] - pos))} - {:id :camera/scale - :path [:camera :scale] - :from w0 - :to w1 - :duration duration - :easing #(fn [t] - (let [[_ scale] (easing t)] - scale))}]}))) diff --git a/src/cljs/tales/geometry.cljs b/src/cljs/tales/geometry.cljs deleted file mode 100644 index 93f5ca2..0000000 --- a/src/cljs/tales/geometry.cljs +++ /dev/null @@ -1,61 +0,0 @@ -(ns tales.geometry) - -(defn zoom->scale [zoom] - (Math/pow 2 zoom)) - -(defn scale->zoom [scale] - (/ (Math/log scale) Math/LN2)) - -(defn scale [point scale] - {:x (/ (:x point) scale) - :y (/ (:y point) scale)}) - -(defn unscale [point scale] - {:x (* (:x point) scale) - :y (* (:y point) scale)}) - -(defn add-points [p1 p2] - {:x (+ (:x p2) (:x p1)) - :y (+ (:y p2) (:y p1))}) - -(defn distance [p1 p2] - {:x (- (:x p2) (:x p1)) - :y (- (:y p2) (:y p1))}) - -(defn rect-center [rect] - {:x (+ (:x rect) (/ (:width rect) 2)) - :y (+ (:y rect) (/ (:height rect) 2))}) - -(defn move-point [point dx dy] - {:x (+ (:x point) dx) - :y (+ (:y point) dy)}) - -(defn move-rect [rect dx dy] - (merge rect (move-point rect dx dy))) - -(defn normalize-rect [rect] - {:x (if (< (:width rect) 0) (+ (:x rect) (:width rect)) (:x rect)) - :y (if (< (:height rect) 0) (+ (:y rect) (:height rect)) (:y rect)) - :width (Math/abs (:width rect)) - :height (Math/abs (:height rect))}) - -(defn resize-rect [rect corner dx dy] - (let [delta (case corner - :top-left {:dx dx :dy dy :dwidth (- dx) :dheight (- dy)} - :top {:dx 0 :dy dy :dwidth 0 :dheight (- dy)} - :top-right {:dx 0 :dy dy :dwidth (+ dx) :dheight (- dy)} - :right {:dx 0 :dy 0 :dwidth (+ dx) :dheight 0} - :bottom-right {:dx 0 :dy 0 :dwidth (+ dx) :dheight (+ dy)} - :bottom {:dx 0 :dy 0 :dwidth 0 :dheight (+ dy)} - :bottom-left {:dx dx :dy 0 :dwidth (- dx) :dheight (+ dy)} - :left {:dx dx :dy 0 :dwidth (- dx) :dheight 0})] - (normalize-rect - {:x (+ (:x rect) (:dx delta)) - :y (+ (:y rect) (:dy delta)) - :width (+ (:width rect) (:dwidth delta)) - :height (+ (:height rect) (:dheight delta))}))) - -(defn rect-scale [rect target] - (Math/min - (/ (:width rect) (:width target)) - (/ (:height rect) (:height target)))) \ No newline at end of file diff --git a/src/cljs/tales/image.cljs b/src/cljs/tales/image.cljs deleted file mode 100644 index 7f6ae47..0000000 --- a/src/cljs/tales/image.cljs +++ /dev/null @@ -1,46 +0,0 @@ -(ns tales.image - (:require [clojure.core.async :refer [ (js/DOMParser.) - (.parseFromString - (-> % .-target .-result) - "image/svg+xml") - (.getElementsByTagName "svg") - (aget 0) - cb)) - (.readAsText reader file))) - -(defn- with-image [file cb] - (let [reader (js/FileReader.) - image (js/Image.)] - (set! (.-onload reader) #(set! (.-src image) (-> % .-target .-result))) - (set! (.-onload image) #(cb image)) - (.readAsDataURL reader file))) - -(defn dimensions [file cb] - (let [type (.-type file)] - (case type - "image/svg+xml" (with-svg file #(cb (svg-dimensions %))) - (with-image file #(cb (image-dimensions %)))))) diff --git a/src/cljs/tales/interceptors.cljs b/src/cljs/tales/interceptors.cljs deleted file mode 100644 index 1c02ef9..0000000 --- a/src/cljs/tales/interceptors.cljs +++ /dev/null @@ -1,11 +0,0 @@ -(ns tales.interceptors - (:require [cljs.spec.alpha :as s] - [re-frame.core :refer [->interceptor after]])) - -(defn- check-and-throw - "Throws an exception if `db` doesn't match the Spec `a-spec`." - [a-spec db] - (when-not (s/valid? a-spec db) - (throw (ex-info (str "spec check failed: " (s/explain-str a-spec db)) {})))) - -(def check-db-interceptor (after (partial check-and-throw :tales.db/db))) diff --git a/src/cljs/tales/keybind.cljs b/src/cljs/tales/keybind.cljs deleted file mode 100644 index 0f63d8a..0000000 --- a/src/cljs/tales/keybind.cljs +++ /dev/null @@ -1,29 +0,0 @@ -(ns tales.keybind - (:require [clojure.string :as string] - [re-frame.core :refer [dispatch reg-event-fx trim-v]] - [tales.util.events :as events])) - -(defn cord [ev] - (let [key (events/key-val ev) - ctrl-key? (events/ctrl-key? ev) - alt-key? (events/alt-key? ev) - shift-key? (events/shift-key? ev) - meta-key? (events/meta-key? ev)] - (string/join "+" (filter some? [(if ctrl-key? "Ctrl") - (if alt-key? "Alt") - (if shift-key? "Shift") - (if meta-key? "Meta") - key])))) - -(reg-event-fx :key/down - [trim-v] - (fn [{db :db} [cord]] - (let [page (:active-page db) - action (get-in db [:keybindings page cord])] - (when action - (if (coll? action) - {:dispatch-n (vec (map #(vec [%]) action))} - {:dispatch [action]}))))) - -(defonce keydown-handler - (events/on "keydown" #(dispatch [:key/down (cord %)]))) diff --git a/src/cljs/tales/routes.cljs b/src/cljs/tales/routes.cljs deleted file mode 100644 index 88677fd..0000000 --- a/src/cljs/tales/routes.cljs +++ /dev/null @@ -1,20 +0,0 @@ -(ns tales.routes - (:require [re-frame.core :refer [dispatch dispatch-sync]] - [secretary.core :as secretary :include-macros true] - [accountant.core :as accountant])) - -(secretary/defroute home-path "/" [] - (dispatch [:activate-page :home])) - -(secretary/defroute editor-path "/editor/:slug/" [slug] - (do (dispatch [:activate-page :editor]) - (dispatch [:project/open slug]))) - -(secretary/defroute presenter-path "/presenter/:slug/" [slug] - (do (dispatch [:activate-page :presenter]) - (dispatch [:project/open slug]))) - -(defn init! [] - (accountant/configure-navigation! {:nav-handler #(secretary/dispatch! %) - :path-exists? #(secretary/locate-route %)}) - (accountant/dispatch-current!)) diff --git a/src/cljs/tales/subs/core.cljs b/src/cljs/tales/subs/core.cljs deleted file mode 100644 index cf279fd..0000000 --- a/src/cljs/tales/subs/core.cljs +++ /dev/null @@ -1,19 +0,0 @@ -(ns tales.subs.core - (:require [re-frame.core :refer [reg-sub reg-sub-raw]] - [tales.subs.project] - [tales.subs.slide] - [tales.subs.view])) - -(reg-sub :active-page - (fn [db _] - (:active-page db))) - -(reg-sub :poster/dimensions - :<- [:project] - (fn [project _] - (:dimensions project))) - -(reg-sub :poster/file-path - :<- [:project] - (fn [project _] - (:file-path project))) diff --git a/src/cljs/tales/subs/project.cljs b/src/cljs/tales/subs/project.cljs deleted file mode 100644 index f800f64..0000000 --- a/src/cljs/tales/subs/project.cljs +++ /dev/null @@ -1,12 +0,0 @@ -(ns tales.subs.project - (:require [re-frame.core :refer [dispatch reg-sub reg-sub-raw]])) - -(reg-sub-raw :project/all - (fn [db _] - (dispatch [:project/get-all]) - (reagent.ratom/make-reaction - (fn [] (:projects @db))))) - -(reg-sub :project - (fn [db _] - (get db :project))) \ No newline at end of file diff --git a/src/cljs/tales/subs/slide.cljs b/src/cljs/tales/subs/slide.cljs deleted file mode 100644 index 8e9a673..0000000 --- a/src/cljs/tales/subs/slide.cljs +++ /dev/null @@ -1,14 +0,0 @@ -(ns tales.subs.slide - (:require [re-frame.core :refer [reg-sub]])) - -(reg-sub :slides - :<- [:project] - (fn [project _] - (doall - (map-indexed - (fn [index slide] (assoc slide :index index)) - (:slides project))))) - -(reg-sub :slide/active - (fn [db _] - (:active-slide db))) \ No newline at end of file diff --git a/src/cljs/tales/subs/view.cljs b/src/cljs/tales/subs/view.cljs deleted file mode 100644 index a980268..0000000 --- a/src/cljs/tales/subs/view.cljs +++ /dev/null @@ -1,95 +0,0 @@ -(ns tales.subs.view - (:require-macros [reagent.ratom :as ratom]) - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch reg-sub reg-sub-raw]] - [thi.ng.math.core :as m] - [thi.ng.geom.core :as g] - [thi.ng.geom.matrix :as gm] - [thi.ng.geom.vector :as gv])) - -(reg-sub-raw :viewport/ready? - (fn [db _] - (let [had-size? (r/atom false) - setup-camera #(dispatch [:camera/setup]) - destroy-camera #(dispatch [:camera/destroy]) - has? (fn [key m] (not (nil? (key m))))] - (ratom/reaction - (let [viewport (get @db :viewport) - camera (get @db :camera) - has-size? (has? :size viewport) - ready? (and has-size? - (has? :position camera) - (has? :scale camera))] - (if @had-size? - (when-not has-size? (destroy-camera)) - (when has-size? (setup-camera))) - (reset! had-size? has-size?) - ready?))))) - -(reg-sub :viewport/size - (fn [db _] - (get-in db [:viewport :size] [1 1]))) - -(reg-sub :viewport/view-rect - :<- [:viewport/size] - (fn [size _] - {:pos [0 0] - :size size})) - -(reg-sub :viewport/aspect-ratio - :<- [:viewport/size] - (fn [[width height] _] - (/ width height))) - -(reg-sub :viewport/scale - :<- [:matrix/mvp] - :<- [:matrix/viewport] - (fn [[m1 m2] _] - (-> (gv/vec3 (nth m2 0) (nth m2 1) (nth m2 2)) - (m/* (gv/vec3 (nth m1 0) (nth m1 1) (nth m1 2))) - (m/mag)))) - -(reg-sub :camera/position - (fn [db _] - "The position of the camera in world space." - (get-in db [:camera :position]))) - -(reg-sub :camera/scale - (fn [db _] - "The scale of the camera in world space. A smaller value shrinks the view - of the camera and therefore magnifies the resulting view." - (get-in db [:camera :scale]))) - -(reg-sub :matrix/camera - :<- [:camera/position] - :<- [:camera/scale] - (fn [[position scale] _] - "Matrix to position the camera in the world." - (-> gm/M44 - (g/translate position) - (g/scale [scale scale 1])))) - -(reg-sub :matrix/view - :<- [:matrix/camera] - (fn [camera-matrix _] - "Matrix to convert from world coordinates to eye coordinates." - (m/invert camera-matrix))) - -(reg-sub :matrix/projection - :<- [:viewport/aspect-ratio] - (fn [a _] - "Matrix to convert from eye coordinates to clip coordinates." - (gm/ortho (- a) -1 a 1 -1 1))) - -(reg-sub :matrix/mvp - :<- [:matrix/view] - :<- [:matrix/projection] - (fn [[view-matrix projection-matrix] _] - "Combined matrix to convert from model coordinates to clip coordinates." - (m/* projection-matrix view-matrix))) - -(reg-sub :matrix/viewport - :<- [:viewport/size] - (fn [[width height] _] - "Combined matrix to convert from model coordinates to screen coordinates." - (gm/viewport-matrix width height))) diff --git a/src/cljs/tales/ticker.cljs b/src/cljs/tales/ticker.cljs deleted file mode 100644 index 0cbbcab..0000000 --- a/src/cljs/tales/ticker.cljs +++ /dev/null @@ -1,48 +0,0 @@ -(ns tales.ticker - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch reg-event-db trim-v]])) - -(defprotocol PTickHandler - (init-state [_ db] - "Called during :add-tick-handlers event handling. Must return updated db.") - (tick [_ db] - "Called at each tick with current app-db. Must return updated db.")) - -(defn- re-trigger-ticker - "Dispatches :next-tick event at next redraw cycle." - [] (r/next-tick (fn [] (dispatch [:next-tick])))) - -(defn add-handler [id handler] - (dispatch [:add-tick-handlers {id handler}])) - -(defn remove-handler [id] - (dispatch [:remove-tick-handlers [id]])) - -(reg-event-db :add-tick-handlers - [trim-v] - (fn [db [handlers]] - (let [db (reduce-kv - (fn [db _ handler] (init-state handler db)) - (update-in db [:tick :handlers] merge handlers) - handlers) - paused? (= (count (get-in db [:tick :handlers])) 0)] - (when-not paused? (re-trigger-ticker)) - (assoc-in db [:tick :paused?] paused?)))) - -(reg-event-db :remove-tick-handlers - [trim-v] - (fn [{ticker :tick :as db} [ids]] - (let [handlers (apply dissoc (:handlers ticker) ids)] - (-> db - (assoc-in [:tick :handlers] handlers) - (assoc-in [:tick :paused?] (= (count handlers) 0)))))) - -(reg-event-db :next-tick - [trim-v] - (fn [{ticker :tick :as db} _] - (if-not (:paused? ticker) - (do (re-trigger-ticker) - (reduce-kv - (fn [db _ handler] (tick handler db)) - db (:handlers ticker))) - db))) diff --git a/src/cljs/tales/util/async.cljs b/src/cljs/tales/util/async.cljs deleted file mode 100644 index 5d1c9f6..0000000 --- a/src/cljs/tales/util/async.cljs +++ /dev/null @@ -1,9 +0,0 @@ -(ns tales.util.async - (:import [goog.async Debouncer] - [goog.async Throttle])) - -(defn debounce [f interval] - "Call `f` exactly once for any number of repeatedly calls so long as it is - called less than `interval` apart (in milliseconds)." - (let [debouncer (Debouncer. f interval)] - (fn [& args] (.apply (.-fire debouncer) debouncer (to-array args))))) \ No newline at end of file diff --git a/src/cljs/tales/util/css.cljs b/src/cljs/tales/util/css.cljs deleted file mode 100644 index f3e8b44..0000000 --- a/src/cljs/tales/util/css.cljs +++ /dev/null @@ -1,15 +0,0 @@ -(ns tales.util.css) - -(defn transform-matrix - ([[m00 m01 m02 m10 m11 m12]] - (transform-matrix m00 m10 m01 m11 m02 m12)) - ([m00 m10 m01 m11 m02 m12] - (str "matrix(" m00 "," m10 "," m01 "," m11 "," m02 "," m12 ")"))) - -(defn transform-matrix3d - ([[m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33]] - (str "matrix3d(" - m00 "," m01 "," m02 "," m03 "," - m10 "," m11 "," m12 "," m13 "," - m20 "," m21 "," m22 "," m23 "," - m30 "," m31 "," m32 "," m33 ")"))) diff --git a/src/cljs/tales/util/dom.cljs b/src/cljs/tales/util/dom.cljs deleted file mode 100644 index b263470..0000000 --- a/src/cljs/tales/util/dom.cljs +++ /dev/null @@ -1,27 +0,0 @@ -(ns tales.util.dom) - -(defn element-by-id [id] - "Returns the element whose id property matches the provided `id`." - (.getElementById js/document id)) - -(defn bounding-rect [el] - "Returns the bounding client rect of `el`." - (.getBoundingClientRect el)) - -(defn size [el] - "Provides the inner size of `el` in pixels." - (let [rect (bounding-rect el)] - [(.-width rect) (.-height rect)])) - -(defn width [el] - "Provides the inner width of `el` in pixels." - (first (size el))) - -(defn height [el] - "Provides the inner height of `el` in pixels." - (second (size el))) - -(defn offset [el] - "Provides the position of `el` relative to the viewport." - (let [rect (bounding-rect el)] - {:x (.-left rect) :y (.-top rect)})) \ No newline at end of file diff --git a/src/cljs/tales/util/drag.cljs b/src/cljs/tales/util/drag.cljs deleted file mode 100644 index 4c717a3..0000000 --- a/src/cljs/tales/util/drag.cljs +++ /dev/null @@ -1,30 +0,0 @@ -(ns tales.util.drag - (:require [tales.util.events :as events])) - -(defn- drag-move-fn [drag-start on-drag] - (fn [ev] - (let [drag-start @drag-start - drag-end (events/client-coord ev) - dx (- (:x drag-end) (:x drag-start)) - dy (- (:y drag-end) (:y drag-start))] - (events/prevent ev) - (on-drag {:start drag-start :end drag-end :dx dx :dy dy})))) - -(defn- drag-end-fn [drag-move drag-end on-drag-end] - (fn [ev] - (events/prevent ev) - (events/stop ev) - (events/off "mousemove" drag-move) - (events/off "mouseup" @drag-end) - (on-drag-end))) - -(defn dragging - ([ev on-drag] (dragging ev on-drag (fn []))) - ([ev on-drag on-drag-end] - (let [drag-start (atom (events/client-coord ev)) - drag-move (drag-move-fn drag-start on-drag) - drag-end-atom (atom nil) - drag-end (drag-end-fn drag-move drag-end-atom on-drag-end)] - (reset! drag-end-atom drag-end) - (events/on "mousemove" drag-move) - (events/on "mouseup" drag-end)))) diff --git a/src/cljs/tales/util/events.cljs b/src/cljs/tales/util/events.cljs deleted file mode 100644 index 6a06ce2..0000000 --- a/src/cljs/tales/util/events.cljs +++ /dev/null @@ -1,55 +0,0 @@ -(ns tales.util.events) - -(defn ctrl-key? [ev] - "Indicates if the ctrl key was pressed when the event occured." - (.-ctrlKey ev)) - -(defn alt-key? [ev] - "Indicates if the alt key was pressed when the event occured." - (.-altKey ev)) - -(defn shift-key? [ev] - "Indicates if the shift key was pressed when the event occured." - (.-shiftKey ev)) - -(defn meta-key? [ev] - "Indicates if the meta key was pressed when the event occured." - (.-metaKey ev)) - -(defn key-val [ev] - "The value of the key pressed by the user." - (.-key ev)) - -(defn client-coord [ev] - "Provides the coordinate within the client area at which the event occurred." - {:x (.-clientX ev) :y (.-clientY ev)}) - -(defn page-coord [ev] - "Provides the coordinate within the the entire document at which the event - occurred. This includes any portion of the document not currently visible." - {:x (.-pageX ev) :y (.-pageY ev)}) - -(defn wheel-delta [ev] - "Provides the wheel scroll amount for each axis." - {:x (.-deltaX ev) :y (.-deltaY ev) :z (.-deltaZ ev)}) - -(defn prevent [ev] - "Prevents default actions of the current event." - (.preventDefault ev)) - -(defn stop [ev] - "Prevents further propagation of the current event in the capturing and - bubbling phases." - (.stopPropagation ev)) - -(defn on - "Sets up a `handler` that will be called whenever the specified event of - `type` is delivered to the `target`" - ([type handler] (on js/window type handler)) - ([target type handler] (.addEventListener target type handler))) - -(defn off - "Removes a `handler` that was setup for the specified event of `type` on the - `target`" - ([type handler] (off js/window type handler)) - ([target type handler] (.removeEventListener target type handler))) diff --git a/src/cljs/tales/util/transform.cljs b/src/cljs/tales/util/transform.cljs deleted file mode 100644 index ca943ee..0000000 --- a/src/cljs/tales/util/transform.cljs +++ /dev/null @@ -1,10 +0,0 @@ -(ns tales.util.transform) - -(defn scale - "Applies `new-scale` to point, assuming the original scale is 1 or - `old-scale`." - ([point new-scale] (scale point 1 new-scale)) - ([point old-scale new-scale] - (let [f (/ old-scale new-scale)] - {:x (* (:x point) f) - :y (* (:y point) f)}))) diff --git a/src/cljs/tales/views/core.cljs b/src/cljs/tales/views/core.cljs deleted file mode 100644 index 37cc21e..0000000 --- a/src/cljs/tales/views/core.cljs +++ /dev/null @@ -1,16 +0,0 @@ -(ns tales.views.core - (:require [re-frame.core :refer [subscribe]] - [tales.views.editor :as editor] - [tales.views.project :as project] - [tales.views.presenter :as presenter])) - -(defn- page [page-name] - (case page-name - :home [project/page] - :editor [editor/page] - :presenter [presenter/page] - [project/page])) - -(defn main-page [] - (let [active-page (subscribe [:active-page])] - [page @active-page])) diff --git a/src/cljs/tales/views/editor.cljs b/src/cljs/tales/views/editor.cljs deleted file mode 100644 index 86141f1..0000000 --- a/src/cljs/tales/views/editor.cljs +++ /dev/null @@ -1,112 +0,0 @@ -(ns tales.views.editor - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch subscribe]] - [tales.geometry :as geometry] - [tales.routes :as routes] - [tales.util.dom :as dom] - [tales.util.drag :refer [dragging]] - [tales.util.events :as events] - [tales.views.preview :as preview] - [tales.views.slide :as slide] - [tales.views.stage :refer [stage]])) - -(defn image-upload [project] - [:div#image-upload - [:h2 "You haven't uploaded a poster yet."] - [:h3 "Please do so now to start editing your tale!"] - [:input {:type "file" - :on-change #(let [file (-> % .-target .-files (aget 0)) - data {:project project :file file}] - (dispatch [:project/update-image data]))}]]) - -(defn image-size [] - [:div#image-size - [:h2 "We couldn't determine your poster dimensions."] - [:h3 "Please help us by manually setting them directly in the image!"]]) - -(defn navigator [] - (let [slides (subscribe [:slides]) - active-slide (subscribe [:slide/active]) - scale (subscribe [:viewport/scale]) - - svg-node (r/atom nil) - draw-rect (r/atom nil) - - on-create (fn [{drag-start :start dx :dx dy :dy}] - (let [drag-start (-> (dom/offset @svg-node) - (geometry/distance drag-start)) - x (/ (:x drag-start) @scale) - y (/ (:y drag-start) @scale) - dx (/ dx @scale) - dy (/ dy @scale)] - (reset! draw-rect (geometry/normalize-rect - {:x x :y y :width dx :height dy})))) - - on-create-end (fn [] - (if-let [rect @draw-rect] - (let [new-slide {:rect rect}] - (reset! draw-rect nil) - (dispatch [:slide/add new-slide])))) - - on-move (fn [slide {dx :dx dy :dy}] - (let [dx (/ dx @scale) - dy (/ dy @scale)] - (reset! draw-rect (geometry/move-rect - (:rect slide) dx dy)))) - - on-move-end (fn [slide] - (if-let [rect @draw-rect] - (let [new-slide (assoc-in slide [:rect] rect)] - (reset! draw-rect nil) - (dispatch [:slide/update new-slide])))) - - on-resize (fn [slide corner {dx :dx dy :dy}] - (let [dx (/ dx @scale) - dy (/ dy @scale)] - (reset! draw-rect (geometry/resize-rect - (:rect slide) corner dx dy)))) - - on-resize-end (fn [slide] - (if-let [rect @draw-rect] - (let [new-slide (assoc-in slide [:rect] rect)] - (reset! draw-rect nil) - (dispatch [:slide/update new-slide])))) - - start-create (fn [ev] - (if (or (events/ctrl-key? ev) (events/meta-key? ev)) - (do - (events/stop ev) - (dragging ev on-create on-create-end))))] - (fn [] - (let [active-slide @active-slide] - [stage - [:svg {:ref #(reset! svg-node %) - :style {:position "absolute" - :width "100%" - :height "100%"} - :on-mouse-down start-create} - (for [slide @slides] - [slide/rect {:key (:index slide) - :rect (:rect slide) - :active? (= (:index slide) active-slide) - :on-move #(on-move slide %) - :on-move-end #(on-move-end slide) - :on-resize #(on-resize slide %1 %2) - :on-resize-end #(on-resize-end slide)}]) - (if-let [draw-rect @draw-rect] - [slide/rect {:rect draw-rect}])]])))) - -(defn page [] - (let [project (subscribe [:project])] - [:div {:id "editor"} - [:header - [:h1 (:name @project)] - [:div - [:a {:href (routes/presenter-path {:slug (:slug @project)}) - :style {:padding-right "20px"}} "Tell!"] - [:a {:href (routes/home-path)} "Close"]]] - [:main (cond - (nil? (:file-path @project)) [image-upload @project] - (nil? (:dimensions @project)) [image-size] - :else [navigator])] - [:footer [preview/slides @project]]])) diff --git a/src/cljs/tales/views/loader.cljs b/src/cljs/tales/views/loader.cljs deleted file mode 100644 index cfdc6e0..0000000 --- a/src/cljs/tales/views/loader.cljs +++ /dev/null @@ -1,52 +0,0 @@ -(ns tales.views.loader - (:require [reagent.core :as r])) - -(defn loader [props] - (let [color (or (:color props) "#000") - background-color (or (:background-color props) "#fff")] - [:svg {:width 100 - :hegiht 100 - :viewBox "0 0 100 100" - :enable-background "new 0 0 0 0"} - [:circle {:fill "none" - :stroke color - :stroke-width 4 - :cx 50 - :cy 50 - :r 44 - :opacity 0.5}] - [:circle {:fill color - :stroke background-color - :stroke-width 3 - :cx 8 - :cy 54 - :r 6} - [:animateTransform {:attributeName "transform" - :dur "2s" - :type "rotate" - :from "0 50 46" - :to "360 50 54" - :repeatCount "indefinite"}]]])) - -(defn hide-loading [props] - (let [this (r/current-component) - loading? (:loading? props) - color (:color props) - background-color (:background-color props)] - (into [:div {:style {:width "100%" :height "100%"}} - [:div {:style {:display "flex" - :visibility (if loading? "visible" "hidden") - :opacity (if loading? 1 0) - :transition "visibility 0.5s, opacity 0.5s linear" - :align-items "center" - :justify-content "center" - :position "absolute" - :top 0 - :bottom 0 - :left 0 - :right 0 - :background-color background-color - :z-index 100}} - [loader {:background-color background-color - :color color}]]] - (r/children this)))) \ No newline at end of file diff --git a/src/cljs/tales/views/presenter.cljs b/src/cljs/tales/views/presenter.cljs deleted file mode 100644 index 753f02d..0000000 --- a/src/cljs/tales/views/presenter.cljs +++ /dev/null @@ -1,8 +0,0 @@ -(ns tales.views.presenter - (:require [tales.routes :as routes] - [tales.views.stage :refer [stage]])) - -(defn page [] - [:div {:id "presenter"} - [:main - [stage]]]) diff --git a/src/cljs/tales/views/preview.cljs b/src/cljs/tales/views/preview.cljs deleted file mode 100644 index 5dae898..0000000 --- a/src/cljs/tales/views/preview.cljs +++ /dev/null @@ -1,79 +0,0 @@ -(ns tales.views.preview - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch subscribe]])) - -(defn- slide-scale [slide target-width target-height] - "Calculates the scale factor to resize the slide to target-width/-height" - (let [slide-width (get-in slide [:rect :width]) - slide-height (get-in slide [:rect :height])] - (if (> (/ target-width target-height) (/ slide-width slide-height)) - (/ target-height slide-height) - (/ target-width slide-width)))) - -(defn slide [] - (let [this (r/current-component) - did-update (fn [] - (let [props (r/props this) - active? (:active? props)] - (if active? - (.scrollIntoView (r/dom-node this))))) - render (fn [props project slide] - (let [rect (:rect slide) - preview-width (:width props) - preview-height (:height props) - active? (:active? props) - scale (slide-scale slide preview-width preview-height) - dx (* scale (:x rect)) - dy (* scale (:y rect)) - scaled-slide-width (* scale (:width rect)) - scaled-slide-height (* scale (:height rect)) - scaled-img-width (* scale (:width (:dimensions project))) - scaled-img-height (* scale (:height (:dimensions project)))] - [:div.slide-preview-list-item - {:style {:position "relative" - :width preview-width :min-width preview-width - :height preview-height :min-height preview-height - :background-color "#333" - :border-width 3 - :border-style "solid" - :border-color (if active? "#ff0000" "#333")} - :on-click #(dispatch [:slide/activate (:index slide)]) - :on-double-click #(dispatch [:camera/fly-to-rect (:rect slide)])} - [:div - {:style {:width scaled-slide-width - :height scaled-slide-height - :background-color "#fff" - :background-repeat "no-repeat" - :background-image (str "url(" (:file-path project) ")") - :background-size (str - scaled-img-width "px " - scaled-img-height "px") - :background-position-x (- dx) - :background-position-y (- dy)}}] - [:div {:style {:position "absolute" - :background-color "rgba(0,0,0,0.6)" - :color "#fff" - :line-height "1em" - :font-size "0.8em" - :font-style "monospace" - :left "0" - :bottom "0" - :padding "4px 4px 3px 3px"}} - (inc (:index slide))]]))] - (r/create-class {:display-name "slide" - :component-did-update did-update - :reagent-render render}))) - -(defn slides [project] - (let [slides (subscribe [:slides]) - active-slide (subscribe [:slide/active]) - preview-width 100 - preview-height 75] - (let [active-slide @active-slide] - [:div#slides-preview.slide-preview-list - (for [item @slides] - ^{:key (:index item)} - [slide {:width preview-width - :height preview-height - :active? (= (:index item) active-slide)} - project item])]))) diff --git a/src/cljs/tales/views/project.cljs b/src/cljs/tales/views/project.cljs deleted file mode 100644 index 6195738..0000000 --- a/src/cljs/tales/views/project.cljs +++ /dev/null @@ -1,43 +0,0 @@ -(ns tales.views.project - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch subscribe]] - [tales.routes :refer [editor-path]])) - -(defn add-project [name] - (dispatch [:project/add {:name name}])) - -(defn project-input [] - (let [val (r/atom "") - stop #(do (reset! val "")) - save #(let [v (-> @val str clojure.string/trim)] - (if-not (empty? v) (add-project v)) - (stop))] - (fn [] - [:input {:type "text" - :id "new-project" - :placeholder "Enter the name of your tale and press enter" - :value @val - :on-change #(reset! val (-> % .-target .-value)) - :on-key-down #(case (.-which %) - 13 (save) - 27 (stop) - nil)}]))) - -(defn project-list [projects] - [:ul {:id "project-list"} - (for [[_ project] projects] - ^{:key (:slug project)} - [:li - [:a {:href (editor-path {:slug (:slug project)})} - (:name project)]])]) - -(defn page [] - (let [projects (subscribe [:project/all])] - [:div {:id "projects"} - [:header [:h1 "tales"]] - [:main - [:section [project-input]] - (if-not (empty? @projects) - [:section - [:h3 "or choose an existing tale:"] - [project-list @projects]])]])) diff --git a/src/cljs/tales/views/slide.cljs b/src/cljs/tales/views/slide.cljs deleted file mode 100644 index d233ebb..0000000 --- a/src/cljs/tales/views/slide.cljs +++ /dev/null @@ -1,71 +0,0 @@ -(ns tales.views.slide - (:require [re-frame.core :refer [dispatch subscribe]] - [tales.util.drag :refer [dragging]] - [tales.util.events :as events])) - -(def markers {:top-left {:x 0 :y 0 :cursor "nw-resize"} - :top {:x 1 :y 0 :cursor "n-resize"} - :top-right {:x 2 :y 0 :cursor "ne-resize"} - :right {:x 2 :y 1 :cursor "e-resize"} - :bottom-right {:x 2 :y 2 :cursor "se-resize"} - :bottom {:x 1 :y 2 :cursor "s-resize"} - :bottom-left {:x 0 :y 2 :cursor "sw-resize"} - :left {:x 0 :y 1 :cursor "w-resize"}}) - -(defn rect [props] - (let [scale (subscribe [:viewport/scale]) - active? (:active? props) - rect (:rect props) - x (:x rect) - y (:y rect) - width (:width rect) - height (:height rect) - border-width (/ 2.5 @scale) - marker-width (/ width 3) - marker-height (/ height 3) - color (if active? "#ff9900" "#3388ff") - - start-move (fn [ev] - (if active? - (let [on-move (:on-move props) - on-move-end (:on-move-end props)] - (dragging ev on-move on-move-end) - (events/stop ev)))) - - start-resize (fn [corner ev] - (if active? - (let [on-resize (:on-resize props) - on-resize-end (:on-resize-end props)] - (events/stop ev) - (dragging ev #(on-resize corner %) on-resize-end))))] - [:g {:on-click #(dispatch [:slide/activate (:key props)]) - :on-double-click #(dispatch [:camera/fly-to-rect rect]) - :class (:key props)} - [:rect {:x x - :y y - :width width - :height height - :stroke color - :stroke-width border-width - :fill color - :fill-opacity "0.2"}] - (if active? - [:g - [:rect {:on-mouse-down start-move - :x (+ x marker-width) - :y (+ y marker-height) - :width marker-width - :height marker-height - :fill color - :fill-opacity 0 - :style {:cursor "move"}}] - (for [[position options] markers] - ^{:key position} - [:rect {:on-mouse-down #(start-resize position %) - :x (+ x (* (:x options) marker-width)) - :y (+ y (* (:y options) marker-height)) - :width marker-width - :height marker-height - :fill color - :fill-opacity 0 - :style {:cursor (:cursor options)}}])])])) diff --git a/src/cljs/tales/views/stage.cljs b/src/cljs/tales/views/stage.cljs deleted file mode 100644 index 1d4501e..0000000 --- a/src/cljs/tales/views/stage.cljs +++ /dev/null @@ -1,119 +0,0 @@ -(ns tales.views.stage - (:require [reagent.core :as r] - [re-frame.core :refer [dispatch subscribe]] - [tales.geometry :as geometry] - [tales.util.async :refer [debounce]] - [tales.util.css :as css] - [tales.util.dom :as dom] - [tales.util.drag :refer [dragging]] - [tales.util.events :as events] - [tales.views.loader :refer [hide-loading]] - [thi.ng.math.core :as m] - [thi.ng.geom.matrix :as gm] - [thi.ng.geom.vector :as gv])) - -(def ^:private dispatch-debounced (debounce dispatch 40)) - -(defn poster [] - (let [file-path (subscribe [:poster/file-path])] - [:img {:style {:position "absolute" - :width "100%" - :height "100%"} - :src @file-path}])) - -(defn scene [] - (let [dimensions (subscribe [:poster/dimensions]) - viewport-matrix (subscribe [:matrix/viewport]) - mvp-matrix (subscribe [:matrix/mvp])] - [:div.scene {:style {:transform-origin "0 0" - :transform (css/transform-matrix - @viewport-matrix)}} - (into [:div.world {:style {:width (:width @dimensions) - :height (:height @dimensions) - :transform-origin "0 0" - :transform (css/transform-matrix3d - @mvp-matrix)}}] - (r/children (r/current-component)))])) - -(defn viewport [] - (let [this (r/current-component) - camera-position (subscribe [:camera/position]) - view-matrix (subscribe [:matrix/view]) - projection-matrix (subscribe [:matrix/projection]) - view-rect (subscribe [:viewport/view-rect]) - moving? (r/atom false) - on-move (fn [orig-position {{x1 :x y1 :y} :start {x2 :x y2 :y} :end}] - (let [start (-> [x1 y1] - (gm/unproject-point - @view-matrix - @projection-matrix - @view-rect)) - end (-> [x2 y2] - (gm/unproject-point - @view-matrix - @projection-matrix - @view-rect)) - dxy (m/- end start)] - (dispatch [:camera/move-to (-> - (gv/vec2 orig-position) - (m/- dxy))]))) - on-move-end (fn [] - (reset! moving? false)) - start-move (fn [ev] - (let [orig-position @camera-position] - (reset! moving? true) - (dragging ev #(on-move orig-position %) on-move-end) - (events/prevent ev) - (events/stop ev))) - start-zoom (fn [ev] - (let [dom-node (r/dom-node this) - {x :x y :y} (geometry/distance - (dom/offset dom-node) - (events/client-coord ev)) - position (-> [x y 0] - (gm/unproject-point - @view-matrix - @projection-matrix - @view-rect))] - (if (> 0 (:y (events/wheel-delta ev))) - (dispatch-debounced [:camera/zoom-in position]) - (dispatch-debounced [:camera/zoom-out position]))))] - (fn [] - (into [:div.viewport {:on-mouse-down start-move - :on-wheel start-zoom - :style {:background-color "#ddd" - :overflow "hidden" - :width (first (:size @view-rect)) - :height (second (:size @view-rect)) - :cursor (if @moving? - "grab" - "pointer")}}] - (r/children (r/current-component)))))) - -(defn stage [] - (let [this (r/current-component) - viewport-ready (subscribe [:viewport/ready?]) - on-resize (fn [] - (let [size (dom/size (r/dom-node this))] - (dispatch-debounced [:viewport/set-size size]))) - did-mount (fn [] - (events/on "resize" on-resize) - (on-resize)) - will-unmount (fn [] (events/off "resize" on-resize)) - render (fn [] - [:div.stage {:style {:background-color "#233" - :display "flex" - :align-items "center" - :justify-content "center" - :width "100%" - :height "100%"}} - (if @viewport-ready - [viewport - (into - [scene - [poster]] - (r/children this))])])] - (r/create-class {:display-name "stage" - :component-did-mount did-mount - :component-will-unmount will-unmount - :reagent-render render}))) diff --git a/test/cljs/tales/doo_runner.cljs b/test/cljs/tales/doo_runner.cljs deleted file mode 100644 index 83b639f..0000000 --- a/test/cljs/tales/doo_runner.cljs +++ /dev/null @@ -1,16 +0,0 @@ -(ns tales.doo-runner - (:require [doo.runner :refer-macros [doo-tests]] - [tales.views-test] - [tales.geometry-test] - [tales.events.core-test] - [tales.events.project-test] - [tales.events.slide-test] - [tales.events.view-test])) - -(doo-tests - 'tales.views-test - 'tales.geometry-test - 'tales.events.core-test - 'tales.events.project-test - 'tales.events.slide-test - 'tales.events.view-test) diff --git a/test/cljs/tales/events/core_test.cljs b/test/cljs/tales/events/core_test.cljs deleted file mode 100644 index add73b3..0000000 --- a/test/cljs/tales/events/core_test.cljs +++ /dev/null @@ -1,14 +0,0 @@ -(ns tales.events.core-test - (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]] - [day8.re-frame.test :as rf-test] - [re-frame.core :as rf] - [tales.events.core] - [tales.subs.core])) - -(deftest test-events-core - (testing "activate page" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [active-page (rf/subscribe [:active-page])] - (rf/dispatch [:activate-page :test-page]) - (is (= @active-page :test-page)))))) \ No newline at end of file diff --git a/test/cljs/tales/events/project_test.cljs b/test/cljs/tales/events/project_test.cljs deleted file mode 100644 index 52bb03d..0000000 --- a/test/cljs/tales/events/project_test.cljs +++ /dev/null @@ -1,148 +0,0 @@ -(ns tales.events.project-test - (:require [cljs.test :refer-macros [is are deftest testing]] - [tales.events.project :as project])) - -(deftest test-events-project-open - (testing "sets loading state" - (let [db {} - event [] - {db' :db} (project/open db event)] - (is (true? (get-in db' [:loading? :project]))))) - (testing "makes request to remote" - (let [db {} - event ["my-tale"] - {req :http-xhrio} (project/open db event)] - (is (= (:method req) :get)) - (is (= (:uri req) "/api/tales/my-tale")) - (is (= (:on-success req) [:project/open-success])) - (is (= (:on-failure req) [:api-request-error :project]))))) - -(deftest test-events-project-open-success - (testing "unsets loading state" - (let [db {} - event [] - {db' :db} (project/open-success db event)] - (is (false? (get-in db' [:loading? :project]))))) - (testing "unsets errors" - (let [db {:errors [:error1 :error2]} - event [] - {db' :db} (project/open-success db event)] - (is (nil? (:errors db'))))) - (testing "resets project from response" - (let [db {} - project {:slug "my-tale"} - event [project] - {db' :db} (project/open-success db event)] - (is (= project (:project db')))))) - -(deftest test-events-project-get-all - (testing "sets loading state" - (let [db {} - {db' :db} (project/get-all db)] - (is (true? (get-in db' [:loading? :projects]))))) - (testing "makes request to remote" - (let [db {} - {req :http-xhrio} (project/get-all db)] - (is (= (:method req) :get)) - (is (= (:uri req) "/api/tales/")) - (is (= (:on-success req) [:project/get-all-success])) - (is (= (:on-failure req) [:api-request-error :projects]))))) - -(deftest test-events-project-get-all-success - (testing "unsets loading state" - (let [db {} - event [] - db' (project/get-all-success db event)] - (is (false? (get-in db' [:loading? :projects]))))) - (testing "unsets errors" - (let [db {:errors [:error1 :error2]} - event [] - db' (project/get-all-success db event)] - (is (nil? (:errors db'))))) - (testing "resets project from response" - (let [db {} - project1 {:slug "my-first-tale"} - project2 {:slug "my-second-tale"} - event [[project1 project2]] - db' (project/get-all-success db event)] - (is (= 2 (count (:projects db')))) - (is (= project1 (get-in db' [:projects "my-first-tale"]))) - (is (= project2 (get-in db' [:projects "my-second-tale"])))))) - -(deftest test-events-project-add - (testing "sets loading state" - (let [db {} - event [] - {db' :db} (project/add db event)] - (is (true? (get-in db' [:loading? :project]))))) - (testing "makes request to remote" - (let [db {} - project {:slug "my-tale"} - event [project] - {req :http-xhrio} (project/add db event)] - (is (= (:method req) :post)) - (is (= (:uri req) "/api/tales/")) - (is (= (:params req) project)) - (is (= (:on-success req) [:project/change-success])) - (is (= (:on-failure req) [:api-request-error :project]))))) - -(deftest test-events-project-update - (testing "sets loading state" - (let [db {} - event [] - {db' :db} (project/change db event)] - (is (true? (get-in db' [:loading? :project]))))) - (testing "makes request to remote" - (let [db {} - project {:slug "my-tale"} - event [project] - {req :http-xhrio} (project/change db event)] - (is (= (:method req) :put)) - (is (= (:uri req) "/api/tales/my-tale")) - (is (= (:params req) project)) - (is (= (:on-success req) [:project/change-success])) - (is (= (:on-failure req) [:api-request-error :project]))))) - -(deftest test-events-project-change-success - (testing "unsets loading state" - (let [db {} - event [] - {db' :db} (project/change-success db event)] - (is (false? (get-in db' [:loading? :project]))))) - (testing "unsets errors" - (let [db {:errors [:error1 :error2]} - event [] - {db' :db} (project/change-success db event)] - (is (nil? (:errors db'))))) - (testing "resets project from response" - (let [db {} - project {:slug "my-tale"} - event [project] - {db' :db} (project/change-success db event)] - (is (= project (get-in db' [:projects "my-tale"]))))) - (testing "navigates to project" - (let [db {} - event [{:slug "my-tale"}] - {navigate :navigate} (project/change-success db event)] - (is (= "/editor/my-tale/" navigate))))) - -(deftest test-events-project-api-request-error - (testing "sets errors from response" - (let [db {} - errors ["unknown error"] - event [:test-request {:response {:errors errors}}] - {db' :db} (project/api-request-error db event)] - (is (= errors (get-in db' [:errors :test-request]))))) - (testing "dispatches complete request event" - (let [db {} - event [:test-request nil] - {event :dispatch} (project/api-request-error db event)] - (is (= (first event) :complete-request)) - (is (= (second event) :test-request))))) - -(deftest test-events-project-complete-request - (testing "unsets loading state" - (let [db {:loading? {:test-request true}} - event [:test-request] - db' (project/complete-request db event)] - (is (false? (get-in db' [:loading? :test-request])))))) diff --git a/test/cljs/tales/events/slide_test.cljs b/test/cljs/tales/events/slide_test.cljs deleted file mode 100644 index bf2cf42..0000000 --- a/test/cljs/tales/events/slide_test.cljs +++ /dev/null @@ -1,155 +0,0 @@ -(ns tales.events.slide-test - (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]] - [day8.re-frame.test :as rf-test] - [re-frame.core :as rf] - [tales.events.core] - [tales.subs.core] - [tales.helper :refer [with-mounted-component]])) - -(deftest test-events-slide - (rf/reg-event-db :project/add - (fn [db [_ project]] - (assoc db :project project))) - - (rf/reg-event-db :project/update - (fn [db [_ project]] - (assoc db :project project))) - - (testing "add slide" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale" :slides []} - slides (rf/subscribe [:slides])] - (rf/dispatch [:project/add example-project]) - (is (= (count @slides) 0)) - (rf/dispatch [:slide/add {:id 0}]) - (is (= (count @slides) 1)) - (is (= (:id (nth @slides 0)) 0)) - (rf/dispatch [:slide/add {:id 1}]) - (is (= (count @slides) 2)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (rf/dispatch [:slide/add {:id 2}]) - (is (= (count @slides) 3)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2))))) - - (testing "update slide" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale" :slides []} - slides (rf/subscribe [:slides])] - (rf/dispatch [:project/add example-project]) - (is (= (count @slides) 0)) - (rf/dispatch [:slide/add {:id 0}]) - (rf/dispatch [:slide/add {:id 1}]) - (rf/dispatch [:slide/add {:id 2}]) - (rf/dispatch [:slide/activate 1]) - (rf/dispatch [:slide/update {:id 1 :changed true}]) - (is (= (count @slides) 3)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (is (:changed (nth @slides 1))) - (is (not (:changed (nth @slides 0)))) - (is (not (:changed (nth @slides 2))))))) - - (testing "delete active slide" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale" :slides []} - slides (rf/subscribe [:slides])] - (rf/dispatch [:project/add example-project]) - (is (= (count @slides) 0)) - (rf/dispatch [:slide/add {:id 0}]) - (rf/dispatch [:slide/add {:id 1}]) - (rf/dispatch [:slide/add {:id 2}]) - (is (= (count @slides) 3)) - (rf/dispatch [:slide/delete 1]) - (is (= (count @slides) 2)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 2))))) - - (testing "activate slide" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale"} - active-slide (rf/subscribe [:slide/active])] - (rf/dispatch [:project/add example-project]) - (rf/dispatch [:slide/activate 1]) - (is (= @active-slide 1))))) - - (testing "move between slides" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale" :slides [{} {} {}]} - active-slide (rf/subscribe [:slide/active])] - (rf/dispatch [:project/add example-project]) - (rf/dispatch [:slide/activate nil]) - (rf/dispatch [:slide/next]) - (is (= @active-slide 0)) - (rf/dispatch [:slide/activate nil]) - (rf/dispatch [:slide/prev]) - (is (= @active-slide 2)) - (rf/dispatch [:slide/activate 1]) - (is (= @active-slide 1)) - (rf/dispatch [:slide/next]) - (is (= @active-slide 2)) - (rf/dispatch [:slide/next]) - (is (= @active-slide 0)) - (rf/dispatch [:slide/prev]) - (is (= @active-slide 2)) - (rf/dispatch [:slide/prev]) - (is (= @active-slide 1))))) - - (testing "swap slides" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [example-project {:slug "my-tale" :slides [{:id 0} {:id 1} {:id 2}]} - active-slide (rf/subscribe [:slide/active]) - slides (rf/subscribe [:slides])] - (rf/dispatch [:project/add example-project]) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (rf/dispatch [:slide/swap 1 2]) - (is (= @active-slide 2)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 2)) - (is (= (:id (nth @slides 2)) 1)) - (rf/dispatch [:slide/swap 2 1]) - (is (= @active-slide 1)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (rf/dispatch [:slide/swap 1 3]) - (is (= @active-slide 1)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (rf/dispatch [:slide/swap 3 1]) - (is (= @active-slide 1)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (rf/dispatch [:slide/swap-next 1]) - (is (= @active-slide 2)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 2)) - (is (= (:id (nth @slides 2)) 1)) - (rf/dispatch [:slide/swap-prev 2]) - (is (= @active-slide 1)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)) - (rf/dispatch [:slide/swap-next]) - (is (= @active-slide 2)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 2)) - (is (= (:id (nth @slides 2)) 1)) - (rf/dispatch [:slide/swap-prev]) - (is (= @active-slide 1)) - (is (= (:id (nth @slides 0)) 0)) - (is (= (:id (nth @slides 1)) 1)) - (is (= (:id (nth @slides 2)) 2)))))) \ No newline at end of file diff --git a/test/cljs/tales/events/view_test.cljs b/test/cljs/tales/events/view_test.cljs deleted file mode 100644 index 74e6e90..0000000 --- a/test/cljs/tales/events/view_test.cljs +++ /dev/null @@ -1,80 +0,0 @@ -(ns tales.events.view-test - (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]] - [day8.re-frame.test :as rf-test] - [re-frame.core :as rf] - [tales.events.core] - [tales.subs.view] - [tales.helper :refer [with-mounted-component]])) - -(deftest test-events-view - (testing "viewport set size" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [size (rf/subscribe [:viewport/size])] - (rf/dispatch [:viewport/set-size [123 321]]) - (is (= @size [123 321]))))) - (testing "camera moving" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [position (rf/subscribe [:camera/position])] - (rf/dispatch [:camera/move-to [10 20]]) - (is (= @position [10 20])) - (rf/dispatch [:camera/move-to [20 10]]) - (is (= @position [20 10]))))) - (testing "camera zooming" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [position (rf/subscribe [:camera/position]) - scale (rf/subscribe [:camera/scale])] - (rf/dispatch [:camera/set-scale 1]) - (is (= @scale 1)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-out]) - (is (= @scale 2)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-out]) - (is (= @scale 4)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-in]) - (is (= @scale 2)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-in]) - (is (= @scale 1)) - (is (= @position [0 0]))))) - (testing "camera zooming around" - (rf-test/run-test-sync - (rf/dispatch [:initialise-db]) - (let [position (rf/subscribe [:camera/position]) - scale (rf/subscribe [:camera/scale])] - (rf/dispatch [:camera/set-scale 1]) - (is (= @scale 1)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-in [0 0]]) - (is (= @scale 0.5)) - (is (= @position [0 0])) - (rf/dispatch [:camera/zoom-out [10 20]]) - (is (= @scale 1)) - (is (= @position [-10 -20])) - (rf/dispatch [:camera/zoom-in [100 200]]) - (is (= @scale 0.5)) - (is (= @position [45 90])) - (rf/dispatch [:camera/zoom-out [90 0]]) - (is (= @scale 1)) - (is (= @position [0 180]))))) - (testing "camera fit rect" - (rf-test/run-test-sync - (rf/dispatch-sync [:initialise-db]) - (rf/dispatch [:viewport/set-size [100 100]]) - (rf/dispatch [:project/add {:slug "my-tale" - :dimensions {:width 100 :height 100}}]) - (let [position (rf/subscribe [:camera/position]) - scale (rf/subscribe [:camera/scale])] - (rf/dispatch [:camera/fit-rect {:x 0 :y 0 :width 100 :height 100}]) - (is (= @scale 50)) - (is (= @position [50 50])) - (rf/dispatch [:camera/fit-rect {:x 50 :y 50 :width 50 :height 50}]) - (is (= @scale 25)) - (is (= @position [75 75])) - (rf/dispatch [:camera/fit-rect {:x 20 :y 20 :width 25 :height 25}]) - (is (= @scale 12.5)) - (is (= @position [32.5 32.5])))))) diff --git a/test/cljs/tales/geometry_test.cljs b/test/cljs/tales/geometry_test.cljs deleted file mode 100644 index b9465e2..0000000 --- a/test/cljs/tales/geometry_test.cljs +++ /dev/null @@ -1,69 +0,0 @@ -(ns tales.geometry-test - (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]] - [tales.geometry :as geometry])) - -(deftest test-geometry - (testing "zoom to scale conversion" - (is (= (geometry/zoom->scale 0) 1)) - (is (= (geometry/zoom->scale 2) 4)) - (is (= (geometry/zoom->scale -2) 0.25))) - (testing "scale to zoom conversion" - (is (= (geometry/scale->zoom 1) 0)) - (is (= (geometry/scale->zoom 4) 2)) - (is (= (geometry/scale->zoom 0.25) -2))) - (testing "scale point" - (is (= (geometry/scale {:x 0 :y 0} 1) {:x 0 :y 0})) - (is (= (geometry/scale {:x 10 :y 20} 5) {:x 2 :y 4})) - (is (= (geometry/scale {:x 10 :y 20} 0.5) {:x 20 :y 40}))) - (testing "unscale point" - (is (= (geometry/unscale {:x 0 :y 0} 1) {:x 0 :y 0})) - (is (= (geometry/unscale {:x 10 :y 20} 5) {:x 50 :y 100})) - (is (= (geometry/unscale {:x 10 :y 20} 0.5) {:x 5 :y 10}))) - (testing "add two points" - (is (= (geometry/add-points {:x 10 :y 20} {:x 10 :y 20}) {:x 20 :y 40})) - (is (= (geometry/add-points {:x 10 :y 20} {:x 70 :y 90}) {:x 80 :y 110}))) - (testing "distance between points" - (is (= (geometry/distance {:x 10 :y 20} {:x 10 :y 20}) {:x 0 :y 0})) - (is (= (geometry/distance {:x 10 :y 20} {:x 70 :y 90}) {:x 60 :y 70}))) - (testing "center of rect" - (is (= (geometry/rect-center {:x 10 :y 20 :width 30 :height 40}) - {:x 25 :y 40}))) - (testing "move point" - (is (= (geometry/move-point {:x 10 :y 20} 30 40) {:x 40 :y 60}))) - (testing "move rect" - (is (= (geometry/move-rect {:x 10 :y 20 :width 10 :height 20} 30 40) - {:x 40 :y 60 :width 10 :height 20}))) - (testing "normalize rect" - (is (= (geometry/normalize-rect {:x 10 :y 20 :width 30 :height 40}) - {:x 10 :y 20 :width 30 :height 40})) - (is (= (geometry/normalize-rect {:x -10 :y -20 :width 30 :height 40}) - {:x -10 :y -20 :width 30 :height 40})) - (is (= (geometry/normalize-rect {:x 10 :y 20 :width -30 :height -40}) - {:x -20 :y -20 :width 30 :height 40})) - (is (= (geometry/normalize-rect {:x -10 :y -20 :width -30 :height -40}) - {:x -40 :y -60 :width 30 :height 40}))) - (testing "resize rect" - (let [rect {:x 10 :y 20 :width 30 :height 40}] - (is (= (geometry/resize-rect rect :top-left 10 20) - {:x 20 :y 40 :width 20 :height 20})) - (is (= (geometry/resize-rect rect :top 10 20) - {:x 10 :y 40 :width 30 :height 20})) - (is (= (geometry/resize-rect rect :top-right 10 20) - {:x 10 :y 40 :width 40 :height 20})) - (is (= (geometry/resize-rect rect :right 10 20) - {:x 10 :y 20 :width 40 :height 40})) - (is (= (geometry/resize-rect rect :bottom-right 10 20) - {:x 10 :y 20 :width 40 :height 60})) - (is (= (geometry/resize-rect rect :bottom 10 20) - {:x 10 :y 20 :width 30 :height 60})) - (is (= (geometry/resize-rect rect :bottom-left 10 20) - {:x 20 :y 20 :width 20 :height 60})) - (is (= (geometry/resize-rect rect :left 10 20) - {:x 20 :y 20 :width 20 :height 40})) - (is (= (geometry/resize-rect rect :bottom-right -40 -50) - {:x 0 :y 10 :width 10 :height 10})))) - (testing "rect scale" - (let [rect {:x 10 :y 20 :width 30 :height 40}] - (is (= (geometry/rect-scale rect rect) 1)) - (is (= (geometry/rect-scale rect {:x 10 :y 20 :width 15 :height 10}) 2)) - (is (= (geometry/rect-scale rect {:x 10 :y 20 :width 30 :height 80}) 0.5))))) \ No newline at end of file diff --git a/test/cljs/tales/helper.cljs b/test/cljs/tales/helper.cljs deleted file mode 100644 index 262e1b8..0000000 --- a/test/cljs/tales/helper.cljs +++ /dev/null @@ -1,20 +0,0 @@ -(ns tales.helper - (:require [reagent.core :as r :refer [atom]])) - -(def is-client (not (nil? (try (.-document js/window) - (catch js/Object e nil))))) - -(defn- add-test-div [name] - (let [doc js/document - body (.-body js/document) - div (.createElement doc "div")] - (.appendChild body div) - div)) - -(defn with-mounted-component [comp f] - (when is-client - (let [div (add-test-div "_testreagent")] - (let [comp (r/render-component comp div #(f comp div))] - (r/unmount-component-at-node div) - (r/flush) - (.removeChild (.-body js/document) div))))) \ No newline at end of file diff --git a/test/cljs/tales/views_test.cljs b/test/cljs/tales/views_test.cljs deleted file mode 100644 index 2956bb1..0000000 --- a/test/cljs/tales/views_test.cljs +++ /dev/null @@ -1,26 +0,0 @@ -(ns tales.views-test - (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]] - [reagent.core :as reagent :refer [atom]] - [tales.views.editor :as editor] - [tales.views.project :as project] - [tales.core] - [tales.helper :refer [with-mounted-component]])) - -(defn found-in [re div] - (let [res (.-innerHTML div)] - (if (re-find re res) - true - (do (println "Not found: " res) - false)))) - -(deftest test-project-page - (testing "contains heading in tell page" - (with-mounted-component (project/page) - (fn [_ div] - (is (found-in #"Enter the name of your tale and press enter" div)))))) - -(deftest test-editor-page - (testing "contains heading in editor page" - (with-mounted-component (editor/page) - (fn [_ div] - (is (found-in #"You haven't uploaded a poster yet." div))))))