Sign up confirmation view refactoring

Former-commit-id: 3f145c2059
This commit is contained in:
virvar 2016-03-16 14:42:00 +03:00
parent ef5c7779fc
commit 9f249a1da9
16 changed files with 220 additions and 137 deletions

View File

@ -8,7 +8,7 @@
(:require [om.next :as om :refer-macros [defui]] (:require [om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[messenger.state :as state] [messenger.state :as state]
[messenger.android.resources :as res])) [messenger.utils.resources :as res]))
(set! js/InvertibleScrollView (js/require "react-native-invertible-scroll-view")) (set! js/InvertibleScrollView (js/require "react-native-invertible-scroll-view"))

View File

@ -1,45 +0,0 @@
(ns messenger.android.contacts
(:require [messenger.state :as state]
[messenger.android.utils :refer [log toast http-post]]
[messenger.android.database :as db]))
(def fake-contacts? true)
(def react-native-contacts (js/require "react-native-contacts"))
(defn generate-contact [n]
{:name (str "Contact " n)
:photo-path ""
:phone-numbers [{:label "mobile" :number (apply str (repeat 7 n))}]
:delivery-status (if (< (rand) 0.5) :delivered :seen)
:datetime "15:30"
:new-messages-count (rand-int 3)
:online (< (rand) 0.5)})
(defn generate-contacts [n]
(map generate-contact (range 1 (inc n))))
(defn load-phone-contacts [on-success on-error]
(if fake-contacts?
(on-success (generate-contacts 10))
(.getAll react-native-contacts
(fn [error raw-contacts]
(if (not error)
(let [contacts (map (fn [contact]
(merge (generate-contact 1)
{:name (:givenName contact)
:photo-path (:thumbnailPath contact)
:phone-numbers (:phoneNumbers contact)}))
(js->clj raw-contacts :keywordize-keys true))]
(on-success contacts))
(when on-error
(on-error error)))))))
(defn load-whisper-contacts []
(map (fn [contact]
(merge contact
{:delivery-status (if (< (rand) 0.5) :delivered :seen)
:datetime "15:30"
:new-messages-count (rand-int 3)
:online (< (rand) 0.5)}))
(db/get-contacts)))

View File

