indicator.cljs 8.0 KB

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