[#11716] Implement new Connectivity dialogues and remove 'Offline' snackbars

Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
andrey 2021-02-10 11:34:36 +01:00
parent 8d3fa3c3d7
commit 7c04bb9076
No known key found for this signature in database
GPG Key ID: 89B67245FD2F0272
20 changed files with 195 additions and 290 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -43,6 +43,9 @@
:accent {:icon-color (:icon-05 @colors/theme)
:background-color (:interactive-01 @colors/theme)
:text-color (:text-05 @colors/theme)}
:secondary {:icon-color (:icon-02 @colors/theme)
:background-color (:interactive-02 @colors/theme)
:text-color (:text-02 @colors/theme)}
:disabled {:icon-color (:icon-02 @colors/theme)
:background-color (:ui-01 @colors/theme)
:text-color (:text-02 @colors/theme)}))

View File

@ -208,7 +208,9 @@
(on-long-press))}))
[container {:size size}
[left-side {:icon-color icon-color
:text-color text-color
:text-color (if on-press
text-color
(:text-color (themes :main)))
:icon-bg-color icon-bg-color
:title-accessibility-label title-accessibility-label
:icon icon

View File

@ -850,6 +850,14 @@
(fn [[ranges chat-id]]
(get ranges chat-id)))
(re-frame/reg-sub
:mailserver/current-name
:<- [:mailserver/current-id]
:<- [:fleets/current-fleet]
:<- [:mailserver/mailservers]
(fn [[current-mailserver-id current-fleet mailservers]]
(get-in mailservers [current-fleet current-mailserver-id :name])))
(re-frame/reg-sub
:chats/all-loaded?
:<- [::pagination-info]
@ -1743,54 +1751,41 @@
;;UI ==============================================================================================================
;;TODO this subscription looks super weird huge and with dispatches?
(re-frame/reg-sub
:connectivity/status-properties
:connectivity/state
:<- [:network-status]
:<- [:disconnected?]
:<- [:mailserver/connecting?]
:<- [:mailserver/connection-error?]
:<- [:mailserver/request-error?]
:<- [:mailserver/fetching?]
:<- [:network/type]
:<- [:multiaccount]
(fn [[network-status disconnected? mailserver-connecting? mailserver-connection-error?
mailserver-request-error? mailserver-fetching? network-type multiaccount]]
(let [error-label (cond
mailserver-request-error? network-type {:keys [syncing-on-mobile-network? use-mailservers?]}]]
(merge {:mobile (mobile-network-utils/cellular? network-type)
:sync syncing-on-mobile-network?
:peers :online}
(cond
(= network-status :offline)
:t/offline
{:peers :offline
:node :offline}
mailserver-connecting?
:t/connecting
(not use-mailservers?)
{:node :disabled}
mailserver-connection-error?
:t/mailserver-reconnect
(or mailserver-connection-error? mailserver-connecting?)
{:node :connecting}
mailserver-request-error?
:t/mailserver-request-error-status
(and (mobile-network-utils/cellular? network-type)
(not (:syncing-on-mobile-network? multiaccount)))
:mobile-network
{:node :error}
disconnected?
:t/offline
{:peers :offline
:node :offline}
:else nil)
connected? (and (nil? error-label) (not= :mobile-network error-label))]
{:message (or error-label :t/connected)
:connected? connected?
:connecting? (= error-label :t/connecting)
:loading-indicator? (and mailserver-fetching? connected?)
:on-press-event (cond
mailserver-connection-error?
:mailserver.ui/reconnect-mailserver-pressed
mailserver-request-error?
:mailserver.ui/request-error-pressed
(= :mobile-network error-label)
:mobile-network/show-offline-sheet)})))
:else
{:peers :online
:node :online}))))
;;CONTACT ==============================================================================================================

View File

