diff --git a/deps.edn b/deps.edn new file mode 100644 index 0000000..f25c7da --- /dev/null +++ b/deps.edn @@ -0,0 +1,2 @@ +{:paths ["src" "resources"] + :deps {}} diff --git a/project.clj b/project.clj deleted file mode 100644 index e64bc67..0000000 --- a/project.clj +++ /dev/null @@ -1,8 +0,0 @@ -(defproject ring-refresh "0.2.0" - :description "Ring middleware for automatically refreshing HTML pages" - :url "https://github.com/weavejester/ring-refresh" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.9.0"] - [watchtower "0.1.1"] - [compojure "1.7.1"]]) diff --git a/resources/ring/js/refresh.js b/resources/ring/js/refresh.js index 8426fbc..bf7e66c 100644 --- a/resources/ring/js/refresh.js +++ b/resources/ring/js/refresh.js @@ -1,19 +1,28 @@ -var pageLoadTime = new Date().getTime() +var pageLoadTime = new Date().getTime(); -function reloadIfSourceChanged() { - var request = new XMLHttpRequest() - request.onreadystatechange = function() { - if (request.readyState == 4) { - if (request.responseText == 'true') { - window.location.reload() - } - else { - setTimeout(reloadIfSourceChanged, 200) + +async function reloadIfSourceChanged() { + try { + const response = await fetch('/__source_changed', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' } + }); + const text = await response.text() + const sourceChanged = parseInt(text); + + if (sourceChanged >= pageLoadTime) { + window.location.reload(); } + } catch (error) { + console.error('Error:', error); } - request.open('GET', '/__source_changed?since=' + pageLoadTime, true) - request.send() } -window.onload = reloadIfSourceChanged +async function reloadIfSourceChangedJob() { + await reloadIfSourceChanged() + setTimeout(reloadIfSourceChangedJob, 200); +} + +window.onload = reloadIfSourceChangedJob; diff --git a/src/ring/middleware/refresh.clj b/src/ring/middleware/refresh.clj index 6d98980..1b17991 100644 --- a/src/ring/middleware/refresh.clj +++ b/src/ring/middleware/refresh.clj @@ -1,17 +1,21 @@ (ns ring.middleware.refresh - (:refer-clojure :exclude [random-uuid]) - (:use [compojure.core :only (routes GET)] - [watchtower.core :only (watcher rate on-change)] - ring.middleware.params) (:require [clojure.string :as str] - [clojure.java.io :as io]) - (:import [java.util Date UUID])) + [clojure.java.io :as io])) + +(defn- dir-last-modified-ts [dir] + (when-let [files (file-seq (io/file dir))] + (apply max (map #(.lastModified %) files)))) + +(defn- dirs-last-modified-ts [dir & dirs] + (->> (cons dir dirs) + (mapv dir-last-modified-ts) + (reduce max))) (defn- get-request? [request] (= (:request-method request) :get)) (defn- html-content? [response] - (if-let [content-type (get-in response [:headers "Content-Type"])] + (when-let [content-type (get-in response [:headers "Content-Type"])] (re-find #"text/html" content-type))) (def ^:private refresh-script @@ -33,45 +37,22 @@ (as-str [_] nil)) (defn- add-script [body script] - (if-let [body-str (as-str body)] + (when-let [body-str (as-str body)] (str/replace body-str - #"]+)?>" - #(str % "")))) - -(def ^:private last-modified - (atom (Date.))) - -(defn- watch-dirs! [dirs] - (watcher dirs - (rate 100) - (on-change - (fn [_] (reset! last-modified (Date.)))))) - -(defn- random-uuid [] - (str (UUID/randomUUID))) + #"" + #(str "\n\n" %)))) -(defn- watch-until [reference pred timeout-ms] - (let [result (promise) - watch-key (random-uuid)] - (try - (add-watch reference - watch-key - (fn [_ _ _ value] - (when (pred value) - (deliver result true)))) - (or (pred @reference) - (deref result timeout-ms false)) - (finally - (remove-watch reference watch-key))))) +(defn- source-changed-handler [_ dirs] + {:status 200 + :headers {"Content-Type" "application/json"} + :body (str (apply dirs-last-modified-ts dirs))}) -(def ^:private source-changed-route - (GET "/__source_changed" [since] - (let [timestamp (Long. since)] - (str (watch-until - last-modified - #(> (.getTime %) timestamp) - 60000))))) +(defn- intercept-source-changed-route [handler dirs] + (fn [{:keys [uri] :as request}] + (if (= uri "/__source_changed") + (source-changed-handler request dirs) + (handler request)))) (defn- wrap-with-script [handler script] (fn [request] @@ -91,8 +72,6 @@ ([handler] (wrap-refresh handler ["src" "resources"])) ([handler dirs] - (watch-dirs! dirs) - (wrap-params - (routes - source-changed-route - (wrap-with-script handler refresh-script))))) + (fn [request] + (let [wrapped (-> handler (intercept-source-changed-route dirs) (wrap-with-script refresh-script))] + (wrapped request)))))