Add mailservers confirmations & use peer count for online status
We now check that we are only connected to some `peers` instead of using `NetInfo` from `react-native`. This is because it has been reported to be quite flaky at times, not reporting online status after sleeping, and for privacy concerns (on ios it pings `apple.com`, on desktop `google.com`). Adds a new banner `Wallet Offline` and change `Connecting to peers` to `Chat offline`. A message will be marked as `Sent` only if it made it to the mailserver you are connected to, which will increase the guarantees that we can make about a message (if you see it as sent, it has reached at least a mailserver), this has the consequence that: - If you are not connected to any mailserver or the mailserver is non responsive/down, and you send a message, it will be marked as `Not sent`, although it might have been actually made it in the network. Probably this is something that we would like to communicate to the user through UX (i.e. tick if made it to at least a peer, double tick if it made to a mailserver ) Currently I have only enabled this feature in nightlies & devs, I would give it a run and see how we feel about it.
This commit is contained in:
parent
9110a64dcc
commit
d760f1696c
1
.env
1
.env
|
@ -16,3 +16,4 @@ HARDWALLET_ENABLED=0
|
||||||
PFS_ENCRYPTION_ENABLED=0
|
PFS_ENCRYPTION_ENABLED=0
|
||||||
DEV_BUILD=1
|
DEV_BUILD=1
|
||||||
ERC20_CONTRACT_WARNINGS=1
|
ERC20_CONTRACT_WARNINGS=1
|
||||||
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|
1
.env.e2e
1
.env.e2e
|
@ -12,3 +12,4 @@ PAIRING_ENABLED=1
|
||||||
EXTENSIONS=1
|
EXTENSIONS=1
|
||||||
PFS_ENCRYPTION_ENABLED=0
|
PFS_ENCRYPTION_ENABLED=0
|
||||||
ERC20_CONTRACT_WARNINGS=1
|
ERC20_CONTRACT_WARNINGS=1
|
||||||
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|
|
@ -15,3 +15,4 @@ EXTENSIONS=1
|
||||||
PFS_ENCRYPTION_ENABLED=0
|
PFS_ENCRYPTION_ENABLED=0
|
||||||
PAIRING_ENABLED=1
|
PAIRING_ENABLED=1
|
||||||
ERC20_CONTRACT_WARNINGS=1
|
ERC20_CONTRACT_WARNINGS=1
|
||||||
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|
|
@ -14,3 +14,4 @@ MAINNET_WARNING_ENABLED=1
|
||||||
EXTENSIONS=1
|
EXTENSIONS=1
|
||||||
PFS_ENCRYPTION_ENABLED=0
|
PFS_ENCRYPTION_ENABLED=0
|
||||||
ERC20_CONTRACT_WARNINGS=1
|
ERC20_CONTRACT_WARNINGS=1
|
||||||
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|
|
@ -13,3 +13,4 @@ MAINNET_WARNING_ENABLED=1
|
||||||
EXTENSIONS=1
|
EXTENSIONS=1
|
||||||
PFS_ENCRYPTION_ENABLED=0
|
PFS_ENCRYPTION_ENABLED=0
|
||||||
ERC20_CONTRACT_WARNINGS=1
|
ERC20_CONTRACT_WARNINGS=1
|
||||||
|
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||||
|
|
|
@ -791,6 +791,26 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void updateMailservers(final String enodes, final Callback callback) {
|
||||||
|
Log.d(TAG, "updateMailservers");
|
||||||
|
if (!checkAvailability()) {
|
||||||
|
callback.invoke(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String res = Statusgo.UpdateMailservers(enodes);
|
||||||
|
|
||||||
|
callback.invoke(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable
|
public @Nullable
|
||||||
Map<String, Object> getConstants() {
|
Map<String, Object> getConstants() {
|
||||||
|
|
|
@ -319,3 +319,13 @@ void RCTStatus::logStatusGoResult(const char* methodName, const char* result)
|
||||||
qCWarning(RCTSTATUS) << methodName << "- error:" << qUtf8Printable(error);
|
qCWarning(RCTSTATUS) << methodName << "- error:" << qUtf8Printable(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RCTStatus::updateMailservers(QString enodes, double callbackId) {
|
||||||
|
Q_D(RCTStatus);
|
||||||
|
qCDebug(RCTSTATUS) << "::updateMailservers call - callbackId:" << callbackId;
|
||||||
|
QtConcurrent::run([&](QString enodes, double callbackId) {
|
||||||
|
const char* result = UpdateMailservers(enodes.toUtf8().data());
|
||||||
|
logStatusGoResult("::updateMailservers UpdateMailservers", result);
|
||||||
|
d->bridge->invokePromiseCallback(callbackId, QVariantList{result});
|
||||||
|
}, enodes, callbackId);
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
Q_INVOKABLE void extractGroupMembershipSignatures(QString signatures, double callbackId);
|
Q_INVOKABLE void extractGroupMembershipSignatures(QString signatures, double callbackId);
|
||||||
Q_INVOKABLE void enableInstallation(QString installationId, double callbackId);
|
Q_INVOKABLE void enableInstallation(QString installationId, double callbackId);
|
||||||
Q_INVOKABLE void disableInstallation(QString installationId, double callbackId);
|
Q_INVOKABLE void disableInstallation(QString installationId, double callbackId);
|
||||||
|
Q_INVOKABLE void updateMailservers(QString enodes, double callbackId);
|
||||||
|
|
||||||
Q_INVOKABLE void setAdjustResize();
|
Q_INVOKABLE void setAdjustResize();
|
||||||
Q_INVOKABLE void setAdjustPan();
|
Q_INVOKABLE void setAdjustPan();
|
||||||
|
|
|
@ -206,6 +206,16 @@ RCT_EXPORT_METHOD(addPeer:(NSString *)enode
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////// updateMailservers
|
||||||
|
RCT_EXPORT_METHOD(updateMailservers:(NSString *)enodes
|
||||||
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
|
char * result = UpdateMailservers((char *) [enodes UTF8String]);
|
||||||
|
callback(@[[NSString stringWithUTF8String: result]]);
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"UpdateMailservers() method called");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////// recoverAccount
|
//////////////////////////////////////////////////////////////////// recoverAccount
|
||||||
RCT_EXPORT_METHOD(recoverAccount:(NSString *)passphrase
|
RCT_EXPORT_METHOD(recoverAccount:(NSString *)passphrase
|
||||||
password:(NSString *)password
|
password:(NSString *)password
|
||||||
|
|
|
@ -316,8 +316,8 @@
|
||||||
;;;; Send message
|
;;;; Send message
|
||||||
|
|
||||||
(fx/defn send
|
(fx/defn send
|
||||||
[{{:keys [network-status]} :db :as cofx} chat-id message-id send-record]
|
[{{:keys [peers-count]} :db :as cofx} chat-id message-id send-record]
|
||||||
(if (= network-status :offline)
|
(if (zero? peers-count)
|
||||||
{:dispatch-later [{:ms 10000
|
{:dispatch-later [{:ms 10000
|
||||||
:dispatch [:message/update-message-status chat-id message-id :not-sent]}]}
|
:dispatch [:message/update-message-status chat-id message-id :not-sent]}]}
|
||||||
(protocol/send send-record chat-id (assoc cofx :message-id message-id))))
|
(protocol/send send-record chat-id (assoc cofx :message-id message-id))))
|
||||||
|
|
|
@ -127,6 +127,15 @@
|
||||||
(response-handler #(log/debug "mailserver: add-peer success" %)
|
(response-handler #(log/debug "mailserver: add-peer success" %)
|
||||||
#(log/error "mailserver: add-peer error" %))))
|
#(log/error "mailserver: add-peer error" %))))
|
||||||
|
|
||||||
|
;; We now wait for a confirmation from the mailserver before marking the message
|
||||||
|
;; as sent.
|
||||||
|
|
||||||
|
(defn update-mailservers! [enodes]
|
||||||
|
(status/update-mailservers
|
||||||
|
(.stringify js/JSON (clj->js enodes))
|
||||||
|
(response-handler #(log/debug "mailserver: update-mailservers success" %)
|
||||||
|
#(log/error "mailserver: update-mailservers error" %))))
|
||||||
|
|
||||||
(defn remove-peer! [enode]
|
(defn remove-peer! [enode]
|
||||||
(let [args {:jsonrpc "2.0"
|
(let [args {:jsonrpc "2.0"
|
||||||
:id 2
|
:id 2
|
||||||
|
@ -147,6 +156,11 @@
|
||||||
(fn [enode]
|
(fn [enode]
|
||||||
(remove-peer! enode)))
|
(remove-peer! enode)))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:mailserver/update-mailservers
|
||||||
|
(fn [enodes]
|
||||||
|
(update-mailservers! enodes)))
|
||||||
|
|
||||||
(defn mark-trusted-peer! [web3 enode]
|
(defn mark-trusted-peer! [web3 enode]
|
||||||
(.markTrustedPeer (transport.utils/shh web3)
|
(.markTrustedPeer (transport.utils/shh web3)
|
||||||
enode
|
enode
|
||||||
|
@ -198,6 +212,9 @@
|
||||||
(update-mailserver-state :connecting)
|
(update-mailserver-state :connecting)
|
||||||
(update :mailserver/connection-checks inc))
|
(update :mailserver/connection-checks inc))
|
||||||
:mailserver/add-peer address
|
:mailserver/add-peer address
|
||||||
|
;; Any message sent before this takes effect will not be marked as sent
|
||||||
|
;; probably we should improve the UX so that is more transparent to the user
|
||||||
|
:mailserver/update-mailservers [address]
|
||||||
:utils/dispatch-later [{:ms connection-timeout
|
:utils/dispatch-later [{:ms connection-timeout
|
||||||
:dispatch [:mailserver/check-connection-timeout]}]}
|
:dispatch [:mailserver/check-connection-timeout]}]}
|
||||||
(when-not (or sym-key-id generating-sym-key?)
|
(when-not (or sym-key-id generating-sym-key?)
|
||||||
|
|
|
@ -73,3 +73,5 @@
|
||||||
(def enable-installation native-module/enable-installation)
|
(def enable-installation native-module/enable-installation)
|
||||||
|
|
||||||
(def disable-installation native-module/disable-installation)
|
(def disable-installation native-module/disable-installation)
|
||||||
|
|
||||||
|
(def update-mailservers native-module/update-mailservers)
|
||||||
|
|
|
@ -163,3 +163,7 @@
|
||||||
(defn is24Hour []
|
(defn is24Hour []
|
||||||
(when status
|
(when status
|
||||||
(.-is24Hour status)))
|
(.-is24Hour status)))
|
||||||
|
|
||||||
|
(defn update-mailservers [enodes on-result]
|
||||||
|
(when status
|
||||||
|
(call-module #(.updateMailservers status enodes on-result))))
|
||||||
|
|
|
@ -100,18 +100,19 @@
|
||||||
:RendezvousNodes rendezvous-nodes})
|
:RendezvousNodes rendezvous-nodes})
|
||||||
|
|
||||||
:always
|
:always
|
||||||
(assoc :WhisperConfig {:Enabled true
|
(assoc :WhisperConfig {:Enabled true
|
||||||
:LightClient true
|
:LightClient true
|
||||||
:MinimumPoW 0.001
|
:MinimumPoW 0.001
|
||||||
:EnableNTPSync true}
|
:EnableNTPSync true}
|
||||||
:RequireTopics (get-topics network)
|
:RequireTopics (get-topics network)
|
||||||
:InstallationID installation-id
|
:InstallationID installation-id
|
||||||
:PFSEnabled (or config/pfs-encryption-enabled?
|
:MailServerConfirmations config/mailserver-confirmations-enabled?
|
||||||
|
:PFSEnabled (or config/pfs-encryption-enabled?
|
||||||
;; We don't check dev-mode? here as
|
;; We don't check dev-mode? here as
|
||||||
;; otherwise we would have to restart the node
|
;; otherwise we would have to restart the node
|
||||||
;; when the user enables it
|
;; when the user enables it
|
||||||
config/group-chats-enabled?
|
config/group-chats-enabled?
|
||||||
(config/pairing-enabled? true)))
|
(config/pairing-enabled? true)))
|
||||||
|
|
||||||
(and
|
(and
|
||||||
config/bootnodes-settings-enabled?
|
config/bootnodes-settings-enabled?
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
view-id [:get :view-id]
|
view-id [:get :view-id]
|
||||||
window-width [:dimensions/window-width]]
|
window-width [:dimensions/window-width]]
|
||||||
(when-let [label (cond
|
(when-let [label (cond
|
||||||
offline? :t/offline
|
(and offline?
|
||||||
|
disconnected?) :t/offline
|
||||||
|
offline? :t/wallet-offline
|
||||||
disconnected? :t/disconnected
|
disconnected? :t/disconnected
|
||||||
mailserver-connection-error? :t/mailserver-reconnect
|
mailserver-connection-error? :t/mailserver-reconnect
|
||||||
mailserver-request-error? :t/mailserver-request-error-status
|
mailserver-request-error? :t/mailserver-request-error-status
|
||||||
|
|
|
@ -14,22 +14,22 @@
|
||||||
(animation/timing spin-value {:toValue to-spin-value
|
(animation/timing spin-value {:toValue to-spin-value
|
||||||
:duration 300})))))
|
:duration 300})))))
|
||||||
|
|
||||||
(defn sendable? [input-text offline? login-processing?]
|
(defn sendable? [input-text disconnected? login-processing?]
|
||||||
(let [trimmed (string/trim input-text)]
|
(let [trimmed (string/trim input-text)]
|
||||||
(not (or (string/blank? trimmed)
|
(not (or (string/blank? trimmed)
|
||||||
(= trimmed "/")
|
(= trimmed "/")
|
||||||
offline?
|
login-processing?
|
||||||
login-processing?))))
|
disconnected?))))
|
||||||
|
|
||||||
(defview send-button-view []
|
(defview send-button-view []
|
||||||
(letsubs [{:keys [command-completion]} [:chats/selected-chat-command]
|
(letsubs [{:keys [command-completion]} [:chats/selected-chat-command]
|
||||||
{:keys [input-text]} [:chats/current-chat]
|
{:keys [input-text seq-arg-input-text]} [:chats/current-chat]
|
||||||
offline? [:offline?]
|
disconnected? [:disconnected?]
|
||||||
spin-value (animation/create-value 1)
|
login-processing? [:get-in [:accounts/login :processing]]
|
||||||
login-processing? [:get-in [:accounts/login :processing]]]
|
spin-value (animation/create-value 1)]
|
||||||
{:component-did-update (send-button-view-on-update {:spin-value spin-value
|
{:component-did-update (send-button-view-on-update {:spin-value spin-value
|
||||||
:command-completion command-completion})}
|
:command-completion command-completion})}
|
||||||
(when (and (sendable? input-text offline? login-processing?)
|
(when (and (sendable? input-text disconnected? login-processing?)
|
||||||
(or (not command-completion)
|
(or (not command-completion)
|
||||||
(#{:complete :less-than-needed} command-completion)))
|
(#{:complete :less-than-needed} command-completion)))
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/send-current-message])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/send-current-message])}
|
||||||
|
|
|
@ -238,11 +238,10 @@
|
||||||
:current-public-key current-public-key)]))]]
|
:current-public-key current-public-key)]))]]
|
||||||
[connectivity/error-view]])))
|
[connectivity/error-view]])))
|
||||||
|
|
||||||
(views/defview send-button [inp-ref network-status]
|
(views/defview send-button [inp-ref disconnected?]
|
||||||
(views/letsubs [{:keys [input-text]} [:chats/current-chat]]
|
(views/letsubs [{:keys [input-text]} [:chats/current-chat]]
|
||||||
(let [empty? (= "" input-text)
|
(let [empty? (= "" input-text)
|
||||||
offline? (= :offline network-status)
|
inactive? (or empty? disconnected?)]
|
||||||
inactive? (or empty? offline?)]
|
|
||||||
[react/touchable-highlight {:style styles/send-button
|
[react/touchable-highlight {:style styles/send-button
|
||||||
:disabled inactive?
|
:disabled inactive?
|
||||||
:on-press (fn []
|
:on-press (fn []
|
||||||
|
@ -284,7 +283,7 @@
|
||||||
|
|
||||||
(views/defview chat-text-input [chat-id input-text]
|
(views/defview chat-text-input [chat-id input-text]
|
||||||
(views/letsubs [inp-ref (atom nil)
|
(views/letsubs [inp-ref (atom nil)
|
||||||
network-status [:network-status]]
|
disconnected? [:disconnected?]]
|
||||||
{:component-will-update
|
{:component-will-update
|
||||||
(fn [e [_ new-chat-id new-input-text]]
|
(fn [e [_ new-chat-id new-input-text]]
|
||||||
(let [[_ old-chat-id] (.. e -props -argv)]
|
(let [[_ old-chat-id] (.. e -props -argv)]
|
||||||
|
@ -305,7 +304,7 @@
|
||||||
:default-value input-text
|
:default-value input-text
|
||||||
:on-content-size-change #(set-container-height-fn (.-height (.-contentSize (.-nativeEvent %))))
|
:on-content-size-change #(set-container-height-fn (.-height (.-contentSize (.-nativeEvent %))))
|
||||||
:submit-shortcut {:key "Enter"}
|
:submit-shortcut {:key "Enter"}
|
||||||
:on-submit-editing #(when (= :online network-status)
|
:on-submit-editing #(when-not disconnected?
|
||||||
(.clear @inp-ref)
|
(.clear @inp-ref)
|
||||||
(.focus @inp-ref)
|
(.focus @inp-ref)
|
||||||
(re-frame/dispatch [:chat.ui/send-current-message]))
|
(re-frame/dispatch [:chat.ui/send-current-message]))
|
||||||
|
@ -313,7 +312,7 @@
|
||||||
(let [native-event (.-nativeEvent e)
|
(let [native-event (.-nativeEvent e)
|
||||||
text (.-text native-event)]
|
text (.-text native-event)]
|
||||||
(re-frame/dispatch [:chat.ui/set-chat-input-text text])))}]
|
(re-frame/dispatch [:chat.ui/set-chat-input-text text])))}]
|
||||||
[send-button inp-ref network-status]])))
|
[send-button inp-ref disconnected?]])))
|
||||||
|
|
||||||
(views/defview chat-view []
|
(views/defview chat-view []
|
||||||
(views/letsubs [{:keys [input-text chat-id] :as current-chat} [:chats/current-chat]]
|
(views/letsubs [{:keys [input-text chat-id] :as current-chat} [:chats/current-chat]]
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
(defn pairing-enabled? [dev-mode?]
|
(defn pairing-enabled? [dev-mode?]
|
||||||
(and (enabled? (get-config :PAIRING_ENABLED "0"))
|
(and (enabled? (get-config :PAIRING_ENABLED "0"))
|
||||||
(or dev-mode? platform/desktop?)))
|
(or dev-mode? platform/desktop?)))
|
||||||
|
(def mailserver-confirmations-enabled? (enabled? (get-config :MAILSERVER_CONFIRMATIONS_ENABLED)))
|
||||||
(def mainnet-warning-enabled? (enabled? (get-config :MAINNET_WARNING_ENABLED 0)))
|
(def mainnet-warning-enabled? (enabled? (get-config :MAINNET_WARNING_ENABLED 0)))
|
||||||
(def pfs-encryption-enabled? (enabled? (get-config :PFS_ENCRYPTION_ENABLED "0")))
|
(def pfs-encryption-enabled? (enabled? (get-config :PFS_ENCRYPTION_ENABLED "0")))
|
||||||
(def in-app-notifications-enabled? (enabled? (get-config :IN_APP_NOTIFICATIONS_ENABLED 0)))
|
(def in-app-notifications-enabled? (enabled? (get-config :IN_APP_NOTIFICATIONS_ENABLED 0)))
|
||||||
|
|
|
@ -321,13 +321,13 @@
|
||||||
(testing "Mailserver disconnected, sym-key exists"
|
(testing "Mailserver disconnected, sym-key exists"
|
||||||
(let [result (peers-summary-change-result true false true)]
|
(let [result (peers-summary-change-result true false true)]
|
||||||
(is (= (into #{} (keys result))
|
(is (= (into #{} (keys result))
|
||||||
#{:db :mailserver/add-peer :utils/dispatch-later}))
|
#{:db :mailserver/add-peer :utils/dispatch-later :mailserver/update-mailservers}))
|
||||||
(is (= (get-in result [:db :mailserver/state])
|
(is (= (get-in result [:db :mailserver/state])
|
||||||
:connecting))))
|
:connecting))))
|
||||||
(testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)"
|
(testing "Mailserver disconnected, sym-key doesn't exists (unlikely situation in practice)"
|
||||||
(let [result (peers-summary-change-result false false true)]
|
(let [result (peers-summary-change-result false false true)]
|
||||||
(is (= (into #{} (keys result))
|
(is (= (into #{} (keys result))
|
||||||
#{:db :mailserver/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password}))
|
#{:db :mailserver/add-peer :utils/dispatch-later :shh/generate-sym-key-from-password :mailserver/update-mailservers}))
|
||||||
(is (= (get-in result [:db :mailserver/state])
|
(is (= (get-in result [:db :mailserver/state])
|
||||||
:connecting))))
|
:connecting))))
|
||||||
(testing "Mailserver isn't concerned by peer summary changes"
|
(testing "Mailserver isn't concerned by peer summary changes"
|
||||||
|
|
|
@ -165,7 +165,8 @@
|
||||||
"datetime-yesterday": "yesterday",
|
"datetime-yesterday": "yesterday",
|
||||||
"create-new-account": "Create new account",
|
"create-new-account": "Create new account",
|
||||||
"are-you-sure?": "Are you sure?",
|
"are-you-sure?": "Are you sure?",
|
||||||
"disconnected": "Connecting to peers...",
|
"disconnected": "Chat offline",
|
||||||
|
"wallet-offline": "Wallet offline",
|
||||||
"sign-in-to-status": "Sign in to Status",
|
"sign-in-to-status": "Sign in to Status",
|
||||||
"leave-group-chat-confirmation": "Are you sure you want to leave this group?",
|
"leave-group-chat-confirmation": "Are you sure you want to leave this group?",
|
||||||
"dapp-profile": "ÐApp profile",
|
"dapp-profile": "ÐApp profile",
|
||||||
|
|
Loading…
Reference in New Issue