Allow editing existing mailservers

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2018-05-30 14:11:30 +02:00
parent e59ffc905d
commit 1e4311d4cb
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
6 changed files with 246 additions and 68 deletions

View File

@ -0,0 +1,22 @@
(ns status-im.models.wnode
(:require
[clojure.string :as string]
[status-im.utils.ethereum.core :as ethereum]))
(defn- extract-address-components [address]
(rest (re-matches #"enode://(.*)@(.*)" address)))
(defn- get-chain [db]
(let [network (get (:networks (:account/account db)) (:network db))]
(ethereum/network->chain-keyword network)))
(defn get-wnode [wnode-id {:keys [db]}]
(get-in db [:inbox/wnodes (get-chain db) wnode-id]))
(defn current-wnode? [wnode-id {:keys [db]}]
(let [current-wnode-id (get-in db [:account/account :settings :wnode (get-chain db)])]
(= current-wnode-id wnode-id)))
(defn build-url [address password]
(let [[initial host] (extract-address-components address)]
(str "enode://" initial ":" password "@" host)))

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.offline-messaging-settings.edit-mailserver.events
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.models.wnode :as models.wnode]
[status-im.utils.handlers :refer [register-handler] :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.accounts.utils :as accounts.utils]
@ -9,38 +10,57 @@
[status-im.utils.inbox :as utils.inbox]
[status-im.data-store.mailservers :as data-store.mailservers]))
(defn- new-mailserver [id mailserver-name address]
(defn- build-mailserver [id mailserver-name address]
(assoc (utils.inbox/address->mailserver address)
:id (string/replace id "-" "")
:name mailserver-name))
(defn save-new-mailserver [{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx} _]
(let [{:keys [name url]} manage
(defn upsert-mailserver [{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx} _]
(let [{:keys [name url id]} manage
network (get (:networks (:account/account db)) (:network db))
chain (ethereum/network->chain-keyword network)
mailserver (new-mailserver
(string/replace (:random-id cofx) "-" "")
mailserver (build-mailserver
(or (:value id)
(string/replace (:random-id cofx) "-" ""))
(:value name)
(:value url))]
(:value url))
connected-to-wnode? (models.wnode/current-wnode? (:id mailserver) cofx)]
{:db (-> db
(dissoc :mailservers/manage)
(assoc-in [:inbox/wnodes chain (:id mailserver)] mailserver))
:data-store/tx [(data-store.mailservers/save-mailserver-tx (assoc
:data-store/tx [{:transaction
(data-store.mailservers/save-mailserver-tx (assoc
mailserver
:chain
chain))]
chain))
;; we naively logout if the user is connected to the edited mailserver
:success-event (when connected-to-wnode? [:logout])}]
:dispatch [:navigate-back]}))
(defn set-input [input-key value {:keys [db]}]
{:db (update db :mailservers/manage assoc input-key {:value value
:error (if (= input-key :name)
(string/blank? value)
(not (utils.inbox/valid-enode-address? value)))})})
:error (case input-key
:id false
:name (string/blank? value)
:url (not (utils.inbox/valid-enode-address? value)))})})
(defn edit-mailserver [wnode-id {:keys [db] :as cofx}]
(let [{:keys [id
address
password
name]} (models.wnode/get-wnode wnode-id cofx)
url (when address (models.wnode/build-url address password))
fxs (handlers-macro/merge-fx
cofx
(set-input :id id)
(set-input :url (str url))
(set-input :name (str name)))]
(assoc fxs :dispatch [:navigate-to :edit-mailserver])))
(handlers/register-handler-fx
:save-new-mailserver
:upsert-mailserver
[(re-frame/inject-cofx :random-id)]
save-new-mailserver)
upsert-mailserver)
(handlers/register-handler-fx
:mailserver-set-input
@ -49,11 +69,8 @@
(handlers/register-handler-fx
:edit-mailserver
(fn [{db :db} _]
{:db (update-in db [:mailservers/manage] assoc
:name {:error true}
:url {:error true})
:dispatch [:navigate-to :edit-mailserver]}))
(fn [cofx [_ wnode-id]]
(edit-mailserver wnode-id cofx)))
(handlers/register-handler-fx
:set-mailserver-from-qr

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.offline-messaging-settings.edit-mailserver.styles
(:require-macros [status-im.utils.styles :refer [defstyle]])
(:require [status-im.ui.components.styles :as styles]))
(:require [status-im.ui.components.styles :as styles]
[status-im.ui.components.colors :as colors]))
(def edit-mailserver-view
{:flex 1
@ -28,3 +29,31 @@
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})
(def connect-button-container
{:margin-top 8
:margin-bottom 16
:margin-horizontal 16})
(defstyle connect-button
{:height 52
:align-items :center
:justify-content :center
:background-color colors/blue
:border-radius 8
:ios {:opacity 0.9}})
(defstyle connect-button-label
{:color colors/white
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 14}})
(defstyle connect-button-description
{:color colors/gray
:ios {:margin-top 8
:height 20
:font-size 14
:letter-spacing -0.2}
:android {:margin-top 12
:font-size 12}})