@ -2,15 +2,13 @@
(:require-macros (:require-macros
[natal-shell.components :refer [view text image touchable-highlight list-view [natal-shell.components :refer [view text image touchable-highlight list-view
toolbar-android]] toolbar-android]]
[natal-shell.data-source :refer [data-source clone-with-rows]] [natal-shell.core :refer [with-error-view]])
[natal-shell.core :refer [with-error-view]]
[natal-shell.alert :refer [alert]])
(:require [om.next :as om :refer-macros [defui]] (:require [om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[messenger.state :as state] [messenger.state :as state]
[messenger.android.utils :refer [log toast http-post]] [messenger.utils.utils :refer [log toast http-post]]
[messenger.android.resources :as res] [messenger.utils.resources :as res]
[messenger.android.contacts :as contacts] [messenger.comm.intercom :as intercom]
[messenger.android.chat :refer [chat]])) [messenger.android.chat :refer [chat]]))
(def fake-contacts? true) (def fake-contacts? true)
@ -137,9 +135,7 @@
{:nav nav}))) {:nav nav})))
(defn load-contacts [] (defn load-contacts []
(let [contacts (contacts/load-whisper-contacts)] (intercom/load-syng-contacts))
(swap! state/app-state update :contacts-ds
#(clone-with-rows % contacts))))
(defui ContactsList (defui ContactsList
static om/IQuery static om/IQuery

View File

@ -6,10 +6,9 @@
(:require [om.next :as om :refer-macros [defui]] (:require [om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[messenger.state :as state] [messenger.state :as state]
[messenger.comm.intercom :as intercom :refer [set-user-phone-number [messenger.comm.intercom :as intercom :refer [set-user-phone-number]]
save-user-phone-number]] [messenger.utils.utils :refer [log toast http-post]]
[messenger.android.utils :refer [log toast http-post]] [messenger.utils.resources :as res]
[messenger.android.resources :as res]
[messenger.android.sign-up-confirm :refer [sign-up-confirm]])) [messenger.android.sign-up-confirm :refer [sign-up-confirm]]))
(def nav-atom (atom nil)) (def nav-atom (atom nil))
@ -26,7 +25,6 @@
(let [app-state (state/state) (let [app-state (state/state)
phone-number (:user-phone-number app-state) phone-number (:user-phone-number app-state)
whisper-identity (:user-whisper-identity app-state)] whisper-identity (:user-whisper-identity app-state)]
(save-user-phone-number phone-number)
(intercom/sign-up phone-number whisper-identity show-confirm-view))) (intercom/sign-up phone-number whisper-identity show-confirm-view)))
(defn update-phone-number [value] (defn update-phone-number [value]

View File

@ -5,16 +5,13 @@
[natal-shell.async-storage :refer [get-item set-item]] [natal-shell.async-storage :refer [get-item set-item]]
[natal-shell.core :refer [with-error-view]] [natal-shell.core :refer [with-error-view]]
[natal-shell.alert :refer [alert]]) [natal-shell.alert :refer [alert]])
(:require [clojure.string :as cstr] (:require [om.next :as om :refer-macros [defui]]
[om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[syng-im.protocol.web3 :as whisper] [syng-im.protocol.web3 :as whisper]
[messenger.state :as state] [messenger.state :as state]
[messenger.android.utils :refer [log toast http-post]] [messenger.utils.utils :refer [log toast]]
[messenger.android.crypt :refer [encrypt]] [messenger.utils.resources :as res]
[messenger.android.resources :as res] [messenger.comm.intercom :as intercom :refer [set-confirmation-code]]
[messenger.android.database :as db]
[messenger.android.contacts :as contacts]
[messenger.android.contacts-list :refer [contacts-list]])) [messenger.android.contacts-list :refer [contacts-list]]))
(def nav-atom (atom nil)) (def nav-atom (atom nil))
@ -24,76 +21,28 @@
(.replace @nav-atom (clj->js {:component contacts-list (.replace @nav-atom (clj->js {:component contacts-list
:name "contacts-list"})))) :name "contacts-list"}))))
(defn get-contact-name [phone-contact] (defn sync-contacts []
(cstr/join " " (intercom/sync-contacts show-home-view))
(filter #(not (cstr/blank? %))
[(:givenName phone-contact)
(:middleName phone-contact)
(:familyName phone-contact)])))
(defn handle-load-contacts-identities-response [contacts-by-hash data] (defn on-send-code-response [body]
(let [contacts (map (fn [server-contact]
(let [number-info (get contacts-by-hash
(:phone-number-hash server-contact))
phone-contact (:contact number-info)]
{:phone-number (:number number-info)
:whisper-identity (:whisper-identity server-contact)
:name (get-contact-name phone-contact)
:photo-path (:photo-path phone-contact)}))
(js->clj (:contacts data)))]
(db/add-contacts contacts)
(show-home-view)))
(defn get-contacts-by-hash [contacts]
(let [numbers-info (reduce (fn [numbers contact]
(into numbers
(map (fn [c]
{:number (:number c)
:contact contact})
(:phone-numbers contact))))
'()
contacts)]
(reduce (fn [m number-info]
(let [number (:number number-info)
hash (encrypt number)]
(assoc m hash number-info)))
{}
numbers-info)))
(defn send-load-contacts-identities [contacts]
(let [contacts-by-hash (get-contacts-by-hash contacts)
data (keys contacts-by-hash)]
(http-post "get-contacts" {:phone-number-hashes data}
(partial handle-load-contacts-identities-response contacts-by-hash)
(fn [error]
(toast (str error))))))
(defn load-contacts []
(contacts/load-phone-contacts
send-load-contacts-identities
(fn [error]
(toast (str error)))))
(defn handle-send-code-response [body]
(log body) (log body)
(toast (if (:confirmed body) (toast (if (:confirmed body)
"Confirmed" "Confirmed"
"Wrong code")) "Wrong code"))
(when (:confirmed body) (when (:confirmed body)
(load-contacts))) ;; TODO user action required
(sync-contacts)))
(defn code-valid? [code] (defn code-valid? [code]
(= 4 (count code))) (= 4 (count code)))
(defn send-code [code] (defn send-code [code]
(when (code-valid? code) (when (code-valid? code)
(http-post "sign-up-confirm" (intercom/sign-up-confirm code on-send-code-response)))
{:code code}
handle-send-code-response)))
(defn update-code [value] (defn update-code [value]
(let [formatted value] (let [formatted value]
(swap! state/app-state assoc :confirmation-code formatted))) (set-confirmation-code formatted)))
(defui SignUpConfirm (defui SignUpConfirm
static om/IQuery static om/IQuery
@ -134,7 +83,7 @@
:style {:alignSelf "center" :style {:alignSelf "center"
:borderRadius 7 :borderRadius 7
:backgroundColor "#E5F5F6" :backgroundColor "#E5F5F6"
:width 100}} :width 100}}
(text {:style {:marginVertical 10 (text {:style {:marginVertical 10
:textAlign "center"}} :textAlign "center"}}

View File

@ -11,6 +11,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; user data
(defn set-user-phone-number [phone-number] (defn set-user-phone-number [phone-number]
(publish! :service [:user-data :user-data/set-phone-number phone-number])) (publish! :service [:user-data :user-data/set-phone-number phone-number]))
@ -24,10 +26,29 @@
(defn load-user-whisper-identity [] (defn load-user-whisper-identity []
(publish! :service [:user-data :user-data/load-whisper-identity nil])) (publish! :service [:user-data :user-data/load-whisper-identity nil]))
(defn set-confirmation-code [confirmation-code]
(publish! :service [:user-data :user-data/set-confirmation-code confirmation-code]))
;;; server
(defn sign-up [phone-number whisper-identity handler] (defn sign-up [phone-number whisper-identity handler]
(publish! :service [:server :server/sign-up {:phone-number phone-number (publish! :service [:server :server/sign-up {:phone-number phone-number
:whisper-identity whisper-identity :whisper-identity whisper-identity
:handler handler}])) :handler handler}]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn sign-up-confirm [confirmation-code handler]
(publish! :service [:server :server/sign-up-confirm
{:confirmation-code confirmation-code
:handler handler}]))
;; contacts
(defn load-syng-contacts []
(publish! :service [:contacts :contacts/load-syng-contacts nil]))
(defn sync-contacts [handler]
(publish! :service [:contacts :contacts/sync-contacts handler]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -2,7 +2,8 @@
(:require (:require
[syng-im.utils.logging :as log] [syng-im.utils.logging :as log]
[messenger.services.user-data :refer [user-data-handler]] [messenger.services.user-data :refer [user-data-handler]]
[messenger.services.server :refer [server-handler]])) [messenger.services.server :refer [server-handler]]
[messenger.services.contacts :refer [contacts-handler]]))
(defmulti service (fn [state service-id args] (defmulti service (fn [state service-id args]
service-id)) service-id))
@ -15,6 +16,10 @@
[state service-id args] [state service-id args]
(server-handler state args)) (server-handler state args))
(defmethod service :contacts
[state service-id args]
(contacts-handler state args))
(defn services-handler [state service-id args] (defn services-handler [state service-id args]
(log/info "handling " service-id " args = " args) (log/info "handling " service-id " args = " args)
(service state service-id args)) (service state service-id args))

View File

@ -0,0 +1,54 @@
(ns messenger.models.contacts
(:require-macros [natal-shell.data-source :refer [data-source clone-with-rows]])
(:require [cljs.core.async :as async :refer [chan put! <! >!]]
[messenger.state :as state]
[messenger.utils.utils :refer [log toast http-post]]
[messenger.utils.database :as db]))
(def fake-contacts? true)
(def react-native-contacts (js/require "react-native-contacts"))
(defn- generate-contact [n]
{:name (str "Contact " n)
:photo-path ""
:phone-numbers [{:label "mobile" :number (apply str (repeat 7 n))}]
:delivery-status (if (< (rand) 0.5) :delivered :seen)
:datetime "15:30"
:new-messages-count (rand-int 3)
:online (< (rand) 0.5)})
(defn- generate-contacts [n]
(map generate-contact (range 1 (inc n))))
(defn load-phone-contacts []
(let [ch (chan)]
(if fake-contacts?
(put! ch {:error nil, :contacts (generate-contacts 10)})
(.getAll react-native-contacts
(fn [error raw-contacts]
(put! ch
{:error error
:contacts
(when (not error)
(map (fn [contact]
(merge (generate-contact 1)
{:name (:givenName contact)
:photo-path (:thumbnailPath contact)
:phone-numbers (:phoneNumbers contact)}))
(js->clj raw-contacts :keywordize-keys true)))}))))
ch))
(defn load-syng-contacts []
(let [contacts (map (fn [contact]
(merge contact
{:delivery-status (if (< (rand) 0.5) :delivered :seen)
:datetime "15:30"
:new-messages-count (rand-int 3)
:online (< (rand) 0.5)}))
(db/get-contacts))]
(swap! state/app-state update :contacts-ds
#(clone-with-rows % contacts))))
(defn save-syng-contacts [syng-contacts]
(db/add-contacts syng-contacts))

View File

@ -4,7 +4,7 @@
(:require [cljs.core.async :as async :refer [chan put! <! >!]] (:require [cljs.core.async :as async :refer [chan put! <! >!]]
[syng-im.protocol.web3 :as web3] [syng-im.protocol.web3 :as web3]
[messenger.state :as state] [messenger.state :as state]
[messenger.android.utils :refer [log on-error toast]])) [messenger.utils.utils :refer [log on-error toast]]))
(def ethereum-rpc-url "http://localhost:8545") (def ethereum-rpc-url "http://localhost:8545")
@ -50,3 +50,6 @@
(put! ch {:error error (put! ch {:error error
:value value})))) :value value}))))
ch)) ch))
(defn set-confirmation-code [code]
(swap! state/app-state assoc :confirmation-code code))