@ -1,17 +0,0 @@
(ns status-im.ui.components.connectivity.styles
(:require [status-im.ui.components.colors :as colors]))
(defn text-wrapper
[{:keys [window-width height background-color opacity transform]}]
{:flex-direction :row
:justify-content :center
:transform [{:translateY transform}]
:opacity opacity
:background-color (or background-color colors/gray)
:height height
:width window-width})
(def text
{:color colors/white
:font-size 14
:top 8})

View File

@ -4,21 +4,12 @@
[status-im.i18n :as i18n]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.connectivity.styles :as styles]
[status-im.ui.components.react :as react]
[status-im.utils.datetime :as datetime]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log])
[quo.core :as quo]
[clojure.string :as string])
(:require-macros
[status-im.utils.views :as views :refer [defview letsubs]]))
;; ui-connectivity-status delays
(def standard-delay 1000)
(def long-delay 5000)
;; millisec window from foreground\login within which use long delay
(def timewindow-for-long-delay 5000)
(defn easing [direction n]
{:toValue n
:easing ((if (= :in direction)
@ -39,7 +30,7 @@
:height 3
:background-color color})
(views/defview loading-indicator [parent-width]
(views/defview loading-indicator-anim [parent-width]
(views/letsubs [blue-bar-left-margin (animation/create-value 0)
white-bar-left-margin (animation/create-value 0)]
{:component-did-mount
@ -74,195 +65,106 @@
colors/white)
:left (* 0.15 parent-width))}]]))
(def to-hide? (reagent/atom false))
(defn manage-visibility
"status-hidden is a per-view state, while to-hide? is a global state common to
all connectivity views (we have at least one view in home and one in chat)"
[connected? animate? anim-opacity anim-y status-hidden connectivity-bar-height]
(let [neg-connectivity-bar-height (- @connectivity-bar-height)]
(if connected?
(if animate?
(when (and @to-hide? (not @status-hidden))
(animation/start
(animation/parallel
[(animation/timing anim-opacity
{:toValue 0
:delay 800
:duration 150
:easing (.-ease ^js animation/easing)
:useNativeDriver true})
(animation/timing anim-y
{:toValue neg-connectivity-bar-height
:delay 800
:duration 150
:easing (.-ease ^js animation/easing)
:useNativeDriver true})])
;; second param of start() - a callback that fires when animation stops
#(do (reset! to-hide? false) (reset! status-hidden true))))
(do
(animation/set-value anim-opacity 0)
(animation/set-value anim-y neg-connectivity-bar-height)
(reset! to-hide? false)
(reset! status-hidden true)))
;; else
(if animate?
(when (and (not @to-hide?) @status-hidden)
(animation/start
(animation/parallel
[(animation/timing anim-opacity
{:toValue 1
:duration 150
:easing (.-ease ^js animation/easing)
:useNativeDriver true})
(animation/timing anim-y
{:toValue 0
:duration 150
:easing (.-ease ^js animation/easing)
:useNativeDriver true})])
;; second param of start() - a callback that fires when animation stops
#(do (reset! to-hide? true) (reset! status-hidden false))))
(do
(animation/set-value anim-opacity 1)
(animation/set-value anim-y 0)
(reset! to-hide? true)
(reset! status-hidden false))))))
(defn connectivity-status
[{:keys [connected?]} status-hidden height]
(let [neg-connectivity-bar-height (- @height)
anim-translate-y (animation/create-value neg-connectivity-bar-height)
anim-opacity (animation/create-value 0)]
(reagent/create-class
{:component-did-mount
(fn []
(manage-visibility connected? false
anim-opacity anim-translate-y status-hidden height))
:should-component-update
;; ignore :loading-indicator?
(fn [_ [_ old_p] [_ new_p]]
(not= (dissoc old_p :loading-indicator?)
(dissoc new_p :loading-indicator?)))
:component-did-update
(fn [comp]
(manage-visibility (:connected? (reagent/props comp)) true
anim-opacity anim-translate-y status-hidden height))
:reagent-render
(fn [{:keys [message on-press-event connected? connecting?] :as opts}]
(when-not @status-hidden
[react/animated-view {:style (styles/text-wrapper
(assoc opts
:height @height
:background-color (if connected?
colors/green
colors/gray)
:transform anim-translate-y
:opacity anim-opacity))
:accessibility-label :connection-status-text}
(when connecting?
[react/activity-indicator {:color colors/white :margin-right 6}])
(if (= message :mobile-network)
[react/nested-text {:style styles/text
:on-press (when on-press-event #(re-frame/dispatch [on-press-event]))}
(i18n/label :t/waiting-for-wifi) " "
[{:style {:text-decoration-line :underline}}
(i18n/label :t/waiting-for-wifi-change)]]
(when message
[react/text {:style styles/text
:on-press (when on-press-event #(re-frame/dispatch [on-press-event]))}
(i18n/label message)]))]))})))
(defn connectivity-status-comp
[_ _]
(let [height (reagent/atom 36)]
(fn [props status-hidden]
[react/view {}
(when-not @status-hidden
[react/text {:style (merge styles/text {:position :absolute
:opacity 0})
:on-layout (fn [e]
(let [h (-> e .-nativeEvent .-layout .-height)]
(reset! height (+ h (* (:top styles/text) 2)))))}
(i18n/label (:message props))])
[connectivity-status props status-hidden height]])))
;; timer updating the enqueued status
(def timer (atom nil))
;; connectivity status change going to be persisted to :connectivity/ui-status-properties
(def enqueued-connectivity-status-properties (atom nil))
(defn propagate-status
"Smoothly propagate from :connectivity/status-properties subscription to
:ui-status-properties db. UI components will render based on :ui-status-properties"
[{:keys [status-properties app-active-since logged-in-since ui-status-properties]}]
(when (or (and (nil? @enqueued-connectivity-status-properties)
(not= status-properties ui-status-properties))
(and (some? @enqueued-connectivity-status-properties)
(not= status-properties @enqueued-connectivity-status-properties)))
;; reset queued with new state and start a timer if not yet started
(reset! enqueued-connectivity-status-properties status-properties)
(when-not @timer
(reset!
timer
(utils/set-timeout
#(do
(reset! timer nil)
(when @enqueued-connectivity-status-properties
(re-frame/dispatch [:set
:connectivity/ui-status-properties
@enqueued-connectivity-status-properties])
(reset! enqueued-connectivity-status-properties nil)))
;; timeout choice:
;; if the app is in foreground or logged-in for less than <timeframe>,
;; postpone state changes for <long> otherwise <short>
(let [ts (max
(or logged-in-since 0)
(or app-active-since 0))
ts-diff (- (datetime/timestamp) ts)
timeout (if (< ts-diff timewindow-for-long-delay)
long-delay
standard-delay)]
(log/debug "propagate-status set-timeout: " logged-in-since app-active-since ts-diff timeout)
timeout))))))
(defn status-propagator-dummy-view
"this empty view is needed to react propagate status-properties to ui-status-properties"
[props]
(reagent/create-class
{:component-did-mount
#(propagate-status props)
:should-component-update
(fn [_ _ [_ props]]
(propagate-status props)
false)
:reagent-render
#()}))
(defview connectivity [header footer]
(letsubs [status-properties [:connectivity/status-properties]
app-active-since [:app-active-since]
logged-in-since [:logged-in-since]
ui-status-properties [:connectivity/ui-status-properties]
status-hidden (reagent/atom true)
(defview loading-indicator []
(letsubs [ui-status-properties [:connectivity/ui-status-properties]
window-width (reagent/atom 0)]
(let [loading-indicator? (:loading-indicator? ui-status-properties)]
[react/view {:style {:flex 1}
:on-layout #(reset! window-width (-> ^js % .-nativeEvent .-layout .-width))}
[react/view {:style {:z-index 2 :background-color colors/white}}
header
[react/view
(when (and loading-indicator? @status-hidden)
[loading-indicator @window-width])]]
[connectivity-status-comp
(merge (or ui-status-properties
{:connected? true :message :t/connected})
{:window-width @window-width})
status-hidden]
;;TODO this is something weird, rework
[status-propagator-dummy-view {:status-properties status-properties
:app-active-since app-active-since
:logged-in-since logged-in-since
:ui-status-properties ui-status-properties}]
footer])))
(when (:loading-indicator? ui-status-properties)
[loading-indicator-anim @window-width])))
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide])
(re-frame/dispatch event))
(defview connectivity-sheet []
(letsubs [{:keys [peers node mobile sync]} [:connectivity/state]
current-mailserver-name [:mailserver/current-name]
peers-count [:peers-count]
{:keys [syncing-on-mobile-network?]} [:multiaccount]]
[:<>
[quo/header {:title (i18n/label :t/connection-status) :border-bottom false}]
[quo/list-header (i18n/label :t/peer-to-peer)]
(if (= peers :offline)
[quo/list-item
{:title (i18n/label :t/not-connected-to-peers)
:accessibility-label "not-connected-to-peers"
:subtitle (i18n/label :t/unable-to-send-messages)
:theme :negative
:icon :main-icons/network}]
[quo/list-item
{:title (str (i18n/label :t/connected-to) " " peers-count " " (string/lower-case (i18n/label :t/peers)))
:accessibility-label "connected-to-n-peers"
:subtitle (i18n/label :t/can-send-messages)
:theme :positive
:icon :main-icons/network}])
[quo/list-header (i18n/label :t/history-nodes)]
(cond
(#{:error :offline} node)
[quo/list-item
{:title (i18n/label :t/not-connected-nodes)
:accessibility-label "not-connected-nodes"
:subtitle (i18n/label :t/unable-to-fetch)
:theme :negative
:icon :main-icons/mailserver}]
(= node :disabled)
[quo/list-item
{:title (i18n/label :t/nodes-disabled)
:accessibility-label "nodes-disabled"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(and mobile (not sync))
[quo/list-item
{:title (i18n/label :t/waiting-wi-fi)
:accessibility-label "waiting-wi-fi"
:subtitle (i18n/label :t/unable-to-fetch)
:disabled true
:icon :main-icons/mailserver}]
(= node :connecting)
[quo/list-item
{:title (i18n/label :t/connecting)
:accessibility-label "connecting"
:subtitle (i18n/label :t/unable-to-fetch)
:icon :main-icons/mailserver}]
(= node :online)
[quo/list-item
{:title (str (i18n/label :t/connected-to) " " current-mailserver-name)
:accessibility-label "connected-to-mailserver"
:subtitle (i18n/label :t/you-can-fetch)
:theme :positive
:icon :main-icons/mailserver}])
[quo/list-item
{:title (i18n/label :t/settings)
:accessibility-label "settings"
:theme :accent
:on-press #(hide-sheet-and-dispatch [:navigate-to :profile-stack {:screen :sync-settings}])
:icon :main-icons/settings}]
(when mobile
[:<>
[react/view {:margin-vertical 8 :background-color colors/gray-lighter :height 36
:align-items :center :justify-content :center}
[react/text {:style {:color colors/gray}} (i18n/label :t/youre-on-mobile-network)]]
[quo/list-item
{:title (i18n/label :t/mobile-network-use-mobile)
:accessibility-label "mobile-network-use-mobile"
:accessory :switch
:on-press #(re-frame/dispatch [:mobile-network/set-syncing (not syncing-on-mobile-network?)])
:active syncing-on-mobile-network?}]
[react/text {:style {:margin-horizontal 16 :margin-bottom 12 :color colors/gray}}
(i18n/label :t/status-mobile-descr)]])]))
(defn get-icon [{:keys [peers node mobile sync]}]
(if (= peers :offline)
:main-icons/offline
(if mobile
(if sync :main-icons/mobile-sync :main-icons/mobile-sync-off)
(when (#{:error :disabled} node) :main-icons/node-offline))))
(defview connectivity-button []
(letsubs [state [:connectivity/state]]
(when-let [icon (get-icon state)]
[quo/button {:type :icon
:accessibility-label (str "conn-button-" (name icon))
:style {:margin-right 16}
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content connectivity-sheet}])
:theme (if (= (:peers state) :offline) :negative :secondary)} icon])))

View File

@ -295,7 +295,7 @@
@(re-frame/subscribe [:chats/current-chat])]
(when current-chat
[react/view {:style {:flex 1}}
[connectivity/connectivity
[connectivity/loading-indicator]
[topbar]
[react/view {:style {:flex 1}}
(if group-chat
@ -304,7 +304,7 @@
[messages-view {:chat current-chat
:bottom-space (max @bottom-space @panel-space)
:pan-responder pan-responder
:space-keeper space-keeper}]]]
:space-keeper space-keeper}]]
(when (and group-chat invitation-admin)
[accessory/view {:y position-y
:on-update-inset on-update}

View File

@ -163,10 +163,9 @@
(when (or (seq chats) @search-active? (seq search-filter))
[search-input-wrapper search-filter chats])
[referral-item/list-item]]
(when
(and (empty? chats)
(not status-community))
(or @search-active? (seq search-filter))
(when (and (empty? chats)
(not status-community)
(or @search-active? (seq search-filter)))
[start-suggestion search-filter])
(when status-community
;; We only support one community now, Status
@ -201,8 +200,9 @@
(defn home []
[react/keyboard-avoiding-view {:style styles/home-container}
[connectivity/connectivity
[topbar/topbar {:title (i18n/label :t/chat)
:navigation :none}]
[chats-list]]
:navigation :none
:right-component [connectivity/connectivity-button]}]
[connectivity/loading-indicator]
[chats-list]
[plus-button]])

View File

@ -59,7 +59,6 @@
:syncing-on-mobile-network? (boolean sync?) {})
(multiaccounts.update/multiaccount-update
:remember-syncing-choice? (boolean remember-choice?) {})
(bottom-sheet/hide-bottom-sheet)
(when (and cellular? sync?)
(mailserver/process-next-messages-request))
(wallet/restart-wallet-service-default))))))

View File

@ -34,7 +34,8 @@
(views/defview checkbox []
(views/letsubs [checked? [:mobile-network/remember-choice?]]
[react/view
{:style styles/checkbox-line-container}
{:style styles/checkbox-line-container
:accessibility-label "remember-choice"}
[checkbox/checkbox
{:checked? checked?
:style styles/checkbox
@ -54,6 +55,10 @@
[{:style styles/settings-link}
(str " " (i18n/label :mobile-network-sheet-settings))]]])
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide])
(re-frame/dispatch event))
(views/defview settings-sheet []
[react/view {:flex 1}
[react/view {:align-items :center}
@ -61,16 +66,18 @@
[details :mobile-syncing-sheet-details]]
[quo/list-item
{:theme :accent
:accessibility-label "mobile-network-continue-syncing"
:title (i18n/label :t/mobile-network-continue-syncing)
:subtitle (i18n/label :t/mobile-network-continue-syncing-details)
:icon :main-icons/network
:on-press #(re-frame/dispatch [:mobile-network/continue-syncing])}]
:on-press #(hide-sheet-and-dispatch [:mobile-network/continue-syncing])}]
[quo/list-item
{:theme :negative
:accessibility-label "mobile-network-stop-syncing"
:title (i18n/label :t/mobile-network-stop-syncing)
:subtitle (i18n/label :t/mobile-network-stop-syncing-details)
:icon :main-icons/cancel
:on-press #(re-frame/dispatch [:mobile-network/stop-syncing])}]
:on-press #(hide-sheet-and-dispatch [:mobile-network/stop-syncing])}]
[separator]
[react/view {:flex 1
:align-self :stretch}

View File

@ -25,7 +25,8 @@
[:multiaccount]]
[react/view {:style styles/container}
[topbar/topbar {:title (i18n/label :t/mobile-network-settings)}]
[react/view {:style styles/switch-container}
[react/view {:style styles/switch-container
:accessibility-label "mobile-network-use-mobile"}
[profile.components/settings-switch-item
{:label-kw :t/mobile-network-use-mobile
:value syncing-on-mobile-network?
@ -33,7 +34,8 @@
[react/view {:style styles/details}
[react/text {:style styles/use-mobile-data-text}
(i18n/label :t/mobile-network-use-mobile-data)]]
[react/view {:style styles/switch-container}
[react/view {:style styles/switch-container
:accessibility-label "mobile-network-ask-me"}
[profile.components/settings-switch-item
{:label-kw :t/mobile-network-ask-me
:value (not remember-syncing-choice?)
@ -43,8 +45,9 @@
{:style styles/defaults-container}
[react/text
{:style styles/defaults
:accessibility-label "restore-defaults"
:on-press #(hide-sheet-and-dispatch [:mobile-network/restore-defaults])}
"Restore Defaults"]]]))
(i18n/label :t/restore-defaults)]]]))
(def settings-sheet
{:content sheets/settings-sheet})

View File

@ -10,9 +10,7 @@
(views/defview sync-settings []
(views/letsubs [{:keys [syncing-on-mobile-network?
use-mailservers?]} [:multiaccount]
current-mailserver-id [:mailserver/current-id]
current-fleet [:fleets/current-fleet]
mailservers [:mailserver/mailservers]]
current-mailserver-name [:mailserver/current-name]]
[react/view {:style {:flex 1 :background-color colors/white}}
[topbar/topbar {:title (i18n/label :t/sync-settings)
:navigation {:on-press #(re-frame/dispatch [:navigate-to :profile-stack {:screen :my-profile}])}}]
@ -32,8 +30,7 @@
:title (i18n/label :t/history-nodes)
:on-press #(re-frame/dispatch [:navigate-to :offline-messaging-settings])
:accessory :text
:accessory-text (when use-mailservers?
(get-in mailservers [current-fleet current-mailserver-id :name]))
:accessory-text (when use-mailservers? current-mailserver-name)
:chevron true}]
;; TODO(Ferossgp): Devider componemt
[react/view {:height 1

View File

@ -165,6 +165,7 @@
"connect": "Connect",
"connect-mailserver-content": "Connect to {{name}}?",
"connected": "Connected",
"connected-to": "Connected to",
"connecting": "Connecting...",
"connecting-requires-login": "Connecting to another network requires login",
"connection-with-the-card-lost": "Connection with the card\n has been lost",
@ -1403,5 +1404,18 @@
"everyone": "Everyone",
"show-profile-pictures": "Show profile pictures of",
"non-archival-node": "RPC endpoint doesn't support archival requests. Your local transfers history might be incomplete.",
"custom-node": "You are using custom RPC endpoint. Your local transfers history might be incomplete."
"custom-node": "You are using custom RPC endpoint. Your local transfers history might be incomplete.",
"connection-status": "Connection status",
"peer-to-peer": "Peer to peer",
"not-connected-to-peers": "Not connected to any peers",
"unable-to-send-messages": "Unable to send and receive messages",
"can-send-messages": "You can send and receive new messages",
"not-connected-nodes": "Not connected to a status node",
"unable-to-fetch": "Unable to fetch chat history",
"nodes-disabled": "Status nodes disabled",
"waiting-wi-fi": "Waiting for Wi-Fi…",
"you-can-fetch": "You can fetch chat history",
"youre-on-mobile-network": "Youre on mobile network",
"status-mobile-descr": "Status tends to use a lot of data when syncing chats. You can choose not to sync when on mobile network",
"restore-defaults": "Restore Defaults"
}