diff --git a/src-cljs/frontend/components/canvas.cljs b/src-cljs/frontend/components/canvas.cljs index 44605620..0e653b85 100644 --- a/src-cljs/frontend/components/canvas.cljs +++ b/src-cljs/frontend/components/canvas.cljs @@ -216,6 +216,7 @@ (not external-target?))) show-handles? (and (not part-of-group?) selected? + (not (:unsaved layer)) (contains? #{:layer.type/rect :layer.type/line} (:layer/type layer)) (or (= :select tool) (and (= :circle tool) (layers/circle? layer)) diff --git a/src-cljs/frontend/controllers/controls.cljs b/src-cljs/frontend/controllers/controls.cljs index 95b3a776..65285fc9 100644 --- a/src-cljs/frontend/controllers/controls.cljs +++ b/src-cljs/frontend/controllers/controls.cljs @@ -1075,10 +1075,15 @@ (or (not (get-in previous-state [:drawing :moving?])) (some true? (map detectable-movement? original-layers layers)))) (doseq [layer-group (partition-all 100 layers)] - (d/transact! db (if (= :read (:max-document-scope current-state)) - (map #(assoc % :unsaved true) layer-group) + (utils/mlog "layer-group" layer-group) + (d/transact! db (if (or (utils/inspect (:pessimistic? current-state)) + (= :read (:max-document-scope current-state))) + (utils/inspect (map #(assoc % :unsaved true) layer-group)) layer-group) - {:can-undo? true}))) + {:can-undo? true}) + (if (:pessimistic? current-state) + (js/setTimeout #(d/transact! db (map (fn [g] (assoc g :unsaved false)) layer-group)) + (+ 750 (rand-int 500)))))) (maybe-notify-subscribers! previous-state current-state x y)) :else nil))) @@ -1334,6 +1339,14 @@ [state cmd chat] (update-in state [:db] frontend.db/reset-db!)) +(defmethod handle-cmd-chat "optimistic" + [state cmd chat] + (update-in state [:pessimistic?] not)) + +(defmethod handle-cmd-chat "stop-sync" + [state cmd chat] + (update-in state [:stop-sync?] not)) + (defmethod control-event :chat-body-changed [browser-state message {:keys [chat-body]} state] (-> state diff --git a/src-cljs/frontend/core.cljs b/src-cljs/frontend/core.cljs index d302fbca..9ffd9437 100644 --- a/src-cljs/frontend/core.cljs +++ b/src-cljs/frontend/core.cljs @@ -138,38 +138,39 @@ (:document/id s) :requested-color (get-in s [:subscribers :info (:client-id s) :color]) :requested-remainder (get-in s [:subscribers :info (:client-id s) :frontend-id-seed :remainder])))))))] - (swap! initial-state #(-> (assoc % - ;; id for the browser, used to filter transactions - :admin? admin? - :tab-id tab-id - :sente-id sente-id - :client-id (str sente-id "-" tab-id) - :db (db/make-initial-db initial-entities) - ;; team entities go into the team namespace, so we need a separate database - ;; to prevent conflicts - :team-db (db/make-initial-db nil) - :issue-db issue-db - :document/id document-id - ;; Communicate to nav channel that we shouldn't reset db - :initial-state true - :cust cust - :team team - :subdomain config/subdomain - :show-landing? (:show-landing? utils/initial-query-map) - :ab-choices ab-choices - :tal tal - :use-talaria? use-talaria? - :comms {:controls controls-ch - :api api-ch - :errors errors-ch - :nav navigation-ch - :controls-mult (async/mult controls-ch) - :api-mult (async/mult api-ch) - :errors-mult (async/mult errors-ch) - :nav-mult (async/mult navigation-ch)}) - (merge (when use-talaria? - {:sente tal})) - (browser-settings/restore-browser-settings cust))) + (utils/inspect (swap! initial-state #(-> (assoc % + ;; id for the browser, used to filter transactions + :admin? admin? + :tab-id tab-id + :sente-id sente-id + :client-id (str sente-id "-" tab-id) + :db (db/make-initial-db initial-entities) + ;; team entities go into the team namespace, so we need a separate database + ;; to prevent conflicts + :team-db (db/make-initial-db nil) + :issue-db issue-db + :document/id document-id + ;; Communicate to nav channel that we shouldn't reset db + :initial-state true + :cust cust + :team team + :subdomain config/subdomain + :show-landing? (:show-landing? utils/initial-query-map) + :ab-choices ab-choices + :tal tal + :use-talaria? use-talaria? + :pessimistic? (utils/inspect (:pessimistic? utils/initial-query-map)) + :comms {:controls controls-ch + :api api-ch + :errors errors-ch + :nav navigation-ch + :controls-mult (async/mult controls-ch) + :api-mult (async/mult api-ch) + :errors-mult (async/mult errors-ch) + :nav-mult (async/mult navigation-ch)}) + (merge (when use-talaria? + {:sente tal})) + (browser-settings/restore-browser-settings cust)))) initial-state)) (defn controls-handler diff --git a/src-cljs/frontend/utils.cljs b/src-cljs/frontend/utils.cljs index ec5f48bd..f771c2e2 100644 --- a/src-cljs/frontend/utils.cljs +++ b/src-cljs/frontend/utils.cljs @@ -48,7 +48,8 @@ :utm-campaign (.getParameterValue parsed-uri "utm_campaign") :utm-source (.getParameterValue parsed-uri "utm_source") :use-talaria? (parse-uri-bool (.getParameterValue parsed-uri "tal")) - :use-talaria-ajax? (parse-uri-bool (.getParameterValue parsed-uri "ajax"))}) + :use-talaria-ajax? (parse-uri-bool (.getParameterValue parsed-uri "ajax")) + :pessimistic? (parse-uri-bool (.getParameterValue parsed-uri "pessimistic"))}) (defn logging-enabled? [] (aget js/window "Precursor" "logging-enabled")) diff --git a/src/pc/repl.clj b/src/pc/repl.clj index 5fcd33f1..909d2c94 100644 --- a/src/pc/repl.clj +++ b/src/pc/repl.clj @@ -25,7 +25,8 @@ [pc.models.plan :as plan-model] [pc.models.team :as team-model] [pc.stripe :as stripe] - [slingshot.slingshot :refer (try+ throw+)])) + [slingshot.slingshot :refer (try+ throw+)]) + (:import [java.util UUID])) (defmacro pomegranate-load [artifact] `(do @@ -43,3 +44,129 @@ `(do (require 'clojure.java.javadoc) (clojure.java.javadoc/javadoc ~x))) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +;; Optimistic talk +;; ------------------------------------------------------------------------------ + +;; clojure + +(defn pp-tx-data [tx] + (let [db (:db-after tx) + pv (fn [d] + (if-let [ident (:db/ident (d/entity db (:v d)))] + ident + (:v d)))] + (d/ident (pcd/default-db) (:a (first (:tx-data mytx)))) + (clojure.pprint/pprint + (mapv (fn [d] + [(d/ident db (:a d)) (pv d) (if (:added d) :added :removed)]) + (remove #(or (= :frontend/id (d/ident db (:a %))) + (:db/txInstant (d/entity db (:e %)))) + (:tx-data tx)))))) + +(comment + ;; 1. fill in document-id + (do + (def document-id 17592186047659) + (def document (doc-model/find-by-id (pcd/default-db) document-id)) + (def frontend-part 1184) + (def frontend-id (UUID. (:db/id document) frontend-part))) + + ;; 2. Eval in cljs repl + (defn cljs-pp-tx-data [tx] + (mapv (fn [d] + [(:a d) (:v d) (if (:added d) :added :removed)]) + (:tx-data tx))) + + ;; 3. Eval in cljs repl + (cljs-pp-tx-data (datascript.core/transact! (:db @frontend.core/debug-state) + [{:db/id 1184 + :layer/name "placeholder" + :layer/opacity 1.0 + :layer/stroke-width 1.0 + :layer/stroke-color "black" + :layer/start-x 200.0 + :layer/end-x 500.0 + :layer/start-y 100.0 + :layer/end-y 400.0 + :layer/fill "none" + :layer/type :layer.type/rect}] + {:can-undo? true})) + + ;; 4. Eval small change in cljs repl (rect -> line) + (cljs-pp-tx-data (datascript.core/transact! (:db @frontend.core/debug-state) + [{:db/id 1184 + :layer/name "placeholder" + :layer/opacity 1.0 + :layer/stroke-width 1.0 + :layer/stroke-color "black" + :layer/start-x 200.0 + :layer/end-x 500.0 + :layer/start-y 100.0 + :layer/end-y 400.0 + :layer/fill "none" + :layer/type :layer.type/line}] + {:can-undo? true})) + + ;; 5. Eval in clj repl + (pp-tx-data @(d/transact (pcd/conn) [{:db/id (d/tempid :db.part/user) + :layer/name "placeholder" + :layer/document (:db/id document) + :layer/opacity 1.0 + :layer/stroke-width 1.0 + :layer/stroke-color "black" + :layer/start-x 200.0 + :layer/end-x 400.0 + :layer/start-y 100.0 + :layer/end-y 300.0 + :layer/fill "none" + :layer/type :layer.type/rect + :frontend/id frontend-id} + {:db/id (d/tempid :db.part/tx) + :transaction/broadcast true + :transaction/document (:db/id document) + :session/uuid (d/squuid) + :session/client-id (str (d/squuid))}])) + ) + +;; clojurescript +(comment +)