View File

@ -0,0 +1,85 @@
(ns messenger.services.contacts
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [clojure.string :as cstr]
[cljs.core.async :as async :refer [chan put! <!]]
[messenger.utils.utils :refer [log on-error http-post]]
[messenger.utils.crypt :refer [encrypt]]
[messenger.comm.intercom :as intercom :refer [save-user-phone-number]]
[messenger.models.contacts :as contacts-model]
[syng-im.utils.logging :as log]))
(defn- get-contact-name [phone-contact]
(cstr/join " "
(filter #(not (cstr/blank? %))
[(:givenName phone-contact)
(:middleName phone-contact)
(:familyName phone-contact)])))
(defn- to-syng-contacts [contacts-by-hash data]
(map (fn [server-contact]
(let [number-info (get contacts-by-hash
(:phone-number-hash server-contact))
phone-contact (:contact number-info)]
{:phone-number (:number number-info)
:whisper-identity (:whisper-identity server-contact)
:name (get-contact-name phone-contact)
:photo-path (:photo-path phone-contact)}))
(js->clj (:contacts data))))
(defn- get-contacts-by-hash [contacts]
(let [numbers-info (reduce (fn [numbers contact]
(into numbers
(map (fn [c]
{:number (:number c)
:contact contact})
(:phone-numbers contact))))
'()
contacts)]
(reduce (fn [m number-info]
(let [number (:number number-info)
hash (encrypt number)]
(assoc m hash number-info)))
{}
numbers-info)))
(defn- request-syng-contacts [contacts]
(let [contacts-by-hash (get-contacts-by-hash contacts)
data (keys contacts-by-hash)
ch (chan)]
(http-post "get-contacts" {:phone-number-hashes data}
(fn [data]
(put! ch
(to-syng-contacts contacts-by-hash data))))
ch))
(defn sync-contacts [handler]
(go
(let [result (<! (contacts-model/load-phone-contacts))]
(if-let [error (:error result)]
(on-error error)
(let [syng-contacts (<! (request-syng-contacts (:contacts result)))]
(contacts-model/save-syng-contacts syng-contacts)
(handler))))))
(defn- load-syng-contacts []
(contacts-model/load-syng-contacts)
;; TODO handle contacts
)
(defmulti contacts (fn [state id args]
id))
(defmethod contacts :contacts/load-syng-contacts
[state id args]
(log/info "handling " id " args = " args)
(load-syng-contacts))
(defmethod contacts :contacts/sync-contacts
[state id args]
(log/info "handling " id " args = " args)
(sync-contacts args))
(defn contacts-handler [state [id args]]
(log/info "user notification: " args)
(contacts state id args))

