<commit_before>(ns lt.objs.app
  (:require [lt.object :as object]
            [lt.objs.command :as cmd]
            [lt.objs.context :as ctx]
            [clojure.string :as string]
            [lt.util.js :refer [now]]
            [lt.util.dom :refer [$] :as dom])
  (:require-macros [lt.macros :refer [behavior]]))

(def gui (js/require "nw.gui"))
(def win (.Window.get gui))
(def closing true)

(defn window-number []
  (let [n (last (string/split js/window.location.search "="))]
    (if (empty? n)
      0
      (js/parseInt n))))

(set! (.-ltid win) (window-number))

(defn prevent-close []
  (set! closing false))

(defn close [force?]
  (when force?
    (object/raise app :closing)
    (object/raise app :closed))
  (.close win force?))

(defn refresh []
  (js/window.location.reload true))

(defn open-window []
  (let [id (store-swap! :window-id inc)
        w (.Window.open gui (str "LightTable.html?id=" id) (clj->js {:toolbar false
                                                                     :icon "core/img/lticon.png"
                                                                     :new-instance true
                                                                     :min_height 400
                                                                     :min_width 400
                                                                     :frame true
                                                                     :show false}))]
    (set! (.-ltid w) id)
    w))

(defn args []
  (when-not (= 0 (.-App.argv.length gui))
    (seq (.-App.argv gui))))

(defn init []
  (object/raise app :deploy)
  (object/raise app :pre-init)
  (object/raise app :init)
  (object/raise app :post-init)
  (object/raise app :show))

(defn fetch [k]
  (when-let [v (aget js/localStorage (name k))]
    (when (not= "null" v)
      (js/JSON.parse v))))

(defn store! [k v]
  (aset js/localStorage (name k) (if (string? v)
                                   (pr-str v)
                                   v)))

(defn extract! [k]
  (let [v (fetch k)]
    (store! k nil)
    v))

(defn store-swap! [k f]
  (let [neue (f (fetch k))]
    (store! k neue)
    neue))


(defn ensure-greater [x cap]
  (let [x (if (string? x)
            (js/parseInt x)
            x)]
    (max x cap)))

(defn zoom-level []
  (when (not= (.-zoomLevel win) 0)
    (.-zoomLevel win)))

;;*********************************************************
;; Behaviors
;;*********************************************************

(behavior ::refresh
                  :triggers #{:refresh}
                  :reaction (fn [obj]
                              (set! closing true)
                              (object/raise app :reload)
                              (when closing
                                (refresh))))

(behavior ::close!
                  :triggers #{:close!}
                  :reaction (fn [this]
                              (set! closing true)
                              (object/raise this :close)
                              (when closing
                                (close true))))

(behavior ::store-position-on-close
                  :triggers #{:closed :refresh}
                  :reaction (fn [this]
                              (when-not (.-isFullscreen win)
                                (set! js/localStorage.x (.-x win))
                                (set! js/localStorage.y (.-y win))
                                (set! js/localStorage.width (.-width win))
                                (set! js/localStorage.height (.-height win))
                                (set! js/localStorage.fullscreen (.-isFullscreen win)))))

(behavior ::restore-fullscreen
                  :triggers #{:show}
                  :reaction (fn [this]
                                (when (= js/localStorage.fullscreen "true")
                                  (.enterFullscreen win))))

(behavior ::restore-position-on-init
                  :triggers #{:show}
                  :reaction (fn [this]
                              (when-not (empty? (.-width js/localStorage))
                                (.resizeTo win (ensure-greater js/localStorage.width 400) (ensure-greater js/localStorage.height 400))
                                (.moveTo win (ensure-greater js/localStorage.x 0) (ensure-greater js/localStorage.y 0)))))

(behavior ::on-show-bind-navigate
                  :triggers #{:show}
                  :reaction (fn [this]
                              (dom/on ($ :#canvas) :click (fn [e]
                                                            ;;TODO: when prevent default has been called don't do this.
                                                            (when (= (.-target.nodeName e) "A")
                                                              (dom/prevent e)
                                                              (when-let [href (.-target.href e)]
                                                                (.Shell.openExternal gui href)
                                                                (.focus win)))))))

(behavior ::initial-focus
                  :triggers #{:show}
                  :reaction (fn [this]
                              ;(dom/focus (dom/$ :body))
                              ;(.focus win)
                              ))

