From 2580b0a9d912cf171f2b03a00012974d860a7752 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 19 Oct 2016 15:22:05 +0300 Subject: [PATCH] show connectivity issues & retry sending of phone/confirmation code to server if application is offline --- android/app/src/main/AndroidManifest.xml | 1 + resources/console.js | 36 +---------------- src/status_im/android/core.cljs | 1 + src/status_im/chat/handlers.cljs | 23 ++++++----- src/status_im/chat/handlers/console.cljs | 39 +++++++++++++++++++ src/status_im/chat/handlers/send_message.cljs | 21 +++++++--- src/status_im/chat/views/message.cljs | 10 +++-- src/status_im/commands/handlers/jail.cljs | 24 ++---------- src/status_im/components/react.cljs | 17 +------- .../components/sync_state/offline.cljs | 17 ++++---- src/status_im/handlers.cljs | 1 + src/status_im/handlers/server.cljs | 23 ++++++++--- src/status_im/network/handlers.cljs | 18 +++++++++ src/status_im/network/net_info.cljs | 16 ++++++++ src/status_im/protocol/handlers.cljs | 12 +++--- src/status_im/utils/scheduler.cljs | 10 +++++ src/status_im/utils/utils.cljs | 13 ++++++- test/cljs/status_im/test/handlers_stubs.cljs | 1 - 18 files changed, 174 insertions(+), 109 deletions(-) create mode 100644 src/status_im/chat/handlers/console.cljs create mode 100644 src/status_im/network/handlers.cljs create mode 100644 src/status_im/network/net_info.cljs create mode 100644 src/status_im/utils/scheduler.cljs diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 62c1d80130..99ed60c770 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + db (assoc :user-phone-number formatted) sign-up-service/start-listening-confirmation-code-sms - (server/sign-up formatted sign-up-service/on-sign-up-response))))) + (server/sign-up formatted + message-id + sign-up-service/on-sign-up-response))))) (register-handler :stop-listening-confirmation-code-sms (fn [db [_]] @@ -219,8 +221,11 @@ (register-handler :sign-up-confirm (u/side-effect! - (fn [_ [_ confirmation-code]] - (server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response)))) + (fn [_ [_ confirmation-code message-id]] + (server/sign-up-confirm + confirmation-code + message-id + sign-up-service/on-send-code-response)))) (register-handler :set-signed-up (u/side-effect! @@ -274,9 +279,9 @@ (defmethod nav/preload-data! :chat [{:keys [current-chat-id] :as db} [_ _ id]] - (let [chat-id (or id current-chat-id) - messages (get-in db [:chats chat-id :messages]) - db' (assoc db :current-chat-id chat-id) + (let [chat-id (or id current-chat-id) + messages (get-in db [:chats chat-id :messages]) + db' (assoc db :current-chat-id chat-id) commands-loaded? (get-in db [:chats chat-id :commands-loaded])] (when (= current-chat-id wallet-chat-id) (dispatch [:cancel-command])) diff --git a/src/status_im/chat/handlers/console.cljs b/src/status_im/chat/handlers/console.cljs new file mode 100644 index 0000000000..835bfa0ac4 --- /dev/null +++ b/src/status_im/chat/handlers/console.cljs @@ -0,0 +1,39 @@ +(ns status-im.chat.handlers.console + (:require [re-frame.core :refer [dispatch dispatch-sync after]] + [status-im.utils.handlers :refer [register-handler] :as u] + [status-im.constants :refer [console-chat-id]] + [status-im.data-store.messages :as messages])) + +(def console-commands + {:password + (fn [params _] + (dispatch [:create-account (params "password")])) + + :phone + (fn [params id] + (dispatch [:sign-up (params "phone") id])) + + :confirmation-code + (fn [params id] + (dispatch [:sign-up-confirm (params "code") id]))}) + +(def commands-names (set (keys console-commands))) + +(def commands-with-delivery-status + (disj commands-names :password)) + +(register-handler :invoke-console-command-handler! + (u/side-effect! + (fn [_ [_ {:keys [staged-command] :as parameters}]] + (let [{:keys [id command params]} staged-command + {:keys [name]} command] + (dispatch [:prepare-command! parameters]) + ((console-commands (keyword name)) params id))))) + +(register-handler :set-message-status + (after + (fn [_ [_ message-id status]] + (messages/update {:message-id message-id + :message-status status}))) + (fn [db [_ message-id status]] + (assoc-in db [:message-statuses message-id] {:status status}))) diff --git a/src/status_im/chat/handlers/send_message.cljs b/src/status_im/chat/handlers/send_message.cljs index 0f1baa58b4..e3fac15704 100644 --- a/src/status_im/chat/handlers/send_message.cljs +++ b/src/status_im/chat/handlers/send_message.cljs @@ -13,8 +13,9 @@ default-number-of-messages]] [status-im.utils.datetime :as datetime] [status-im.protocol.core :as protocol] - [taoensso.timbre :refer-macros [debug]] - [taoensso.timbre :as log])) + [taoensso.timbre :refer-macros [debug] :as log] + [status-im.constants :refer [console-chat-id]] + [status-im.chat.handlers.console :as console])) (defn prepare-command [identity chat-id clock-value @@ -53,18 +54,28 @@ (not (s/blank? text)) (dispatch [::prepare-message data])))))) +(defn console-command? [chat-id command-name] + (and (= console-chat-id chat-id) + (console/commands-names (keyword command-name)))) (register-handler ::check-commands-handlers! (u/side-effect! - (fn [_ [_ {:keys [commands message] :as params}]] + (fn [_ [_ {:keys [commands message chat-id] :as params}]] (doseq [{:keys [command] :as message} commands] - (let [params' (assoc params :staged-command message)] + (let [params' (assoc params :staged-command message) + command-name (:name (:command message))] (if (:sent-to-jail? message) ;; todo there could be other reasons for "long-running" ;; hanling of the command besides sendTransaction (dispatch [:navigate-to :confirm]) - (if (:has-handler command) + (cond + (console-command? chat-id command-name) + (dispatch [:invoke-console-command-handler! params']) + + (:has-handler command) (dispatch [::invoke-command-handlers! params']) + + :else (dispatch [:prepare-command! params']))))) (when-not (s/blank? message) (dispatch [::prepare-message params]))))) diff --git a/src/status_im/chat/views/message.cljs b/src/status_im/chat/views/message.cljs index d3316f4a7f..425ed31483 100644 --- a/src/status_im/chat/views/message.cljs +++ b/src/status_im/chat/views/message.cljs @@ -29,7 +29,8 @@ [status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.i18n :refer [label]] [status-im.chat.utils :as cu] - [clojure.string :as str])) + [clojure.string :as str] + [status-im.chat.handlers.console :as console])) (defn message-content-status [_] (let [{:keys [chat-id group-chat name color]} (subscribe [:chat-properties [:chat-id :group-chat :name :color]]) @@ -200,10 +201,13 @@ :font :default} (str "+ " (- (count user-statuses) 3))])]]))) -(defview message-delivery-status [{:keys [message-id chat-id message-status user-statuses]}] +(defview message-delivery-status + [{:keys [message-id chat-id message-status user-statuses content]}] [app-db-message-status-value [:get-in [:message-statuses message-id :status]]] (let [delivery-status (get-in user-statuses [chat-id :status]) - status (if (cu/console? chat-id) + command-name (keyword (:command content)) + status (if (and (not (console/commands-with-delivery-status command-name)) + (cu/console? chat-id)) :seen (or delivery-status message-status app-db-message-status-value :sending))] [view st/delivery-view diff --git a/src/status_im/commands/handlers/jail.cljs b/src/status_im/commands/handlers/jail.cljs index af4c4ec055..4cd1c74ab7 100644 --- a/src/status_im/commands/handlers/jail.cljs +++ b/src/status_im/commands/handlers/jail.cljs @@ -15,23 +15,12 @@ (let [hiccup (generate-hiccup markup)] (assoc-in db [:rendered-commands chat-id message-id] hiccup))) -(def console-events - {:save-password (fn [[parameter]] - (dispatch [:create-account parameter])) - :sign-up (fn [[parameter]] - (dispatch [:sign-up parameter])) - :confirm-sign-up (fn [[parameter]] - (dispatch [:sign-up-confirm parameter]))}) - -(def regular-events {}) - (defn command-hadler! [_ [chat-id {:keys [staged-command] :as parameters} {:keys [result error]}]] (let [{:keys [context returned]} result - {:keys [event params] - handler-error :error} returned] + {handler-error :error} returned] (cond handler-error (log/debug :error-from-handler handler-error @@ -39,18 +28,11 @@ :command staged-command) result - (let [{:keys [event params]} returned - command' (assoc staged-command :handler-data returned) + (let [command' (assoc staged-command :handler-data returned) parameters' (assoc parameters :command command')] (if (:eth_sendTransaction context) (dispatch [:wait-for-transaction (:id staged-command) parameters']) - (let [events (if (= console-chat-id chat-id) - (merge regular-events console-events) - regular-events) - parameters'' (if-let [handler (events (keyword event))] - (assoc parameters' :handler #(handler params command')) - parameters')] - (dispatch [:prepare-command! parameters''])))) + (dispatch [:prepare-command! parameters']))) (not (or error handler-error)) (dispatch [:prepare-command! parameters]) diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 30a84f5e55..b1e6524b63 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -1,32 +1,19 @@ (ns status-im.components.react (:require [reagent.core :as r] [status-im.components.styles :as st] - [status-im.utils.utils :as u] + [status-im.utils.utils :as u + :refer [get-react-property get-class adapt-class]] [status-im.utils.platform :refer [platform-specific]])) (def react-native (u/require "react-native")) (def native-modules (.-NativeModules react-native)) (def device-event-emitter (.-DeviceEventEmitter react-native)) -(def geth (.-Geth native-modules)) (def linear-gradient-module (u/require "react-native-linear-gradient")) (def dismiss-keyboard! (u/require "dismissKeyboard")) (def orientation (u/require "react-native-orientation")) (def drawer (u/require "react-native-drawer-layout")) -;; Getters - -(defn- get-react-property [name] - (aget react-native name)) - -(defn- adapt-class [class] - (when class - (r/adapt-react-class class))) - -(defn- get-class [name] - (adapt-class (get-react-property name))) - - ;; React Components (def app-registry (get-react-property "AppRegistry")) diff --git a/src/status_im/components/sync_state/offline.cljs b/src/status_im/components/sync_state/offline.cljs index 4464923353..99f51761d5 100644 --- a/src/status_im/components/sync_state/offline.cljs +++ b/src/status_im/components/sync_state/offline.cljs @@ -18,12 +18,13 @@ :duration 250}))) (defn offline-view [_] - (let [sync-state (subscribe [:get :sync-state]) - offline-opacity (anim/create-value 0.0) - on-update (fn [_ _] - (anim/set-value offline-opacity 0) - (when (= @sync-state :offline) - (start-offline-animation offline-opacity)))] + (let [sync-state (subscribe [:get :sync-state]) + network-status (subscribe [:get :network-status]) + offline-opacity (anim/create-value 0.0) + on-update (fn [_ _] + (anim/set-value offline-opacity 0) + (when (or (= @network-status :offline) (= @sync-state :offline)) + (start-offline-animation offline-opacity)))] (r/create-class {:component-did-mount on-update @@ -31,8 +32,8 @@ on-update :reagent-render (fn [{:keys [top]}] - (when (= @sync-state :offline) + (when (or (= @network-status :offline) (= @sync-state :offline)) [animated-view {:style (st/offline-wrapper top offline-opacity window-width)} [view [text {:style st/offline-text} - (label :t/offline)]]]))}))) \ No newline at end of file + (label :t/offline)]]]))}))) diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index 9f886dbb61..849495b37e 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -22,6 +22,7 @@ status-im.accounts.handlers status-im.protocol.handlers status-im.transactions.handlers + status-im.network.handlers [status-im.utils.types :as t] [status-im.constants :refer [console-chat-id]])) diff --git a/src/status_im/handlers/server.cljs b/src/status_im/handlers/server.cljs index b01777c94e..84a85de296 100644 --- a/src/status_im/handlers/server.cljs +++ b/src/status_im/handlers/server.cljs @@ -1,10 +1,12 @@ (ns status-im.handlers.server (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] [status-im.utils.utils :refer [http-post]] - [taoensso.timbre :as log])) + [taoensso.timbre :as log] + [status-im.utils.scheduler :as sch] + [status-im.data-store.messages :as messages])) (defn sign-up - [db phone-number handler] + [db phone-number message-id handler] (let [current-account-id (get db :current-account-id) {:keys [public-key address]} (get-in db [:accounts current-account-id])] ;(user-data/save-phone-number phone-number) @@ -14,11 +16,22 @@ :address address} (fn [body] (log/debug body) - (handler))) + (dispatch [:set-message-status message-id :seen]) + (handler)) + (fn [_] + (sch/execute-later + #(dispatch [:sign-up phone-number message-id]) + (sch/s->ms 1)))) db)) (defn sign-up-confirm - [confirmation-code handler] + [confirmation-code message-id handler] (http-post "sign-up-confirm" {:code confirmation-code} - handler)) + (fn [body] + (dispatch [:set-message-status message-id :seen]) + (handler body)) + (fn [_] + (sch/execute-later + #(dispatch [:sign-up-confirm confirmation-code message-id]) + (sch/s->ms 1))))) diff --git a/src/status_im/network/handlers.cljs b/src/status_im/network/handlers.cljs new file mode 100644 index 0000000000..d43c72a878 --- /dev/null +++ b/src/status_im/network/handlers.cljs @@ -0,0 +1,18 @@ +(ns status-im.network.handlers + (:require [re-frame.core :refer [dispatch debug enrich after]] + [status-im.utils.handlers :refer [register-handler]] + [status-im.utils.handlers :as u] + [status-im.network.net-info :as ni] + [clojure.string :as s])) + +(register-handler :listen-to-network-status! + (u/side-effect! + (fn [] + (let [handler #(dispatch [:update-network-status %])] + (ni/init handler) + (ni/add-listener handler))))) + +(register-handler :update-network-status + (fn [db [_ is-connected?]] + (let [status (if is-connected? :online :offline)] + (assoc db :network-status status)))) diff --git a/src/status_im/network/net_info.cljs b/src/status_im/network/net_info.cljs new file mode 100644 index 0000000000..86bfcd6d0c --- /dev/null +++ b/src/status_im/network/net_info.cljs @@ -0,0 +1,16 @@ +(ns status-im.network.net-info + (:require [status-im.utils.utils :as u] + [taoensso.timbre :as log])) + +(def net-info (u/get-react-property "NetInfo")) + +(defn init [callback] + (when net-info + (.then (.fetch (.-isConnected net-info)) + (fn [is-connected?] + (log/debug "Is connected?" is-connected?) + (callback is-connected?))))) + +(defn add-listener [listener] + (when net-info + (.addEventListener (.-isConnected net-info) "change" listener))) diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index be0d8388f6..0c2d5155b0 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -184,7 +184,7 @@ (register-handler :participant-invited-to-group (u/side-effect! (fn [{:keys [current-public-key]} - [_ {:keys [from] + [_ {:keys [from] {:keys [group-id identity message-id]} :payload}]] (participant-invited-to-group-message group-id current-public-key identity from message-id) (when-not (= current-public-key identity) @@ -232,11 +232,11 @@ [_ {:keys [from] {:keys [message-id ack-of-message group-id]} :payload}]] (if (chats/is-active? (or group-id from)) - (let [message-id' (or ack-of-message message-id) - group? (boolean group-id) - status-path (if (and group? (not= status :sent)) - [:message-user-statuses message-id' from] - [:message-statuses message-id']) + (let [message-id' (or ack-of-message message-id) + group? (boolean group-id) + status-path (if (and group? (not= status :sent)) + [:message-user-statuses message-id' from] + [:message-statuses message-id']) {current-status :status} (get-in db status-path)] (if-not (= :seen current-status) (assoc-in db status-path {:whisper-identity from diff --git a/src/status_im/utils/scheduler.cljs b/src/status_im/utils/scheduler.cljs new file mode 100644 index 0000000000..c67841c227 --- /dev/null +++ b/src/status_im/utils/scheduler.cljs @@ -0,0 +1,10 @@ +(ns status-im.utils.scheduler + (:require-macros [cljs.core.async.macros :refer [go]]) + (:require [cljs.core.async :refer [ms [s] (* 1000 s)) + +(defn execute-later + [function timeout-ms] + (go (