Rewrite sync contacts with server
This commit is contained in:
parent
7fdb31b73e
commit
2a0d39726a
|
@ -10,6 +10,7 @@
|
||||||
[syng-im.components.contact-list.contact-list :refer [contact-list]]
|
[syng-im.components.contact-list.contact-list :refer [contact-list]]
|
||||||
[syng-im.components.chat :refer [chat]]
|
[syng-im.components.chat :refer [chat]]
|
||||||
[syng-im.components.login :refer [login-view]]
|
[syng-im.components.login :refer [login-view]]
|
||||||
|
[syng-im.components.sign-up-confirm :refer [sign-up-confirm-view]]
|
||||||
|
|
||||||
;; [syng-im.components.chat.chat :refer [chat]]
|
;; [syng-im.components.chat.chat :refer [chat]]
|
||||||
[syng-im.components.nav :as nav]
|
[syng-im.components.nav :as nav]
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
})
|
})
|
||||||
:render-scene (fn [route nav]
|
:render-scene (fn [route nav]
|
||||||
(log/debug "route" route)
|
(log/debug "route" route)
|
||||||
(when nav/*nav-render*
|
(when true ;; nav/*nav-render*
|
||||||
(let [{:keys [view-id]} (js->clj route :keywordize-keys true)
|
(let [{:keys [view-id]} (js->clj route :keywordize-keys true)
|
||||||
view-id (keyword view-id)]
|
view-id (keyword view-id)]
|
||||||
(init-back-button-handler! nav)
|
(init-back-button-handler! nav)
|
||||||
|
@ -50,7 +51,9 @@
|
||||||
:contact-list (r/as-element [contact-list
|
:contact-list (r/as-element [contact-list
|
||||||
{:navigator nav}])
|
{:navigator nav}])
|
||||||
:chat (r/as-element [chat {:navigator nav}])
|
:chat (r/as-element [chat {:navigator nav}])
|
||||||
:login (r/as-element [login-view {:navigator nav}])))))}])
|
:login (r/as-element [login-view {:navigator nav}])
|
||||||
|
:sign-up-confirm (r/as-element [sign-up-confirm-view
|
||||||
|
{:navigator nav}])))))}])
|
||||||
|
|
||||||
(defn init []
|
(defn init []
|
||||||
(dispatch-sync [:initialize-db])
|
(dispatch-sync [:initialize-db])
|
||||||
|
|
|
@ -6,20 +6,18 @@
|
||||||
[syng-im.components.spinner :refer [spinner]]
|
[syng-im.components.spinner :refer [spinner]]
|
||||||
[syng-im.components.nav :as nav]
|
[syng-im.components.nav :as nav]
|
||||||
[syng-im.utils.utils :refer [log toast http-post]]
|
[syng-im.utils.utils :refer [log toast http-post]]
|
||||||
[syng-im.utils.phone-number :refer [format-phone-number]]
|
[syng-im.utils.phone-number :refer [format-phone-number]]))
|
||||||
;; [messenger.android.sign-up-confirm :refer [sign-up-confirm]]
|
|
||||||
))
|
|
||||||
|
|
||||||
(def nav-atom (atom nil))
|
;; (def nav-atom (atom nil))
|
||||||
|
|
||||||
(defn show-confirm-view []
|
(defn show-confirm-view [navigator]
|
||||||
(dispatch [:set-loading false])
|
(dispatch [:set-loading false])
|
||||||
;; TODO 'nav-replace
|
;; TODO 'nav-replace
|
||||||
(nav/nav-push @nav-atom {:view-id :chat}))
|
(nav/nav-push navigator {:view-id :sign-up-confirm}))
|
||||||
|
|
||||||
(defn sign-up [user-phone-number user-identity]
|
(defn sign-up [user-phone-number user-identity navigator]
|
||||||
(dispatch [:set-loading true])
|
(dispatch [:set-loading true])
|
||||||
(dispatch [:sign-up user-phone-number user-identity show-confirm-view]))
|
(dispatch [:sign-up user-phone-number user-identity #(show-confirm-view navigator)]))
|
||||||
|
|
||||||
(defn update-phone-number [value]
|
(defn update-phone-number [value]
|
||||||
(let [formatted (format-phone-number value)]
|
(let [formatted (format-phone-number value)]
|
||||||
|
@ -30,7 +28,7 @@
|
||||||
user-phone-number (subscribe [:get-user-phone-number])
|
user-phone-number (subscribe [:get-user-phone-number])
|
||||||
user-identity (subscribe [:get-user-identity])]
|
user-identity (subscribe [:get-user-identity])]
|
||||||
(fn []
|
(fn []
|
||||||
(reset! nav-atom navigator)
|
;; (reset! nav-atom navigator)
|
||||||
[view {:style {:flex 1}}
|
[view {:style {:flex 1}}
|
||||||
[view {:style {:flex 1
|
[view {:style {:flex 1
|
||||||
:backgroundColor "white"}}
|
:backgroundColor "white"}}
|
||||||
|
@ -53,7 +51,7 @@
|
||||||
:fontFamily "Avenir-Roman"
|
:fontFamily "Avenir-Roman"
|
||||||
:color "#9CBFC0"}}
|
:color "#9CBFC0"}}
|
||||||
@user-phone-number]
|
@user-phone-number]
|
||||||
[touchable-highlight {:onPress #(sign-up @user-phone-number @user-identity)
|
[touchable-highlight {:onPress #(sign-up @user-phone-number @user-identity navigator)
|
||||||
:style {:alignSelf "center"
|
:style {:alignSelf "center"
|
||||||
:borderRadius 7
|
:borderRadius 7
|
||||||
:backgroundColor "#E5F5F6"
|
:backgroundColor "#E5F5F6"
|
||||||
|
@ -61,6 +59,5 @@
|
||||||
[text {:style {:marginVertical 10
|
[text {:style {:marginVertical 10
|
||||||
:textAlign "center"}}
|
:textAlign "center"}}
|
||||||
"Sign up"]]]]
|
"Sign up"]]]]
|
||||||
;; (when (or loading (not user-identity))
|
(when (or @loading (not @user-identity))
|
||||||
;; [spinner {:visible true}])
|
[spinner {:visible true}])])))
|
||||||
])))
|
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
(ns syng-im.components.sign-up-confirm
|
||||||
|
(:require-macros
|
||||||
|
[natal-shell.core :refer [with-error-view]])
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||||
|
[syng-im.components.react :refer [view text image touchable-highlight list-view
|
||||||
|
toolbar-android text-input]]
|
||||||
|
[syng-im.components.resources :as res]
|
||||||
|
[syng-im.components.spinner :refer [spinner]]
|
||||||
|
[syng-im.components.nav :as nav]
|
||||||
|
[syng-im.utils.utils :refer [log toast http-post]]))
|
||||||
|
|
||||||
|
(defn show-home-view [navigator]
|
||||||
|
(dispatch [:set-loading false])
|
||||||
|
(nav/nav-push navigator {:view-id :contact-list}))
|
||||||
|
|
||||||
|
(defn sync-contacts [navigator]
|
||||||
|
(dispatch [:sync-contacts #(show-home-view navigator)]))
|
||||||
|
|
||||||
|
(defn on-send-code-response [navigator body]
|
||||||
|
(log body)
|
||||||
|
(toast (if (:confirmed body)
|
||||||
|
"Confirmed"
|
||||||
|
"Wrong code"))
|
||||||
|
(if (:confirmed body)
|
||||||
|
;; TODO user action required
|
||||||
|
(sync-contacts navigator)
|
||||||
|
(dispatch [:set-loading false])))
|
||||||
|
|
||||||
|
(defn code-valid? [code]
|
||||||
|
(= 4 (count code)))
|
||||||
|
|
||||||
|
(defn send-code [code navigator]
|
||||||
|
(when (code-valid? code)
|
||||||
|
(dispatch [:set-loading true])
|
||||||
|
(dispatch [:sign-up-confirm code (partial on-send-code-response navigator)])))
|
||||||
|
|
||||||
|
(defn update-code [value]
|
||||||
|
(let [formatted value]
|
||||||
|
(dispatch [:set-confirmation-code formatted])))
|
||||||
|
|
||||||
|
(defn sign-up-confirm-view [{:keys [navigator]}]
|
||||||
|
(let [loading (subscribe [:get-loading])
|
||||||
|
confirmation-code (subscribe [:get-confirmation-code])]
|
||||||
|
(fn []
|
||||||
|
[view {:style {:flex 1}}
|
||||||
|
[view {:style {:flex 1
|
||||||
|
:backgroundColor "white"}}
|
||||||
|
[toolbar-android {:logo res/logo-icon
|
||||||
|
:title "Confirm"
|
||||||
|
:titleColor "#4A5258"
|
||||||
|
:style {:backgroundColor "white"
|
||||||
|
:height 56
|
||||||
|
:elevation 2}}]
|
||||||
|
[view {}
|
||||||
|
[text-input {:underlineColorAndroid "#9CBFC0"
|
||||||
|
:placeholder "Enter confirmation code"
|
||||||
|
:keyboardType "number-pad"
|
||||||
|
:maxLength 4
|
||||||
|
:onChangeText (fn [value]
|
||||||
|
(update-code value))
|
||||||
|
:style {:flex 1
|
||||||
|
:marginHorizontal 18
|
||||||
|
:lineHeight 42
|
||||||
|
:fontSize 14
|
||||||
|
:fontFamily "Avenir-Roman"
|
||||||
|
:color "#9CBFC0"}}
|
||||||
|
@confirmation-code]
|
||||||
|
(if (code-valid? @confirmation-code)
|
||||||
|
[touchable-highlight {:onPress #(send-code @confirmation-code navigator)
|
||||||
|
:style {:alignSelf "center"
|
||||||
|
:borderRadius 7
|
||||||
|
:backgroundColor "#E5F5F6"
|
||||||
|
|
||||||
|
:width 100}}
|
||||||
|
[text {:style {:marginVertical 10
|
||||||
|
:textAlign "center"}}
|
||||||
|
"Confirm"]]
|
||||||
|
[view {:style {:alignSelf "center"
|
||||||
|
:borderRadius 7
|
||||||
|
:backgroundColor "#AAB2B2"
|
||||||
|
:width 100}}
|
||||||
|
[text {:style {:marginVertical 10
|
||||||
|
:textAlign "center"}}
|
||||||
|
"Confirm"]])]]
|
||||||
|
(when @loading
|
||||||
|
[spinner {:visible true}])])))
|
|
@ -12,6 +12,7 @@
|
||||||
[syng-im.models.messages :refer [save-message
|
[syng-im.models.messages :refer [save-message
|
||||||
new-message-arrived]]
|
new-message-arrived]]
|
||||||
[syng-im.handlers.server :as server]
|
[syng-im.handlers.server :as server]
|
||||||
|
[syng-im.handlers.contacts :as contacts-service]
|
||||||
[syng-im.utils.logging :as log]))
|
[syng-im.utils.logging :as log]))
|
||||||
|
|
||||||
;; -- Middleware ------------------------------------------------------------
|
;; -- Middleware ------------------------------------------------------------
|
||||||
|
@ -76,6 +77,20 @@
|
||||||
(server/sign-up phone-number whisper-identity handler)
|
(server/sign-up phone-number whisper-identity handler)
|
||||||
db))
|
db))
|
||||||
|
|
||||||
|
(register-handler :set-confirmation-code
|
||||||
|
(fn [db [_ value]]
|
||||||
|
(assoc db :confirmation-code value)))
|
||||||
|
|
||||||
|
(register-handler :sign-up-confirm
|
||||||
|
(fn [db [_ confirmation-code handler]]
|
||||||
|
(server/sign-up-confirm confirmation-code handler)
|
||||||
|
db))
|
||||||
|
|
||||||
|
(register-handler :sync-contacts
|
||||||
|
(fn [db [_ handler]]
|
||||||
|
(contacts-service/sync-contacts handler)
|
||||||
|
db))
|
||||||
|
|
||||||
;; -- Contacts --------------------------------------------------------------
|
;; -- Contacts --------------------------------------------------------------
|
||||||
|
|
||||||
(register-handler :load-syng-contacts
|
(register-handler :load-syng-contacts
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
(ns syng-im.handlers.contacts
|
||||||
|
(:require-macros [cljs.core.async.macros :refer [go]])
|
||||||
|
(:require [clojure.string :as cstr]
|
||||||
|
[cljs.core.async :as async :refer [chan put! <!]]
|
||||||
|
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||||
|
[syng-im.utils.utils :refer [log on-error http-post toast]]
|
||||||
|
[syng-im.utils.crypt :refer [encrypt]]
|
||||||
|
[syng-im.utils.phone-number :refer [format-phone-number]]
|
||||||
|
[syng-im.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 (format-phone-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)
|
||||||
|
(dispatch [:load-syng-contacts])
|
||||||
|
(handler))))))
|
|
@ -8,14 +8,13 @@
|
||||||
[phone-number whisper-identity handler]
|
[phone-number whisper-identity handler]
|
||||||
(user-data/save-phone-number phone-number)
|
(user-data/save-phone-number phone-number)
|
||||||
(http-post "sign-up" {:phone-number phone-number
|
(http-post "sign-up" {:phone-number phone-number
|
||||||
:whisper-identity whisper-identity}
|
:whisper-identity (:public whisper-identity)}
|
||||||
(fn [body]
|
(fn [body]
|
||||||
(log body)
|
(log body)
|
||||||
(handler))))
|
(handler))))
|
||||||
|
|
||||||
(defn sign-up-confirm
|
(defn sign-up-confirm
|
||||||
[state id {:keys [confirmation-code handler] :as args}]
|
[confirmation-code handler]
|
||||||
(log/info "handling " id " args = " args)
|
|
||||||
(http-post "sign-up-confirm"
|
(http-post "sign-up-confirm"
|
||||||
{:code confirmation-code}
|
{:code confirmation-code}
|
||||||
handler))
|
handler))
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
[syng-im.utils.utils :refer [log toast]]
|
[syng-im.utils.utils :refer [log toast]]
|
||||||
[syng-im.persistence.realm :as realm]))
|
[syng-im.persistence.realm :as realm]))
|
||||||
|
|
||||||
(def fake-contacts? true)
|
;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45
|
||||||
|
(def fake-phone-contacts? true)
|
||||||
|
(def fake-contacts? false)
|
||||||
|
|
||||||
(def react-native-contacts (js/require "react-native-contacts"))
|
(def react-native-contacts (js/require "react-native-contacts"))
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@
|
||||||
|
|
||||||
(defn load-phone-contacts []
|
(defn load-phone-contacts []
|
||||||
(let [ch (chan)]
|
(let [ch (chan)]
|
||||||
(if fake-contacts?
|
(if fake-phone-contacts?
|
||||||
(put! ch {:error nil, :contacts (generate-contacts 10)})
|
(put! ch {:error nil, :contacts (generate-contacts 10)})
|
||||||
(.getAll react-native-contacts
|
(.getAll react-native-contacts
|
||||||
(fn [error raw-contacts]
|
(fn [error raw-contacts]
|
||||||
|
@ -32,7 +34,6 @@
|
||||||
(when (not error)
|
(when (not error)
|
||||||
(log raw-contacts)
|
(log raw-contacts)
|
||||||
(map (fn [contact]
|
(map (fn [contact]
|
||||||
;; (toast (str contact))
|
|
||||||
(merge contact
|
(merge contact
|
||||||
(generate-contact 1)
|
(generate-contact 1)
|
||||||
{:name (:givenName contact)
|
{:name (:givenName contact)
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
:get-user-identity
|
:get-user-identity
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(reaction
|
(reaction
|
||||||
(get @db :identity))))
|
(get @db :user-identity))))
|
||||||
|
|
||||||
(register-sub
|
(register-sub
|
||||||
:get-loading
|
:get-loading
|
||||||
|
@ -27,6 +27,12 @@
|
||||||
(reaction
|
(reaction
|
||||||
(get @db :loading))))
|
(get @db :loading))))
|
||||||
|
|
||||||
|
(register-sub
|
||||||
|
:get-confirmation-code
|
||||||
|
(fn [db _]
|
||||||
|
(reaction
|
||||||
|
(get @db :confirmation-code))))
|
||||||
|
|
||||||
(register-sub
|
(register-sub
|
||||||
:get-contacts
|
:get-contacts
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
|
|
Loading…
Reference in New Issue