(behavior ::run-on-init
                  :triggers #{:init}
                  :desc "App: Run commands on start"
                  :params [{:label "commands"
                            :type :list<commit_msg>when opening a new window make sure it has focus<commit_after>(ns lt.objs.app
  (:require [lt.object :as object]
            [lt.objs.command :as cmd]
            [lt.objs.context :as ctx]
            [clojure.string :as string]
            [lt.util.js :refer [now]]
            [lt.util.dom :refer [$] :as dom])
  (:require-macros [lt.macros :refer [behavior]]))

(def gui (js/require "nw.gui"))
(def win (.Window.get gui))
(def closing true)

(defn window-number []
  (let [n (last (string/split js/window.location.search "="))]
    (if (empty? n)
      0
      (js/parseInt n))))

(set! (.-ltid win) (window-number))

(defn prevent-close []
  (set! closing false))

(defn close [force?]
  (when force?
    (object/raise app :closing)
    (object/raise app :closed))
  (.close win force?))

(defn refresh []
  (js/window.location.reload true))

(defn open-window []
  (let [id (store-swap! :window-id inc)
        w (.Window.open gui (str "LightTable.html?id=" id) (clj->js {:toolbar false
                                                                     :icon "core/img/lticon.png"
                                                                     :new-instance true
                                                                     :min_height 400
                                                                     :min_width 400
                                                                     :frame true
                                                                     :show false}))]
    (set! (.-ltid w) id)
    w))

(defn args []
  (when-not (= 0 (.-App.argv.length gui))
    (seq (.-App.argv gui))))

(defn init []
  (object/raise app :deploy)
  (object/raise app :pre-init)
  (object/raise app :init)
  (object/raise app :post-init)
  (object/raise app :show))

(defn fetch [k]
  (when-let [v (aget js/localStorage (name k))]
    (when (not= "null" v)
      (js/JSON.parse v))))

(defn store! [k v]
  (aset js/localStorage (name k) (if (string? v)
                                   (pr-str v)
                                   v)))

(defn extract! [k]
  (let [v (fetch k)]
    (store! k nil)
    v))

(defn store-swap! [k f]
  (let [neue (f (fetch k))]
    (store! k neue)
    neue))


(defn ensure-greater [x cap]
  (let [x (if (string? x)
            (js/parseInt x)
            x)]
    (max x cap)))

(defn zoom-level []
  (when (not= (.-zoomLevel win) 0)
    (.-zoomLevel win)))

;;*********************************************************
;; Behaviors
;;*********************************************************

(behavior ::refresh
                  :triggers #{:refresh}
                  :reaction (fn [obj]
                              (set! closing true)
                              (object/raise app :reload)
                              (when closing
                                (refresh))))

(behavior ::close!
                  :triggers #{:close!}
                  :reaction (fn [this]
                              (set! closing true)
                              (object/raise this :close)
                              (when closing
                                (close true))))

(behavior ::store-position-on-close
                  :triggers #{:closed :refresh}
                  :reaction (fn [this]
                              (when-not (.-isFullscreen win)
                                (set! js/localStorage.x (.-x win))
                                (set! js/localStorage.y (.-y win))
                                (set! js/localStorage.width (.-width win))
                                (set! js/localStorage.height (.-height win))
                                (set! js/localStorage.fullscreen (.-isFullscreen win)))))

(behavior ::restore-fullscreen
                  :triggers #{:show}
                  :reaction (fn [this]
                                (when (= js/localStorage.fullscreen "true")
                                  (.enterFullscreen win))))

(behavior ::restore-position-on-init
                  :triggers #{:show}
                  :reaction (fn [this]
                              (when-not (empty? (.-width js/localStorage))
                                (.resizeTo win (ensure-greater js/localStorage.width 400) (ensure-greater js/localStorage.height 400))
                                (.moveTo win (ensure-greater js/localStorage.x 0) (ensure-greater js/localStorage.y 0)))))

(behavior ::on-show-bind-navigate
                  :triggers #{:show}
                  :reaction (fn [this]
                              (dom/on ($ :#canvas) :click (fn [e]
                                                            ;;TODO: when prevent default has been called don't do this.
                                                            (when (= (.-target.nodeName e) "A")
                                                              (dom/prevent e)
                                                              (when-let [href (.-target.href e)]
                                                                (.Shell.openExternal gui href)
                                                                (.focus win)))))))

(behavior ::initial-focus
                  :triggers #{:show}
                  :reaction (fn [this]
                              ;(dom/focus (dom/$ :body))
                              (.focus win)
                              ))

(behavior ::run-on-init
                  :triggers #{:init}
                  :desc "App: Run commands on start"
                  :params [{:label "commands"
                            :type :list
{'fraction_non_alphanumeric': 0.14325539568345325, 'fraction_numerical': 0.0030575539568345324, 'mean_word_length': 1.0717213114754098, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 66, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '769693', 'n_tokens_mistral': 2981, 'n_tokens_neox': 2806, 'n_words': 770}