Jelajahi Sumber

feat(sync): add sync history

rcmerci 3 tahun lalu
induk
melakukan
3c9c500959

+ 15 - 3
src/main/frontend/components/header.cljs

@@ -61,7 +61,9 @@
         not-syncing? (or (nil? sync-state) (fs-sync/-stopped? sync-state))
         *existed-graphs (::existed-graphs state)
         _ (rum/react file-sync-handler/refresh-file-sync-component)
-        graph-txid-exists? (file-sync-handler/graph-txid-exists?)]
+        graph-txid-exists? (file-sync-handler/graph-txid-exists?)
+        uploading-files (state/sub :file-sync/sync-uploading-files)
+        downloading-files (state/sub :file-sync/sync-downloading-files)]
     (when-not config/publishing?
       (when (user-handler/logged?)
         (when-not (file-sync-handler/graph-txid-exists?)
@@ -88,8 +90,18 @@
                     {:title "create graph"
                      :options {:on-click #(file-sync-handler/create-graph (path/basename (state/get-current-repo)))}}])
            graph-txid-exists?
-           (conj {:title "toggle file sync"
-                  :options {:on-click #(if not-syncing? (fs-sync/sync-start) (fs-sync/sync-stop))}}))
+           (concat
+            [{:title "toggle file sync"
+              :options {:on-click #(if not-syncing? (fs-sync/sync-start) (fs-sync/sync-stop))} }]
+            [{:hr true}]
+            (map (fn [f] {:title f
+                          :icon (ui/icon "arrow-narrow-up")}) uploading-files)
+            (map (fn [f] {:title f
+                          :icon (ui/icon "arrow-narrow-down")}) downloading-files)
+            (when sync-state
+              (map (fn [f] (:time f)
+                     {:title [:div [:div (:path f)] [:div (util/time-ago (:time f))]]})
+                   (take 10 (.-history sync-state))))))
 
          (cond-> {}
            (not graph-txid-exists?) (assoc :links-header [:div.font-medium.text-sm.opacity-60.px-4.pt-2

+ 10 - 0
src/main/frontend/fs/sync.cljs

@@ -1,6 +1,7 @@
 (ns frontend.fs.sync
   (:require ["path" :as path]
             [cljs-http.client :as http]
+            [cljs-time.core :as t]
             [cljs.core.async :as async :refer [go timeout go-loop offer! poll! chan <! >!]]
             [cljs.core.async.interop :refer [p->c]]
             [clojure.set :as set]
@@ -712,6 +713,13 @@
 (deftype SyncState [^:mutable state ^:mutable current-local->remote-files ^:mutable current-remote->local-files
                     ^:mutable history]
   Object
+  (add-to-history [_ fs]
+    (let [now (t/now)]
+      (->> fs
+           (map (fn [p] {:path p :time now}))
+           (apply conj history)
+           (set! history))))
+
   (update-state! [this v]
     (set! state v)
     (state/set-file-sync-state v))
@@ -723,9 +731,11 @@
     (state/set-file-sync-downloading-files current-remote->local-files))
   (remove-current-local->remote-files! [this fs]
     (set! current-local->remote-files (set/difference current-local->remote-files (set fs)))
+    (.add-to-history this fs)
     (state/set-file-sync-uploading-files current-local->remote-files))
   (remove-current-remote->local-files! [this fs]
     (set! current-remote->local-files (set/difference current-remote->local-files (set fs)))
+    (.add-to-history this fs)
     (state/set-file-sync-downloading-files current-remote->local-files))
   (reset-current-local->remote-files! [this]
     (set! current-local->remote-files #{})

+ 21 - 0
src/main/frontend/util.cljc

@@ -1453,3 +1453,24 @@
 #?(:cljs
    (defn atom? [v]
      (instance? Atom v)))
+
+;; https://stackoverflow.com/questions/32511405/how-would-time-ago-function-implementation-look-like-in-clojure
+#?(:cljs
+   (defn time-ago [time]
+     (let [units [{:name "second" :limit 60 :in-second 1}
+                  {:name "minute" :limit 3600 :in-second 60}
+                  {:name "hour" :limit 86400 :in-second 3600}
+                  {:name "day" :limit 604800 :in-second 86400}
+                  {:name "week" :limit 2629743 :in-second 604800}
+                  {:name "month" :limit 31556926 :in-second 2629743}
+                  {:name "year" :limit js/Number.MAX_SAFE_INTEGER :in-second 31556926}]
+           diff (t/in-seconds (t/interval time (t/now)))]
+       (if (< diff 5)
+         "just now"
+         (let [unit (first (drop-while #(or (>= diff (:limit %))
+                                            (not (:limit %)))
+                                       units))]
+           (-> (/ diff (:in-second unit))
+               Math/floor
+               int
+               (#(str % " " (:name unit) (when (> % 1) "s") " ago"))))))))