(ns outliner.model.state (:require [reagent.core :as r] [outliner.model.core.logic :as logic] [outliner.control.system :as system] #?(:cljs [outliner.boundaries.firestore :as firestore]) #?(:cljs [outliner.boundaries.firebase :as fb]))) (defn welcome-doc [] (let [id1 (str (random-uuid)) id2 (str (random-uuid))] {:root [id1] :nodes {id1 {:id id1 :text "Welcome to Palatium" :annotations [] :children [id2] :parent nil} id2 {:id id2 :text "Try adding a sub-node" :annotations [] :children [] :parent id1}}})) (defn empty-doc [] {:root [] :nodes {}}) (defn get-zoom-id-from-url [] (let [params (js/URLSearchParams. js/window.location.search)] (.get params "zoom"))) (defn html-format? [] (let [params (js/URLSearchParams. js/window.location.search)] (= (.get params "format") "text/html"))) (defn init-view [doc] (let [zoom-id (get-zoom-id-from-url)] {:focused-id (or zoom-id (first (:root doc))) :zoom-id zoom-id :active-context-menu-id nil :toast nil})) (defn init-sys [] {:undo-stack [] :redo-stack [] :location-history [] :dark-mode? false :viewport nil}) (def initial-doc (empty-doc)) (def initial-view (init-view initial-doc)) (def initial-sys (init-sys)) (defonce doc-state (r/atom initial-doc)) (defonce lost-found-count (r/atom "Checking...")) (defonce tree-size (r/atom 0)) (defmethod logic/resolve-variable "$lost-found-count" [_] (str "Nodes: " @lost-found-count)) (defmethod logic/resolve-variable "$tree-size" [_] (str "Tree size: " @tree-size)) (defn- update-tree-size! [new-doc] (let [count (count (:nodes new-doc))] (reset! tree-size count))) (add-watch doc-state :tree-size-watcher (fn [_ _ _ new-doc] (update-tree-size! new-doc))) ;; Initial count (update-tree-size! @doc-state) (defonce view-state (r/atom initial-view)) (defonce sys-state (r/atom (merge initial-sys {:user nil :sync-status :disconnected :last-sync-timestamp nil :unsaved-changes? false}))) (defn node-exists? [id] (boolean (get-in @doc-state [:nodes id]))) (defn reset-to-initial-state! [] (let [doc (welcome-doc)] (reset! doc-state doc) (reset! view-state (init-view doc)))) (defn clear-preserved-caret-position! [] (swap! view-state dissoc :preserved-caret-position)) (defn clear-preserved-selection! [] (swap! view-state dissoc :preserved-selection)) (defn update-node! [id updates] (swap! doc-state update-in [:nodes id] merge updates)) (defn show-toast! [message] (swap! view-state assoc :toast message)) (defn hide-toast! [] (swap! view-state assoc :toast nil)) (defn on-node-expanded [sys id] #?(:cljs (let [user-id (fb/get-user-uid (:user sys)) node (some (fn [n] (when (= (:id n) id) n)) (system/system-nodes user-id))] (when (= (:on-expand node) :fetch-orphan-count) (when user-id (firestore/fetch-orphan-count user-id (fn [count] (reset! lost-found-count count))))))))