View File

@ -14,6 +14,15 @@
[status-im.ui.components.text-input.view :as text-input]
[status-im.ui.screens.offline-messaging-settings.edit-mailserver.styles :as styles]))
(defn connect-button [id]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:connect-wnode id])}
[react/view styles/connect-button-container
[react/view {:style styles/connect-button
:accessibility-label :mailserver-connect-button}
[react/text {:style styles/connect-button-label
:uppercase? true}
(i18n/label :t/connect)]]]])
(def qr-code
[react/touchable-highlight {:on-press #(re-frame/dispatch [:scan-qr-code
{:toolbar-title (i18n/label :t/add-mailserver)}
@ -25,6 +34,9 @@
(views/defview edit-mailserver []
(views/letsubs [manage-mailserver [:get-manage-mailserver]
is-valid? [:manage-mailserver-valid?]]
(let [url (get-in manage-mailserver [:url :value])
id (get-in manage-mailserver [:id :value])
name (get-in manage-mailserver [:name :value])]
[react/view components.styles/flex
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
@ -36,7 +48,7 @@
:placeholder (i18n/label :t/specify-name)
:style styles/input
:container styles/input-container
:default-value (get-in manage-mailserver [:name :value])
:default-value name
:on-change-text #(re-frame/dispatch [:mailserver-set-input :name %])
:auto-focus true}]
[text-input/text-input-with-label
@ -45,12 +57,13 @@
:content qr-code
:style styles/input
:container styles/input-container
:default-value (get-in manage-mailserver [:url :value])
:on-change-text #(re-frame/dispatch [:mailserver-set-input :url %])}]]]
:default-value url
:on-change-text #(re-frame/dispatch [:mailserver-set-input :url %])}]
(when id [connect-button id])]]
[react/view styles/bottom-container
[react/view components.styles/flex]
[components.common/bottom-button
{:forward? true
:label (i18n/label :t/save)
:disabled? (not is-valid?)
:on-press #(re-frame/dispatch [:save-new-mailserver])}]]]]))
:on-press #(re-frame/dispatch [:upsert-mailserver])}]]]])))

View File

@ -15,14 +15,19 @@
[react/view (styles/wnode-icon connected?)
[vector-icons/icon :icons/wnode {:color (if connected? :white :gray)}]])
(defn navigate-to-add-mailserver []
(re-frame/dispatch [:edit-mailserver]))
(defn connect-to-mailserver [id]
(re-frame/dispatch [:connect-wnode id]))
(defn- render-row [current-wnode]
(fn [{:keys [name id]}]
(let [connected? (= id current-wnode)]
(defn navigate-to-add-mailserver [wnode-id]
(re-frame/dispatch [:edit-mailserver wnode-id]))
(defn- render-row [current-wnode-id]
(fn [{:keys [name id user-defined]}]
(let [connected? (= id current-wnode-id)]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:connect-wnode id])
{:on-press #(if user-defined
(navigate-to-add-mailserver id)
(connect-to-mailserver id))
:accessibility-label :mailserver-item}
[react/view styles/wnode-item
[wnode-icon connected?]
@ -31,7 +36,7 @@
name]]]])))
(views/defview offline-messaging-settings []
(views/letsubs [current-wnode [:settings/current-wnode]
(views/letsubs [current-wnode-id [:settings/current-wnode]
wnodes [:settings/network-wnodes]]
[react/view {:flex 1}
[status-bar/status-bar]
@ -40,9 +45,9 @@
[toolbar/content-title (i18n/label :t/offline-messaging-settings)]
(when config/add-custom-mailservers-enabled?
[toolbar/actions
[(toolbar.actions/add false navigate-to-add-mailserver)]])]
[(toolbar.actions/add false (partial navigate-to-add-mailserver nil))]])]
[react/view styles/wrapper
[list/flat-list {:data (vals wnodes)
:default-separator? false
:key-fn :id
:render-fn (render-row current-wnode)}]]]))
:render-fn (render-row current-wnode-id)}]]]))

