(ns outliner.control.system (:require [outliner.model.core.logic :as logic] [outliner.model.core.tree :as tree] #?(:cljs [outliner.boundaries.firestore :as firestore]) #?(:cljs [outliner.boundaries.firebase :as fb]) #?(:cljs [reagent.core :as r]))) (def system-id "system-root") (def githash-id "system-githash") (def help-id "system-help") (def lost-found-id "system-lost-found") (def lost-found-count-id "system-lost-found-count") (def tree-size-id "system-tree-size") (def lost-found-count #?(:cljs (r/atom "Checking...") :clj (atom "Checking..."))) (def tree-size #?(:cljs (r/atom 0) :clj (atom 0))) (defn handle-node-expanded [doc sys id] #?(:cljs (let [node (tree/get-node doc id)] (when (= (:on-expand node) :fetch-orphan-count) (let [user-id (fb/get-user-uid (:user sys))] (when user-id (firestore/fetch-orphan-count user-id (fn [count] (reset! lost-found-count count))))))))) (defmethod logic/resolve-variable "$lost-found-count" [_] (str "Nodes: " @lost-found-count)) (defmethod logic/resolve-variable "$tree-size" [_] (str "Tree size: " @tree-size)) (defn get-githash [] #?(:cljs (or (and (exists? js/window) (.-app_commit_hash js/window)) "unknown") :clj "unknown")) (defn system-nodes [user-id] [;; Root level system node {:id system-id :text "System" :annotations [] :parent nil :system-root? true :expanded? false} ;; Children of system-root (let [prefix "Git hash: " text (str prefix (get-githash))] {:id githash-id :text text :annotations [{:range-start (count prefix) :range-end (count text) :type :style :style :code}] :parent system-id}) {:id help-id :text "Help" :annotations [] :parent system-id :expanded? false} (when user-id {:id lost-found-id :text "lost+found" :annotations [] :parent system-id :expanded? false :on-expand :fetch-orphan-count}) {:id tree-size-id :text "$tree-size" :annotations [] :parent system-id} ;; Children of Help {:id "help-shortcuts" :text "Keyboard Shortcuts" :annotations [{:range-start 0 :range-end 18 :type :style :style :bold}] :parent help-id} {:id "help-formatting" :text "Markdown Formatting" :annotations [{:range-start 0 :range-end 19 :type :style :style :bold}] :parent help-id} ;; Children of Keyboard Shortcuts {:id "sc-1" :text "Tab / Shift+Tab: Indent / Outdent" :parent "help-shortcuts"} {:id "sc-2" :text "Enter: New node / Split node" :parent "help-shortcuts"} {:id "sc-3" :text "Ctrl+Enter: Toggle complete" :parent "help-shortcuts"} {:id "sc-4" :text "Ctrl+ArrowUp/Down: Collapse / Expand" :parent "help-shortcuts"} {:id "sc-5" :text "Alt+Shift+ArrowUp/Down: Move node up / down" :parent "help-shortcuts"} {:id "sc-6" :text "Alt+ArrowUp/Down: Zoom out / in" :parent "help-shortcuts"} {:id "sc-7" :text "Ctrl+B / Ctrl+I: Bold / Italic" :parent "help-shortcuts"} {:id "sc-8" :text "Backspace at start: Merge with previous node" :parent "help-shortcuts"} ;; Children of Markdown Formatting {:id "f-1" :text "**Bold** and *Italic*" :parent "help-formatting" :annotations [{:range-start 2 :range-end 6 :type :style :style :bold} {:range-start 13 :range-end 19 :type :style :style :italic}]} {:id "f-2" :text "==Highlight==" :parent "help-formatting" :annotations [{:range-start 2 :range-end 11 :type :style :style :highlight}]} {:id "f-3" :text "[Link](url)" :parent "help-formatting" :annotations [{:range-start 0 :range-end 11 :type :link :url "url"}]} {:id "f-4" :text "--- for horizontal line" :parent "help-formatting" :annotations [{:range-start 0 :range-end 3 :type :horizontal-line}]} ;; Children of lost+found (when user-id {:id lost-found-count-id :text "$lost-found-count" :annotations [] :parent lost-found-id})]) (defn strip-system-nodes [doc] (let [read-only? (fn [id] (get-in doc [:nodes id :read-only?])) nodes (into {} (remove (fn [[_ node]] (:read-only? node)) (:nodes doc))) root (vec (remove read-only? (:root doc)))] (assoc doc :nodes nodes :root root))) (defn inject-system-nodes [doc user-id] (let [clean-doc (strip-system-nodes doc)] (reduce (fn [d node] (if (nil? node) d (let [id (:id node) existing (get-in d [:nodes id])] (if existing (assoc-in d [:nodes id] (merge existing (assoc node :read-only? true))) (tree/insert-node d (assoc node :read-only? true) false))))) clean-doc (system-nodes user-id)))) (defn has-user-nodes? [doc] (boolean (some (fn [[_ node]] (not (:read-only? node))) (:nodes doc))))