Wallet status badge for offline RPC handling (#21484)
This commit is contained in:
parent
7acaff6167
commit
65c872c6ec
|
@ -94,13 +94,16 @@
|
|||
notification-count
|
||||
activity-center-on-press
|
||||
scan-on-press
|
||||
qr-code-on-press]
|
||||
qr-code-on-press
|
||||
right-section-content]
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
button-common-props (get-button-common-props {:theme theme
|
||||
:jump-to? jump-to?
|
||||
:blur? blur?})]
|
||||
[rn/view {:style style/right-section}
|
||||
(when right-section-content
|
||||
right-section-content)
|
||||
[button/button
|
||||
(assoc button-common-props :accessibility-label :open-scanner-button :on-press scan-on-press)
|
||||
:i/scan]
|
||||
|
@ -137,6 +140,7 @@
|
|||
:qr-code-on-press callback
|
||||
:notification-count number
|
||||
:max-unread-notifications used to specify max number for counter
|
||||
:right-section-content
|
||||
"
|
||||
[{:keys [avatar-on-press avatar-props customization-color container-style] :as props}]
|
||||
[rn/view {:style (merge style/top-nav-container container-style)}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
(ns quo.components.tags.network-status-tag.component-spec
|
||||
(:require
|
||||
[quo.components.tags.network-status-tag.view :as network-status-tag]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Network status component test"
|
||||
(h/test "5 min ago render"
|
||||
(h/render [network-status-tag/view
|
||||
{:label "Updated 5 min ago"}])
|
||||
(h/is-truthy (h/get-by-text "Updated 5 min ago")))
|
||||
(h/test "15 min ago render"
|
||||
(h/render [network-status-tag/view
|
||||
{:label "Updated 15 min ago"}])
|
||||
(h/is-truthy (h/get-by-text "Updated 15 min ago"))))
|
|
@ -0,0 +1,28 @@
|
|||
(ns quo.components.tags.network-status-tag.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def main
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:height 24})
|
||||
|
||||
(defn inner
|
||||
[theme]
|
||||
{:border-width 1
|
||||
:border-radius 12
|
||||
:flex 1
|
||||
:flex-direction :row
|
||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||
:align-items :center
|
||||
:padding-horizontal 8})
|
||||
|
||||
(def label
|
||||
{:color colors/warning-50
|
||||
:margin-left 6})
|
||||
|
||||
(def dot
|
||||
{:width 8
|
||||
:height 8
|
||||
:border-radius 8
|
||||
:background-color colors/warning-50})
|
|
@ -0,0 +1,19 @@
|
|||
(ns quo.components.tags.network-status-tag.view
|
||||
(:require
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.network-status-tag.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
[{:keys [label]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/main}
|
||||
[rn/view {:style (style/inner theme)}
|
||||
[rn/view {:style style/dot}]
|
||||
[text/text
|
||||
{:style style/label
|
||||
:weight :medium
|
||||
:size :label
|
||||
:align :center}
|
||||
label]]]))
|
|
@ -155,6 +155,7 @@
|
|||
quo.components.tabs.tabs.view
|
||||
quo.components.tags.collectible-tag.view
|
||||
quo.components.tags.context-tag.view
|
||||
quo.components.tags.network-status-tag.view
|
||||
quo.components.tags.network-tags.view
|
||||
quo.components.tags.number-tag.view
|
||||
quo.components.tags.permission-tag
|
||||
|
@ -438,6 +439,7 @@
|
|||
(def context-tag quo.components.tags.context-tag.view/view)
|
||||
(def network-tags quo.components.tags.network-tags.view/view)
|
||||
(def number-tag quo.components.tags.number-tag.view/view)
|
||||
(def network-status-tag quo.components.tags.network-status-tag.view/view)
|
||||
(def permission-tag quo.components.tags.permission-tag/tag)
|
||||
(def status-tag quo.components.tags.status-tags/status-tag)
|
||||
(def summary-tag quo.components.tags.summary-tag.view/view)
|
||||
|
|
|
@ -1,11 +1,26 @@
|
|||
(ns status-im.common.home.top-nav.view
|
||||
(:require
|
||||
[cljs-time.core :as t]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.home.top-nav.style :as style]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- network-status-label
|
||||
[now wallet-latest-update]
|
||||
(when (t/after? now (t/plus wallet-latest-update (t/minutes 5)))
|
||||
(let [units [{:name :t/datetime-second-short :limit 60 :in-second 1}
|
||||
{:name :t/datetime-minute-mid :limit 3600 :in-second 60}
|
||||
{:name :t/datetime-hour-short-lowercase :limit 86400 :in-second 3600}
|
||||
{:name :t/datetime-day :limit nil :in-second 86400}]
|
||||
time-ago (datetime/time-ago-long wallet-latest-update units)]
|
||||
[rn/view {:style {:justify-content :center}}
|
||||
[quo/network-status-tag {:label (i18n/label :t/wallet-updated-at {:at time-ago})}]])))
|
||||
|
||||
(defn view
|
||||
"[top-nav props]
|
||||
props
|
||||
|
@ -17,6 +32,8 @@
|
|||
online? (rf/sub [:visibility-status-updates/online?
|
||||
public-key])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
wallet-latest-update (rf/sub [:wallet/latest-update])
|
||||
wallet-blockchain-status (rf/sub [:wallet/blockchain-status])
|
||||
avatar {:online? online?
|
||||
:full-name (profile.utils/displayed-name profile)
|
||||
:profile-picture (profile.utils/photo profile)}
|
||||
|
@ -37,6 +54,9 @@
|
|||
{:avatar-on-press #(rf/dispatch [:open-modal :settings])
|
||||
:scan-on-press #(rf/dispatch [:open-modal :shell-qr-reader])
|
||||
:activity-center-on-press #(rf/dispatch [:activity-center/open])
|
||||
:right-section-content (when (and (= (:status wallet-blockchain-status) "down")
|
||||
wallet-latest-update)
|
||||
[network-status-label (t/now) wallet-latest-update])
|
||||
:qr-code-on-press #(rf/dispatch [:open-modal :screen/share-shell
|
||||
{:initial-tab initial-share-tab}])
|
||||
:container-style (merge style/top-nav-container container-style)
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
[status-im.contexts.preview.quo.tabs.tabs :as tabs]
|
||||
[status-im.contexts.preview.quo.tags.collectible-tag :as collectible-tag]
|
||||
[status-im.contexts.preview.quo.tags.context-tags :as context-tags]
|
||||
[status-im.contexts.preview.quo.tags.network-status-tag :as network-status-tag]
|
||||
[status-im.contexts.preview.quo.tags.network-tags :as network-tags]
|
||||
[status-im.contexts.preview.quo.tags.number-tag :as number-tag]
|
||||
[status-im.contexts.preview.quo.tags.permission-tag :as permission-tag]
|
||||
|
@ -520,6 +521,8 @@
|
|||
:component collectible-tag/view}
|
||||
{:name :context-tags
|
||||
:component context-tags/view}
|
||||
{:name :network-status-tag
|
||||
:component network-status-tag/view}
|
||||
{:name :network-tags
|
||||
:component network-tags/view}
|
||||
{:name :number-tag
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
(ns status-im.contexts.preview.quo.tags.network-status-tag
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :label :type :text}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:label "Updated 5 min ago"})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor}
|
||||
[rn/view {:style {:align-items :center}}
|
||||
[quo/network-status-tag @state]]])))
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.contexts.wallet.events
|
||||
(:require
|
||||
[camel-snake-kebab.extras :as cske]
|
||||
[cljs-time.coerce :as time-coerce]
|
||||
[clojure.set]
|
||||
[clojure.string :as string]
|
||||
[react-native.platform :as platform]
|
||||
|
@ -224,7 +225,8 @@
|
|||
{:error error
|
||||
:event :wallet/get-wallet-token-for-account
|
||||
:params address})
|
||||
{:db (assoc-in db [:wallet :ui :tokens-loading address] false)}))
|
||||
{:fx [[:dispatch [:wallet/get-last-wallet-token-update-if-needed]]]
|
||||
:db (assoc-in db [:wallet :ui :tokens-loading address] false)}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/store-wallet-token
|
||||
|
@ -240,10 +242,34 @@
|
|||
accounts))
|
||||
stored-accounts
|
||||
tokens-per-account))]
|
||||
{:db (-> db
|
||||
{:fx [[:dispatch [:wallet/get-last-wallet-token-update-if-needed]]]
|
||||
:db (-> db
|
||||
(update-in [:wallet :accounts] add-tokens tokens)
|
||||
(assoc-in [:wallet :ui :tokens-loading address] false))})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-last-wallet-token-update-if-needed
|
||||
(fn [{:keys [db]}]
|
||||
(let [all-tokens-loaded? (->> (get-in db [:wallet :ui :tokens-loading])
|
||||
vals
|
||||
(every? false?))]
|
||||
(when all-tokens-loaded?
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getLastWalletTokenUpdate"
|
||||
:params []
|
||||
:on-success [:wallet/get-last-wallet-token-update-success]
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/get-last-wallet-token-update-if-needed}]}]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-last-wallet-token-update-success
|
||||
(fn [{:keys [db]} [data]]
|
||||
(let [last-updates (reduce (fn [acc [k v]]
|
||||
(assoc acc k (time-coerce/from-long (* 1000 v))))
|
||||
{}
|
||||
data)]
|
||||
{:db (assoc-in db [:wallet :ui :last-updates-per-address] last-updates)})))
|
||||
|
||||
(rf/defn scan-address-success
|
||||
{:events [:wallet/scan-address-success]}
|
||||
[{:keys [db]} address]
|
||||
|
@ -653,3 +679,10 @@
|
|||
new-account-addresses)))))
|
||||
|
||||
(rf/reg-event-fx :wallet/reconcile-keypairs reconcile-keypairs)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/blockchain-health-changed
|
||||
(fn [{:keys [db]} [{:keys [message]}]]
|
||||
(let [full-status (cske/transform-keys message transforms/->kebab-case-keyword)]
|
||||
{:db (assoc-in db [:wallet :blockchain] full-status)})))
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@
|
|||
:dispatch [:wallet/blockchain-status-changed
|
||||
(transforms/js->clj event-js)]}]]]}
|
||||
|
||||
"wallet-blockchain-health-changed"
|
||||
{:fx [[:dispatch [:wallet/blockchain-health-changed (transforms/js->clj event-js)]]]}
|
||||
|
||||
"wallet-activity-filtering-done"
|
||||
{:fx
|
||||
[[:dispatch
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.subs.wallet.wallet
|
||||
(:require [clojure.string :as string]
|
||||
(:require [cljs-time.core :as t]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
|
@ -39,6 +40,33 @@
|
|||
:<- [:wallet/ui]
|
||||
:-> :scanned-address)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/last-updates-per-address
|
||||
:<- [:wallet/ui]
|
||||
:-> :last-updates-per-address)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/latest-update
|
||||
:<- [:wallet/last-updates-per-address]
|
||||
(fn [last-updates-per-address]
|
||||
(->> last-updates-per-address
|
||||
vals
|
||||
(reduce (fn [earliest-time last-update-time]
|
||||
(if (or (nil? earliest-time)
|
||||
(t/before? last-update-time earliest-time))
|
||||
last-update-time
|
||||
earliest-time))))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/blockchain
|
||||
:<- [:wallet]
|
||||
:-> :blockchain)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/blockchain-status
|
||||
:<- [:wallet/blockchain]
|
||||
:-> :status)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens
|
||||
:<- [:wallet]
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
(def day (* 24 hour))
|
||||
(def week (* 7 day))
|
||||
(defn weeks [w] (* w week))
|
||||
(def units
|
||||
(def default-units
|
||||
[{:name :t/datetime-second-short :limit 60 :in-second 1}
|
||||
{:name :t/datetime-minute-short :limit 3600 :in-second 60}
|
||||
{:name :t/datetime-hour-short :limit 86400 :in-second 3600}
|
||||
|
@ -272,27 +272,29 @@
|
|||
(let [diff (seconds-ago date-time)
|
||||
unit (first (drop-while #(and (>= diff (:limit %))
|
||||
(:limit %))
|
||||
units))]
|
||||
default-units))]
|
||||
(-> (/ diff (:in-second unit))
|
||||
Math/floor
|
||||
int
|
||||
(format-time-ago unit))))
|
||||
|
||||
(defn time-ago-long
|
||||
[date-time]
|
||||
(let [time-ago-seconds (seconds-ago date-time)
|
||||
unit (first (drop-while #(and (>= time-ago-seconds (:limit %))
|
||||
(:limit %))
|
||||
units))
|
||||
diff (-> (/ time-ago-seconds (:in-second unit))
|
||||
Math/floor
|
||||
int)
|
||||
([date-time units]
|
||||
(let [time-ago-seconds (seconds-ago date-time)
|
||||
unit (first (drop-while #(and (>= time-ago-seconds (:limit %))
|
||||
(:limit %))
|
||||
units))
|
||||
diff (-> (/ time-ago-seconds (:in-second unit))
|
||||
Math/floor
|
||||
int)
|
||||
|
||||
name (i18n/label-pluralize diff (:name unit))]
|
||||
(i18n/label :t/datetime-ago-format
|
||||
{:ago (i18n/label :t/datetime-ago)
|
||||
:number diff
|
||||
:time-intervals name})))
|
||||
name (i18n/label-pluralize diff (:name unit))]
|
||||
(i18n/label :t/datetime-ago-format
|
||||
{:ago (i18n/label :t/datetime-ago)
|
||||
:number diff
|
||||
:time-intervals name})))
|
||||
([date-time]
|
||||
(time-ago-long date-time default-units)))
|
||||
|
||||
(defn to-date
|
||||
[ms]
|
||||
|
|
|
@ -690,10 +690,18 @@
|
|||
"one": "H",
|
||||
"other": "H"
|
||||
},
|
||||
"datetime-hour-short-lowercase": {
|
||||
"one": "h",
|
||||
"other": "h"
|
||||
},
|
||||
"datetime-minute": {
|
||||
"one": "minute",
|
||||
"other": "minutes"
|
||||
},
|
||||
"datetime-minute-mid": {
|
||||
"one": "min",
|
||||
"other": "min"
|
||||
},
|
||||
"datetime-minute-short": {
|
||||
"one": "M",
|
||||
"other": "M"
|
||||
|
@ -2804,6 +2812,7 @@
|
|||
"wallet-settings": "Wallet settings",
|
||||
"wallet-total-value": "Total value",
|
||||
"wallet-transaction-total-fee": "Total Fee",
|
||||
"wallet-updated-at": "Updated {{at}}",
|
||||
"wants-to-access-profile": "wants to access to your profile",
|
||||
"wants-to-join": "wants to join",
|
||||
"warning": "Warning",
|
||||
|
|
Loading…
Reference in New Issue