View File

@ -1,20 +1,30 @@
(ns messenger.services.server (ns messenger.services.server
(:require-macros [cljs.core.async.macros :refer [go]]) (:require-macros [cljs.core.async.macros :refer [go]])
(:require [cljs.core.async :as async :refer [chan put! <!]] (:require [cljs.core.async :as async :refer [chan put! <!]]
[messenger.android.utils :refer [log on-error http-post]] [messenger.utils.utils :refer [log on-error http-post]]
[messenger.comm.intercom :as intercom :refer [save-user-phone-number]]
[syng-im.utils.logging :as log])) [syng-im.utils.logging :as log]))
(defmulti server (fn [state id args] (defmulti server (fn [state id args]
id)) id))
(defmethod server :server/sign-up (defmethod server :server/sign-up
[state id args] [state id {:keys [phone-number whisper-identity handler] :as args}]
(log/info "handling " id " args = " args) (log/info "handling " id " args = " args)
(http-post "sign-up" (select-keys args [:phone-number :whisper-identity]) (save-user-phone-number phone-number)
(http-post "sign-up" {:phone-number phone-number
:whisper-identity whisper-identity}
(fn [body] (fn [body]
(log body) (log body)
;; TODO replace with core.async ;; TODO replace with core.async
((:handler args))))) (handler))))
(defmethod server :server/sign-up-confirm
[state id {:keys [confirmation-code handler] :as args}]
(log/info "handling " id " args = " args)
(http-post "sign-up-confirm"
{:code confirmation-code}
handler))
(defn server-handler [state [id args]] (defn server-handler [state [id args]]
(log/info "user notification: " args) (log/info "user notification: " args)

View File

@ -6,8 +6,9 @@
load-phone-number load-phone-number
save-whisper-identity save-whisper-identity
load-whisper-identity load-whisper-identity
new-whisper-identity]] new-whisper-identity
[messenger.android.utils :refer [log on-error]] set-confirmation-code]]
[messenger.utils.utils :refer [log on-error]]
[syng-im.utils.logging :as log])) [syng-im.utils.logging :as log]))
(defmulti user-data (fn [state id args] (defmulti user-data (fn [state id args]
@ -41,6 +42,11 @@
(on-error error) (on-error error)
(save-whisper-identity (:value result))))))))) (save-whisper-identity (:value result)))))))))
(defmethod user-data :user-data/set-confirmation-code
[state id confirmation-code]
(log/info "handling " id " args = " confirmation-code)
(set-confirmation-code confirmation-code))
(defn user-data-handler [state [id args]] (defn user-data-handler [state [id args]]
(log/info "user notification: " args) (log/info "user notification: " args)
(user-data state id args)) (user-data state id args))

