| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- (ns frontend.components.rtc.indicator
- "RTC state indicator"
- (:require [cljs-time.core :as t]
- [clojure.pprint :as pprint]
- [frontend.db :as db]
- [frontend.handler.db-based.rtc-flows :as rtc-flows]
- [frontend.state :as state]
- [frontend.ui :as ui]
- [frontend.util :as util]
- [frontend.common.missionary :as c.m]
- [logseq.shui.ui :as shui]
- [missionary.core :as m]
- [rum.core :as rum]))
- (comment
- (def rtc-state-schema
- [:enum :open :close]))
- (defonce ^:private *detail-info
- (atom {:pending-local-ops 0
- :graph-uuid nil
- :local-tx nil
- :remote-tx nil
- :rtc-state :open
- :download-logs nil
- :upload-logs nil
- :misc-logs nil}))
- (defonce ^:private *update-detail-info-canceler (atom nil))
- (defn- run-task--update-detail-info
- []
- (when-let [canceler @*update-detail-info-canceler]
- (canceler)
- (reset! *update-detail-info-canceler nil))
- (letfn [(update-log-task [flow k]
- (m/reduce
- (fn [_ log]
- (when log
- (swap! *detail-info update k (fn [logs] (take 5 (conj logs log))))))
- flow))]
- (let [canceler (c.m/run-task
- (m/join
- (constantly nil)
- (update-log-task rtc-flows/rtc-download-log-flow :download-logs)
- (update-log-task rtc-flows/rtc-upload-log-flow :upload-logs)
- (update-log-task rtc-flows/rtc-misc-log-flow :misc-logs)
- (m/reduce (fn [_ state]
- (swap! *detail-info assoc
- :pending-local-ops (:unpushed-block-update-count state)
- :graph-uuid (:graph-uuid state)
- :local-tx (:local-tx state)
- :remote-tx (:remote-tx state)
- :rtc-state (if (:rtc-lock state) :open :close)))
- rtc-flows/rtc-state-stream-flow))
- ::update-detail-info)]
- (reset! *update-detail-info-canceler canceler))))
- (run-task--update-detail-info)
- (rum/defc assets-progressing < rum/reactive
- []
- (let [repo (state/get-current-repo)
- progress (state/sub :rtc/asset-upload-download-progress {:path-in-sub-atom [repo]})
- downloading (->>
- (keep (fn [[id {:keys [direction loaded total]}]]
- (when (and (= direction :download)
- (not= loaded total)
- (number? loaded) (number? total))
- (when-let [block (db/entity [:block/uuid (uuid id)])]
- {:block block
- :percent (int (* 100 (/ loaded total)))}))) progress)
- (sort-by (fn [{:keys [block]}] (:block/title block))))
- uploading (->> (keep (fn [[id {:keys [direction loaded total]}]]
- (when (and (= direction :upload)
- (not= loaded total)
- (number? loaded) (number? total))
- (when-let [block (db/entity [:block/uuid (uuid id)])]
- {:block block
- :percent (int (* 100 (/ loaded total)))}))) progress)
- (sort-by (fn [{:keys [block]}] (:block/title block))))]
- [:div.assets-sync-progress.flex.flex-col.gap-2
- (when (seq downloading)
- [:details
- [:summary
- (util/format "Downloading assets (%s)" (count downloading))]
- [:div.flex.flex-col.gap-1.text-sm
- (for [{:keys [block percent]} downloading]
- [:div.flex.flex-row.gap-1.items-center
- (ui/indicator-progress-pie percent)
- (:block/title block)])]])
- (when (seq uploading)
- [:details
- [:summary
- (util/format "Uploading assets (%s)" (count uploading))]
- [:div.flex.flex-col.gap-1.text-sm
- (for [{:keys [block percent]} uploading]
- [:div.flex.flex-row.gap-1.items-center
- (ui/indicator-progress-pie percent)
- (:block/title block)])]])]))
- (rum/defcs details < rum/reactive
- (rum/local false ::expand-debug-info?)
- [state online?]
- (let [*expand-debug? (::expand-debug-info? state)
- {:keys [graph-uuid local-tx remote-tx rtc-state
- download-logs upload-logs misc-logs pending-local-ops pending-server-ops]}
- (rum/react *detail-info)]
- [:div.rtc-info.flex.flex-col.gap-1.p-2.text-gray-11
- [:div.font-medium.mb-2 (if online? "Online" "Offline")]
- [:div [:span.font-medium.mr-1 (or pending-local-ops 0)] "pending local changes"]
- ;; FIXME: pending-server-ops
- [:div [:span.font-medium.mr-1 (or pending-server-ops 0)] "pending server changes"]
- (assets-progressing)
- ;; FIXME: What's the type for downloaded log?
- (when-let [latest-log (some (fn [l] (when (contains? #{:rtc.log/push-local-update} (:type l)) l)) misc-logs)]
- (when-let [time (:created-at latest-log)]
- [:div.text-sm "Last synced time: "
- (.toLocaleString time)]))
- [:a.fade-link.text-sm {:on-click #(swap! *expand-debug? not)}
- "More debug info"]
- (when @*expand-debug?
- [:div.rtc-info-debug
- [:pre.select-text
- (-> (cond-> {:pending-local-ops pending-local-ops}
- download-logs (assoc :download download-logs)
- upload-logs (assoc :upload upload-logs)
- misc-logs (assoc :misc misc-logs)
- graph-uuid (assoc :graph-uuid graph-uuid)
- local-tx (assoc :local-tx local-tx)
- remote-tx (assoc :remote-tx remote-tx)
- rtc-state (assoc :rtc-state rtc-state))
- pprint/pprint
- with-out-str)]])]))
- (defn- downloading?
- [detail-info]
- (when-let [{:keys [created-at sub-type]} (first (:download-logs detail-info))]
- (and (not= :download-completed sub-type)
- (> 600 ;; 10min
- (/ (- (t/now) created-at) 1000)))))
- (defn- uploading?
- [detail-info]
- (when-let [{:keys [created-at sub-type]} (first (:upload-logs detail-info))]
- (and (not= :upload-completed sub-type)
- (> 600
- (/ (- (t/now) created-at) 1000)))))
- (rum/defc indicator < rum/reactive
- []
- (let [detail-info (rum/react *detail-info)
- _ (state/sub :auth/id-token)
- online? (state/sub :network/online?)
- uploading?' (uploading? detail-info)
- downloading?' (downloading? detail-info)
- rtc-state (:rtc-state detail-info)
- unpushed-block-update-count (:pending-local-ops detail-info)]
- [:div.cp__rtc-sync
- [:div.cp__rtc-sync-indicator.flex.flex-row.items-center.gap-1
- (when downloading?'
- (shui/button
- {:class "opacity-50"
- :variant :ghost
- :size :sm}
- "Downloading..."))
- (when uploading?'
- (shui/button
- {:class "opacity-50"
- :variant :ghost
- :size :sm}
- "Uploading..."))
- (shui/button-ghost-icon :cloud
- {:on-click #(shui/popup-show! (.-target %)
- (details online?)
- {:align "end"})
- :class (util/classnames [{:cloud true
- :on (and online? (= :open rtc-state))
- :idle (and online? (= :open rtc-state) (zero? unpushed-block-update-count))
- :queuing (pos? unpushed-block-update-count)}])})]]))
|