indicator.cljs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. (ns frontend.components.rtc.indicator
  2. "RTC state indicator"
  3. (:require [cljs-time.core :as t]
  4. [clojure.pprint :as pprint]
  5. [frontend.db :as db]
  6. [frontend.handler.db-based.rtc-flows :as rtc-flows]
  7. [frontend.state :as state]
  8. [frontend.ui :as ui]
  9. [frontend.util :as util]
  10. [frontend.common.missionary :as c.m]
  11. [logseq.shui.ui :as shui]
  12. [missionary.core :as m]
  13. [rum.core :as rum]))
  14. (comment
  15. (def rtc-state-schema
  16. [:enum :open :close]))
  17. (defonce ^:private *detail-info
  18. (atom {:pending-local-ops 0
  19. :graph-uuid nil
  20. :local-tx nil
  21. :remote-tx nil
  22. :rtc-state :open
  23. :download-logs nil
  24. :upload-logs nil
  25. :misc-logs nil}))
  26. (defonce ^:private *update-detail-info-canceler (atom nil))
  27. (defn- run-task--update-detail-info
  28. []
  29. (when-let [canceler @*update-detail-info-canceler]
  30. (canceler)
  31. (reset! *update-detail-info-canceler nil))
  32. (letfn [(update-log-task [flow k]
  33. (m/reduce
  34. (fn [_ log]
  35. (when log
  36. (swap! *detail-info update k (fn [logs] (take 5 (conj logs log))))))
  37. flow))]
  38. (let [canceler (c.m/run-task
  39. (m/join
  40. (constantly nil)
  41. (update-log-task rtc-flows/rtc-download-log-flow :download-logs)
  42. (update-log-task rtc-flows/rtc-upload-log-flow :upload-logs)
  43. (update-log-task rtc-flows/rtc-misc-log-flow :misc-logs)
  44. (m/reduce (fn [_ state]
  45. (swap! *detail-info assoc
  46. :pending-local-ops (:unpushed-block-update-count state)
  47. :graph-uuid (:graph-uuid state)
  48. :local-tx (:local-tx state)
  49. :remote-tx (:remote-tx state)
  50. :rtc-state (if (:rtc-lock state) :open :close)))
  51. rtc-flows/rtc-state-stream-flow))
  52. ::update-detail-info)]
  53. (reset! *update-detail-info-canceler canceler))))
  54. (run-task--update-detail-info)
  55. (rum/defc assets-progressing < rum/reactive
  56. []
  57. (let [repo (state/get-current-repo)
  58. progress (state/sub :rtc/asset-upload-download-progress {:path-in-sub-atom [repo]})
  59. downloading (->>
  60. (keep (fn [[id {:keys [direction loaded total]}]]
  61. (when (and (= direction :download)
  62. (not= loaded total)
  63. (number? loaded) (number? total))
  64. (when-let [block (db/entity [:block/uuid (uuid id)])]
  65. {:block block
  66. :percent (int (* 100 (/ loaded total)))}))) progress)
  67. (sort-by (fn [{:keys [block]}] (:block/title block))))
  68. uploading (->> (keep (fn [[id {:keys [direction loaded total]}]]
  69. (when (and (= direction :upload)
  70. (not= loaded total)
  71. (number? loaded) (number? total))
  72. (when-let [block (db/entity [:block/uuid (uuid id)])]
  73. {:block block
  74. :percent (int (* 100 (/ loaded total)))}))) progress)
  75. (sort-by (fn [{:keys [block]}] (:block/title block))))]
  76. [:div.assets-sync-progress.flex.flex-col.gap-2
  77. (when (seq downloading)
  78. [:details
  79. [:summary
  80. (util/format "Downloading assets (%s)" (count downloading))]
  81. [:div.flex.flex-col.gap-1.text-sm
  82. (for [{:keys [block percent]} downloading]
  83. [:div.flex.flex-row.gap-1.items-center
  84. (ui/indicator-progress-pie percent)
  85. (:block/title block)])]])
  86. (when (seq uploading)
  87. [:details
  88. [:summary
  89. (util/format "Uploading assets (%s)" (count uploading))]
  90. [:div.flex.flex-col.gap-1.text-sm
  91. (for [{:keys [block percent]} uploading]
  92. [:div.flex.flex-row.gap-1.items-center
  93. (ui/indicator-progress-pie percent)
  94. (:block/title block)])]])]))
  95. (rum/defcs details < rum/reactive
  96. (rum/local false ::expand-debug-info?)
  97. [state online?]
  98. (let [*expand-debug? (::expand-debug-info? state)
  99. {:keys [graph-uuid local-tx remote-tx rtc-state
  100. download-logs upload-logs misc-logs pending-local-ops pending-server-ops]}
  101. (rum/react *detail-info)]
  102. [:div.rtc-info.flex.flex-col.gap-1.p-2.text-gray-11
  103. [:div.font-medium.mb-2 (if online? "Online" "Offline")]
  104. [:div [:span.font-medium.mr-1 (or pending-local-ops 0)] "pending local changes"]
  105. ;; FIXME: pending-server-ops
  106. [:div [:span.font-medium.mr-1 (or pending-server-ops 0)] "pending server changes"]
  107. (assets-progressing)
  108. ;; FIXME: What's the type for downloaded log?
  109. (when-let [latest-log (some (fn [l] (when (contains? #{:rtc.log/push-local-update} (:type l)) l)) misc-logs)]
  110. (when-let [time (:created-at latest-log)]
  111. [:div.text-sm "Last synced time: "
  112. (.toLocaleString time)]))
  113. [:a.fade-link.text-sm {:on-click #(swap! *expand-debug? not)}
  114. "More debug info"]
  115. (when @*expand-debug?
  116. [:div.rtc-info-debug
  117. [:pre.select-text
  118. (-> (cond-> {:pending-local-ops pending-local-ops}
  119. download-logs (assoc :download download-logs)
  120. upload-logs (assoc :upload upload-logs)
  121. misc-logs (assoc :misc misc-logs)
  122. graph-uuid (assoc :graph-uuid graph-uuid)
  123. local-tx (assoc :local-tx local-tx)
  124. remote-tx (assoc :remote-tx remote-tx)
  125. rtc-state (assoc :rtc-state rtc-state))
  126. pprint/pprint
  127. with-out-str)]])]))
  128. (defn- downloading?
  129. [detail-info]
  130. (when-let [{:keys [created-at sub-type]} (first (:download-logs detail-info))]
  131. (and (not= :download-completed sub-type)
  132. (> 600 ;; 10min
  133. (/ (- (t/now) created-at) 1000)))))
  134. (defn- uploading?
  135. [detail-info]
  136. (when-let [{:keys [created-at sub-type]} (first (:upload-logs detail-info))]
  137. (and (not= :upload-completed sub-type)
  138. (> 600
  139. (/ (- (t/now) created-at) 1000)))))
  140. (rum/defc indicator < rum/reactive
  141. []
  142. (let [detail-info (rum/react *detail-info)
  143. _ (state/sub :auth/id-token)
  144. online? (state/sub :network/online?)
  145. uploading?' (uploading? detail-info)
  146. downloading?' (downloading? detail-info)
  147. rtc-state (:rtc-state detail-info)
  148. unpushed-block-update-count (:pending-local-ops detail-info)]
  149. [:div.cp__rtc-sync
  150. [:div.cp__rtc-sync-indicator.flex.flex-row.items-center.gap-1
  151. (when downloading?'
  152. (shui/button
  153. {:class "opacity-50"
  154. :variant :ghost
  155. :size :sm}
  156. "Downloading..."))
  157. (when uploading?'
  158. (shui/button
  159. {:class "opacity-50"
  160. :variant :ghost
  161. :size :sm}
  162. "Uploading..."))
  163. (shui/button-ghost-icon :cloud
  164. {:on-click #(shui/popup-show! (.-target %)
  165. (details online?)
  166. {:align "end"})
  167. :class (util/classnames [{:cloud true
  168. :on (and online? (= :open rtc-state))
  169. :idle (and online? (= :open rtc-state) (zero? unpushed-block-update-count))
  170. :queuing (pos? unpushed-block-update-count)}])})]]))