View File

@ -2,7 +2,12 @@
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.ui.screens.offline-messaging-settings.edit-mailserver.events :as events]))
(def valid-enode-url "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40:somepassword@167.99.209.61:30504")
(def enode-id "1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40")
(def password "password")
(def host "167.99.209.61:30504")
(def valid-enode-address (str "enode://" enode-id "@" host))
(def valid-enode-url (str "enode://" enode-id ":" password "@" host))
(deftest set-input
(testing "it validates names"
@ -24,8 +29,59 @@
:error true}}}}
(events/set-input :url "broken" {}))))))
(deftest save-new-mailserver
(testing "save a new mailserver"
(deftest edit-mailserver
(let [db {:network "mainnet_rpc"
:account/account {:networks {"mainnet_rpc"
{:config {:NetworkId 1}}}}
:inbox/wnodes
{:mainnet {"a" {:id "a"
:address valid-enode-address
:password password
:name "name"}}}}
cofx {:db db}]
(testing "when no id is given"
(let [actual (events/edit-mailserver nil cofx)]
(testing "it resets :mailserver/manage"
(is (= {:id {:value nil
:error false}
:url {:value ""
:error true}
:name {:value ""
:error true}}
(-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver]
(-> actual :dispatch))))))
(testing "when an id is given"
(testing "when the wnode is in the list"
(let [actual (events/edit-mailserver "a" cofx)]
(testing "it populates the fields with the correct values"
(is (= {:id {:value "a"
:error false}
:url {:value valid-enode-url
:error false}
:name {:value "name"
:error false}}
(-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver]
(-> actual :dispatch))))))
(testing "when the wnode is not in the list"
(let [actual (events/edit-mailserver "not-existing" cofx)]
(testing "it populates the fields with the correct values"
(is (= {:id {:value nil
:error false}
:url {:value ""
:error true}
:name {:value ""
:error true}}
(-> actual :db :mailservers/manage))))
(testing "it navigates to edit-mailserver view"
(is (= [:navigate-to :edit-mailserver]
(-> actual :dispatch)))))))))
(deftest upsert-mailserver
(testing "new mailserver"
(let [cofx {:random-id "random-id"
:db {:network "mainnet_rpc"
:account/account {:networks {"mainnet_rpc"
@ -34,7 +90,8 @@
:url {:value "enode://test-id:test-password@url:port"}}
:inbox/wnodes {}}}
actual (events/save-new-mailserver cofx nil)]
actual (events/upsert-mailserver cofx nil)]
(testing "it adds the enode to inbox/wnodes"
(is (= {:mainnet {"randomid" {:password "test-password"
:address "enode://test-id@url:port"
@ -42,5 +99,40 @@
:id "randomid"
:user-defined true}}}
(get-in actual [:db :inbox/wnodes]))))
(testing "it navigates back"
(is (= [:navigate-back]
(:dispatch actual))))
(testing "it stores it in the db"
(is (= 1 (count (:data-store/tx actual))))))))
(is (= 1 (count (:data-store/tx actual)))))))
(testing "existing mailserver"
(let [cofx {:random-id "random-id"
:db {:network "mainnet_rpc"
:account/account {:networks {"mainnet_rpc"
{:config {:NetworkId 1}}}}
:mailservers/manage {:id {:value "a"}
:name {:value "new-name"}
:url {:value "enode://new-id:new-password@url:port"}}
:inbox/wnodes {:mainnet {"a" {:id "a"
:name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}
actual (events/upsert-mailserver cofx nil)]
(testing "it navigates back"
(is (= [:navigate-back]
(:dispatch actual))))
(testing "it updates the enode to inbox/wnodes"
(is (= {:mainnet {"a" {:password "new-password"
:address "enode://new-id@url:port"
:name "new-name"
:id "a"
:user-defined true}}}
(get-in actual [:db :inbox/wnodes]))))
(testing "it stores it in the db"
(is (= 1 (count (:data-store/tx actual)))))
(testing "it logs the user out if connected to the current mailserver"
(let [actual (events/upsert-mailserver (assoc-in cofx
[:db :account/account :settings]
{:wnode
{:mainnet "a"}}) nil)]
(is (= [:logout]
(-> actual :data-store/tx first :success-event))))))))