View File

@ -1,4 +1,4 @@
(ns messenger.android.crypt (ns messenger.utils.crypt
(:require [goog.crypt :refer [byteArrayToHex]]) (:require [goog.crypt :refer [byteArrayToHex]])
(:import goog.crypt.Sha256)) (:import goog.crypt.Sha256))

View File

@ -1,5 +1,5 @@
(ns messenger.android.database (ns messenger.utils.database
(:require [messenger.android.utils :refer [log toast http-post]])) (:require [messenger.utils.utils :refer [log toast http-post]]))
(set! js/Realm (js/require "realm")) (set! js/Realm (js/require "realm"))

View File

@ -1,4 +1,4 @@
(ns messenger.android.resources) (ns messenger.utils.resources)
(def logo-icon (js/require "./images/logo.png")) (def logo-icon (js/require "./images/logo.png"))
(def nav-back-icon (js/require "./images/nav-back.png")) (def nav-back-icon (js/require "./images/nav-back.png"))

View File

@ -1,10 +1,11 @@
(ns messenger.android.utils (ns messenger.utils.utils
(:require-macros (:require-macros
[natal-shell.async-storage :refer [get-item set-item]] [natal-shell.async-storage :refer [get-item set-item]]
[natal-shell.alert :refer [alert]] [natal-shell.alert :refer [alert]]
[natal-shell.toast-android :as toast])) [natal-shell.toast-android :as toast]))
(def server-address "http://rpc0.syng.im:20000/") (def server-address "http://rpc0.syng.im:20000/")
;; (def server-address "http://10.0.3.2:3000/")
(defn log [obj] (defn log [obj]
(.log js/console obj)) (.log js/console obj))