After Width: | Height: | Size: 651 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 526 B |
After Width: | Height: | Size: 529 B |
After Width: | Height: | Size: 985 B |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 307 B |
After Width: | Height: | Size: 898 B |
After Width: | Height: | Size: 284 B |
After Width: | Height: | Size: 584 B |
|
@ -7,10 +7,10 @@
|
||||||
[syng-im.handlers]
|
[syng-im.handlers]
|
||||||
[syng-im.subs]
|
[syng-im.subs]
|
||||||
[syng-im.components.react :refer [navigator app-registry]]
|
[syng-im.components.react :refer [navigator app-registry]]
|
||||||
|
[syng-im.components.contact-list.contact-list :refer [contact-list]]
|
||||||
[syng-im.components.chat :refer [chat]]
|
[syng-im.components.chat :refer [chat]]
|
||||||
[syng-im.utils.logging :as log]))
|
[syng-im.utils.logging :as log]))
|
||||||
|
|
||||||
|
|
||||||
(def ^{:dynamic true :private true} *nav-render*
|
(def ^{:dynamic true :private true} *nav-render*
|
||||||
"Flag to suppress navigator re-renders from outside om when pushing/popping."
|
"Flag to suppress navigator re-renders from outside om when pushing/popping."
|
||||||
true)
|
true)
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
(def back-button-handler (cljs/atom {:nav nil
|
(def back-button-handler (cljs/atom {:nav nil
|
||||||
:handler nil}))
|
:handler nil}))
|
||||||
|
|
||||||
|
|
||||||
(defn init-back-button-handler! [nav]
|
(defn init-back-button-handler! [nav]
|
||||||
(let [handler @back-button-handler]
|
(let [handler @back-button-handler]
|
||||||
(when-not (= nav (:nav handler))
|
(when-not (= nav (:nav handler))
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
(add-event-listener "hardwareBackPress" new-listener)))))
|
(add-event-listener "hardwareBackPress" new-listener)))))
|
||||||
|
|
||||||
(defn app-root []
|
(defn app-root []
|
||||||
[navigator {:initial-route (clj->js {:view-id :chat})
|
[navigator {:initial-route (clj->js {:view-id :contact-list})
|
||||||
:render-scene (fn [route nav]
|
:render-scene (fn [route nav]
|
||||||
(log/debug "route" route)
|
(log/debug "route" route)
|
||||||
(when *nav-render*
|
(when *nav-render*
|
||||||
|
@ -40,9 +41,12 @@
|
||||||
view-id (keyword view-id)]
|
view-id (keyword view-id)]
|
||||||
(init-back-button-handler! nav)
|
(init-back-button-handler! nav)
|
||||||
(case view-id
|
(case view-id
|
||||||
|
:contact-list (r/as-element [contact-list
|
||||||
|
{:navigator nav}])
|
||||||
:chat (r/as-element [chat {:navigator nav}])))))}])
|
:chat (r/as-element [chat {:navigator nav}])))))}])
|
||||||
|
|
||||||
(defn init []
|
(defn init []
|
||||||
(dispatch-sync [:initialize-db])
|
(dispatch-sync [:initialize-db])
|
||||||
(dispatch [:initialize-protocol])
|
(dispatch [:initialize-protocol])
|
||||||
|
(dispatch [:load-syng-contacts])
|
||||||
(.registerComponent app-registry "SyngIm" #(r/reactify-component app-root)))
|
(.registerComponent app-registry "SyngIm" #(r/reactify-component app-root)))
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
(ns syng-im.components.contact-list.contact
|
||||||
|
(:require [syng-im.components.react :refer [view text image touchable-highlight]]
|
||||||
|
[syng-im.components.resources :as res]
|
||||||
|
;; [messenger.comm.intercom :as intercom :refer [show-chat]]
|
||||||
|
;; [messenger.components.chat.chat :refer [chat]]
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn contact-view [contact]
|
||||||
|
(let [{:keys [name photo-path delivery-status datetime new-messages-count
|
||||||
|
online whisper-identity]} contact]
|
||||||
|
[touchable-highlight {:onPress (fn []
|
||||||
|
;; TODO
|
||||||
|
;; (show-chat nav whisper-identity)
|
||||||
|
)}
|
||||||
|
[view {:style {:flexDirection "row"
|
||||||
|
:marginTop 5
|
||||||
|
:marginBottom 5
|
||||||
|
:paddingLeft 15
|
||||||
|
:paddingRight 15
|
||||||
|
:height 75}}
|
||||||
|
[view {:width 54
|
||||||
|
:height 54}
|
||||||
|
;;; photo
|
||||||
|
[view {:width 54
|
||||||
|
:height 54
|
||||||
|
:borderRadius 50
|
||||||
|
:backgroundColor "#FFFFFF"
|
||||||
|
:elevation 6}
|
||||||
|
[image {:source (if (< 0 (count photo-path))
|
||||||
|
{:uri photo-path}
|
||||||
|
res/user-no-photo)
|
||||||
|
:style {:borderWidth 2
|
||||||
|
:borderColor "#FFFFFF"
|
||||||
|
:borderRadius 50
|
||||||
|
:width 54
|
||||||
|
:height 54
|
||||||
|
:position "absolute"}}]]
|
||||||
|
;;; online
|
||||||
|
(when online
|
||||||
|
[view {:position "absolute"
|
||||||
|
:top 41
|
||||||
|
:left 36
|
||||||
|
:width 12
|
||||||
|
:height 12
|
||||||
|
:borderRadius 50
|
||||||
|
:backgroundColor "#FFFFFF"
|
||||||
|
:elevation 6}
|
||||||
|
[image {:source res/online-icon
|
||||||
|
:style {:width 12
|
||||||
|
:height 12}}]])]
|
||||||
|
[view {:style {:flexDirection "column"
|
||||||
|
:marginLeft 7
|
||||||
|
:marginRight 10
|
||||||
|
:flex 1
|
||||||
|
:position "relative"}}
|
||||||
|
;;; name
|
||||||
|
[text {:style {:fontSize 15
|
||||||
|
:fontFamily "Avenir-Roman"}} name]
|
||||||
|
;;; last message
|
||||||
|
[text {:style {:color "#AAB2B2"
|
||||||
|
:fontFamily "Avenir-Roman"
|
||||||
|
:fontSize 14
|
||||||
|
:marginTop 2
|
||||||
|
:paddingRight 10}}
|
||||||
|
(str "Hi, I'm " name)]]
|
||||||
|
[view {:style {:flexDirection "column"}}
|
||||||
|
;;; delivery status
|
||||||
|
[view {:style {:flexDirection "row"
|
||||||
|
:position "absolute"
|
||||||
|
:top 0
|
||||||
|
:right 0}}
|
||||||
|
(when delivery-status
|
||||||
|
[image {:source (if (= (keyword delivery-status) :seen)
|
||||||
|
res/seen-icon
|
||||||
|
res/delivered-icon)
|
||||||
|
:style {:marginTop 5}}])
|
||||||
|
;;; datetime
|
||||||
|
[text {:style {:fontFamily "Avenir-Roman"
|
||||||
|
:fontSize 11
|
||||||
|
:color "#AAB2B2"
|
||||||
|
:letterSpacing 1
|
||||||
|
:lineHeight 15
|
||||||
|
:marginLeft 5}}
|
||||||
|
datetime]]
|
||||||
|
;;; new messages count
|
||||||
|
(when (< 0 new-messages-count)
|
||||||
|
[view {:style {:position "absolute"
|
||||||
|
:right 0
|
||||||
|
:bottom 24
|
||||||
|
:width 18
|
||||||
|
:height 18
|
||||||
|
:backgroundColor "#6BC6C8"
|
||||||
|
:borderColor "#FFFFFF"
|
||||||
|
:borderRadius 50
|
||||||
|
:alignSelf "flex-end"}}
|
||||||
|
[text {:style {:width 18
|
||||||
|
:height 17
|
||||||
|
:fontFamily "Avenir-Roman"
|
||||||
|
:fontSize 10
|
||||||
|
:color "#FFFFFF"
|
||||||
|
:lineHeight 19
|
||||||
|
:textAlign "center"
|
||||||
|
:top 1}}
|
||||||
|
new-messages-count]])]]]))
|
|
@ -0,0 +1,96 @@
|
||||||
|
(ns syng-im.components.contact-list.contact-list
|
||||||
|
(:require-macros
|
||||||
|
[natal-shell.data-source :refer [data-source clone-with-rows]]
|
||||||
|
[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
|
||||||
|
navigator list-view toolbar-android
|
||||||
|
list-item]]
|
||||||
|
[syng-im.components.resources :as res]
|
||||||
|
[syng-im.components.contact-list.contact :refer [contact-view]]
|
||||||
|
[syng-im.utils.logging :as log]
|
||||||
|
;; [messenger.comm.intercom :as intercom]
|
||||||
|
;; [messenger.components.contact-list.contact :refer [contact]]
|
||||||
|
;; [messenger.components.iname :as in]
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn render-row [row section-id row-id]
|
||||||
|
(list-item (contact-view (js->clj row :keywordize-keys true))))
|
||||||
|
|
||||||
|
;; (defn load-contacts []
|
||||||
|
;; (intercom/load-syng-contacts))
|
||||||
|
|
||||||
|
;; (defui ContactList
|
||||||
|
;; static in/IName
|
||||||
|
;; (get-name [this]
|
||||||
|
;; :contacts/contacts)
|
||||||
|
;; static om/IQuery
|
||||||
|
;; (query [this]
|
||||||
|
;; '[:contacts-ds])
|
||||||
|
;; Object
|
||||||
|
;; (componentDidMount [this]
|
||||||
|
;; (load-contacts))
|
||||||
|
;; (render [this]
|
||||||
|
;; (let [{{contacts-ds :contacts-ds} :contacts/contacts} (om/props this)
|
||||||
|
;; {:keys [nav]} (om/get-computed this)]
|
||||||
|
;; (view {:style {:flex 1
|
||||||
|
;; :backgroundColor "white"}}
|
||||||
|
;; (toolbar-android {:logo res/logo-icon
|
||||||
|
;; :title "Chats"
|
||||||
|
;; :titleColor "#4A5258"
|
||||||
|
;; :style {:backgroundColor "white"
|
||||||
|
;; :height 56
|
||||||
|
;; :elevation 2}})
|
||||||
|
;; (when contacts-ds
|
||||||
|
;; (list-view {:dataSource contacts-ds
|
||||||
|
;; :renderRow (partial render-row nav)
|
||||||
|
;; :style {:backgroundColor "white"}}))))))
|
||||||
|
|
||||||
|
;; (def contact-list (om/factory ContactList))
|
||||||
|
|
||||||
|
(defn get-data-source [contacts]
|
||||||
|
(clone-with-rows (data-source {:rowHasChanged (fn [row1 row2]
|
||||||
|
(not= row1 row2))})
|
||||||
|
contacts))
|
||||||
|
|
||||||
|
(defn contacts-list-re-frame [contacts]
|
||||||
|
(let [contacts-ds (get-data-source contacts)]
|
||||||
|
[view {:style {:flex 1
|
||||||
|
:backgroundColor "white"}}
|
||||||
|
[toolbar-android {:logo res/logo-icon
|
||||||
|
:title "Chats"
|
||||||
|
:titleColor "#4A5258"
|
||||||
|
:style {:backgroundColor "white"
|
||||||
|
:height 56
|
||||||
|
:elevation 2}}]
|
||||||
|
(when contacts-ds
|
||||||
|
[list-view {:dataSource contacts-ds
|
||||||
|
:renderRow render-row
|
||||||
|
:style {:backgroundColor "white"}}]
|
||||||
|
)
|
||||||
|
]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(def logo-img (js/require "./images/cljs.png"))
|
||||||
|
|
||||||
|
|
||||||
|
(defn alert [title]
|
||||||
|
(.alert (.-Alert js/React) title))
|
||||||
|
|
||||||
|
(defn contact-list [{:keys [navigator]}]
|
||||||
|
(let [greeting (subscribe [:get-greeting])
|
||||||
|
contacts (subscribe [:get-contacts])]
|
||||||
|
(fn []
|
||||||
|
(contacts-list-re-frame @contacts)
|
||||||
|
|
||||||
|
;; [view {:style {:flex-direction "column" :margin 40 :align-items "center"}}
|
||||||
|
;; [text {:style {:font-size 30 :font-weight "100" :margin-bottom 20 :text-align "center"}} (str @greeting " " (count @contacts))]
|
||||||
|
;; [image {:source logo-img
|
||||||
|
;; :style {:width 80 :height 80 :margin-bottom 30}}]
|
||||||
|
;; [touchable-highlight {:style {:background-color "#999" :padding 10 :border-radius 5}
|
||||||
|
;; :on-press #(alert "HELLO!")}
|
||||||
|
;; [text {:style {:color "white" :text-align "center" :font-weight "bold"}} "press me"]]]
|
||||||
|
)))
|
|
@ -8,4 +8,43 @@
|
||||||
(def text (r/adapt-react-class (.-Text js/React)))
|
(def text (r/adapt-react-class (.-Text js/React)))
|
||||||
(def view (r/adapt-react-class (.-View js/React)))
|
(def view (r/adapt-react-class (.-View js/React)))
|
||||||
(def image (r/adapt-react-class (.-Image js/React)))
|
(def image (r/adapt-react-class (.-Image js/React)))
|
||||||
(def touchable-highlight (r/adapt-react-class (.-TouchableHighlight js/React)))
|
(def touchable-highlight (r/adapt-react-class (.-TouchableHighlight js/React)))
|
||||||
|
(def toolbar-android (r/adapt-react-class (.-ToolbarAndroid js/React)))
|
||||||
|
(def list-view (r/adapt-react-class (.-ListView js/React)))
|
||||||
|
|
||||||
|
(defn list-item [component]
|
||||||
|
(r/as-element component))
|
||||||
|
|
||||||
|
;; (do
|
||||||
|
;; (def activity-indicator-ios (r/adapt-react-class (.-ActivityIndicatorIOS js/React)))
|
||||||
|
;; (def animated-image (r/adapt-react-class (.-Animated.Image js/React)))
|
||||||
|
;; (def animated-text (r/adapt-react-class (.-Animated.Text js/React)))
|
||||||
|
;; (def animated-view (r/adapt-react-class (.-Animated.View js/React)))
|
||||||
|
;; (def date-picker-ios (r/adapt-react-class (.-DatePickerIOS js/React)))
|
||||||
|
;; (def drawer-layout-android (r/adapt-react-class (.-DrawerLayoutAndroid js/React)))
|
||||||
|
;; (def image (r/adapt-react-class (.-Image js/React)))
|
||||||
|
;; (def list-view (r/adapt-react-class (.-ListView js/React)))
|
||||||
|
;; (def map-view (r/adapt-react-class (.-MapView js/React)))
|
||||||
|
;; (def modal (r/adapt-react-class (.-Modal js/React)))
|
||||||
|
;; (def navigator (r/adapt-react-class (.-Navigator js/React)))
|
||||||
|
;; (def navigator-ios (r/adapt-react-class (.-NavigatorIOS js/React)))
|
||||||
|
;; (def picker-ios (r/adapt-react-class (.-PickerIOS js/React)))
|
||||||
|
;; (def progress-bar-android (r/adapt-react-class (.-ProgressBarAndroid js/React)))
|
||||||
|
;; (def progress-view-ios (r/adapt-react-class (.-ProgressViewIOS js/React)))
|
||||||
|
;; (def pull-to-refresh-view-android (r/adapt-react-class (.-PullToRefreshViewAndroid js/React)))
|
||||||
|
;; (def scroll-view (r/adapt-react-class (.-ScrollView js/React)))
|
||||||
|
;; (def segmented-control-ios (r/adapt-react-class (.-SegmentedControlIOS js/React)))
|
||||||
|
;; (def slider-ios (r/adapt-react-class (.-SliderIOS js/React)))
|
||||||
|
;; (def switch (r/adapt-react-class (.-Switch js/React)))
|
||||||
|
;; (def tab-bar-ios (r/adapt-react-class (.-TabBarIOS js/React)))
|
||||||
|
;; (def tab-bar-ios-item (r/adapt-react-class (.-TabBarIOS.Item js/React)))
|
||||||
|
;; (def text (r/adapt-react-class (.-Text js/React)))
|
||||||
|
;; (def text-input (r/adapt-react-class (.-TextInput js/React)))
|
||||||
|
;; (def toolbar-android (r/adapt-react-class (.-ToolbarAndroid js/React)))
|
||||||
|
;; (def touchable-highlight (r/adapt-react-class (.-TouchableHighlight js/React)))
|
||||||
|
;; (def touchable-native-feedback (r/adapt-react-class (.-TouchableNativeFeedback js/React)))
|
||||||
|
;; (def touchable-opacity (r/adapt-react-class (.-TouchableOpacity js/React)))
|
||||||
|
;; (def touchable-without-feedback (r/adapt-react-class (.-TouchableWithoutFeedback js/React)))
|
||||||
|
;; (def view (r/adapt-react-class (.-View js/React)))
|
||||||
|
;; (def view-pager-android (r/adapt-react-class (.-ViewPagerAndroid js/React)))
|
||||||
|
;; (def web-view (r/adapt-react-class (.-WebView js/React))))
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
(ns syng-im.components.resources)
|
||||||
|
|
||||||
|
(def logo-icon (js/require "./images/logo.png"))
|
||||||
|
(def nav-back-icon (js/require "./images/nav-back.png"))
|
||||||
|
(def user-no-photo (js/require "./images/no-photo.png"))
|
||||||
|
(def online-icon (js/require "./images/online.png"))
|
||||||
|
(def seen-icon (js/require "./images/seen.png"))
|
||||||
|
(def delivered-icon (js/require "./images/delivered.png"))
|
||||||
|
(def play (js/require "./images/play.png"))
|
||||||
|
(def mic (js/require "./images/mic.png"))
|
||||||
|
(def smile (js/require "./images/smile.png"))
|
||||||
|
(def att (js/require "./images/att.png"))
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
;; initial state of app-db
|
;; initial state of app-db
|
||||||
(def app-db {:greeting "Hello Clojure in iOS and Android!"
|
(def app-db {:greeting "Hello Clojure in iOS and Android!"
|
||||||
:identity-password "replace-me-with-user-entered-password"})
|
:identity-password "replace-me-with-user-entered-password"
|
||||||
|
:contacts []})
|
||||||
|
|
||||||
|
|
||||||
(def protocol-initialized-path [:protocol-initialized])
|
(def protocol-initialized-path [:protocol-initialized])
|
||||||
|
@ -14,4 +15,4 @@
|
||||||
(def identity-password-path [:identity-password])
|
(def identity-password-path [:identity-password])
|
||||||
(def current-chat-id-path [:chat :current-chat-id])
|
(def current-chat-id-path [:chat :current-chat-id])
|
||||||
(defn arrived-message-path [chat-id]
|
(defn arrived-message-path [chat-id]
|
||||||
[:chat chat-id :arrived-message-id])
|
[:chat chat-id :arrived-message-id])
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
[syng-im.protocol.protocol-handler :refer [make-handler]]
|
[syng-im.protocol.protocol-handler :refer [make-handler]]
|
||||||
[syng-im.models.protocol :refer [update-identity
|
[syng-im.models.protocol :refer [update-identity
|
||||||
set-initialized]]
|
set-initialized]]
|
||||||
|
[syng-im.models.contacts :as contacts]
|
||||||
[syng-im.models.messages :refer [save-message
|
[syng-im.models.messages :refer [save-message
|
||||||
new-message-arrived]]
|
new-message-arrived]]
|
||||||
[syng-im.utils.logging :as log]))
|
[syng-im.utils.logging :as log]))
|
||||||
|
@ -49,8 +50,14 @@
|
||||||
(save-message chat-id msg)
|
(save-message chat-id msg)
|
||||||
(new-message-arrived db chat-id msg-id)))
|
(new-message-arrived db chat-id msg-id)))
|
||||||
|
|
||||||
|
;; -- Contacts --------------------------------------------------------------
|
||||||
|
|
||||||
|
(register-handler :load-syng-contacts
|
||||||
|
(fn [db [_ value]]
|
||||||
|
(contacts/load-syng-contacts db)))
|
||||||
|
|
||||||
;; -- Something --------------------------------------------------------------
|
;; -- Something --------------------------------------------------------------
|
||||||
|
|
||||||
(register-handler :set-greeting
|
(register-handler :set-greeting
|
||||||
(fn [db [_ value]]
|
(fn [db [_ value]]
|
||||||
(assoc db :greeting value)))
|
(assoc db :greeting value)))
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
(ns syng-im.models.contacts
|
||||||
|
(:require [cljs.core.async :as async :refer [chan put! <! >!]]
|
||||||
|
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||||
|
[syng-im.utils.utils :refer [log toast]]
|
||||||
|
[syng-im.persistence.realm :as realm]))
|
||||||
|
|
||||||
|
(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)
|
||||||
|
(log raw-contacts)
|
||||||
|
(map (fn [contact]
|
||||||
|
;; (toast (str contact))
|
||||||
|
(merge contact
|
||||||
|
(generate-contact 1)
|
||||||
|
{:name (:givenName contact)
|
||||||
|
:photo-path (:thumbnailPath contact)
|
||||||
|
:phone-numbers (:phoneNumbers contact)}))
|
||||||
|
(js->clj raw-contacts :keywordize-keys true)))}))))
|
||||||
|
ch))
|
||||||
|
|
||||||
|
(defn- get-contacts []
|
||||||
|
(if fake-contacts?
|
||||||
|
[{:phone-number "123"
|
||||||
|
:whisper-identity "abc"
|
||||||
|
:name "fake"
|
||||||
|
:photo-path ""}]
|
||||||
|
(realm/get-list "Contact")))
|
||||||
|
|
||||||
|
(defn load-syng-contacts [db]
|
||||||
|
(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)}))
|
||||||
|
(get-contacts))]
|
||||||
|
(assoc db :contacts contacts)))
|
||||||
|
|
||||||
|
(defn- create-contact [{:keys [phone-number whisper-identity name photo-path]}]
|
||||||
|
(realm/create "Contact"
|
||||||
|
{:phone-number phone-number
|
||||||
|
:whisper-identity whisper-identity
|
||||||
|
:name (or name "")
|
||||||
|
:photo-path (or photo-path "")}))
|
||||||
|
|
||||||
|
(defn- contact-exist? [contacts contact]
|
||||||
|
(some #(= (:phone-number contact) (:phone-number %)) contacts))
|
||||||
|
|
||||||
|
(defn- add-contacts [contacts]
|
||||||
|
(realm/write (fn []
|
||||||
|
(let [db-contacts (get-contacts)]
|
||||||
|
(dorun (map (fn [contact]
|
||||||
|
(if (not (contact-exist? db-contacts contact))
|
||||||
|
(create-contact contact)
|
||||||
|
;; TODO else override?
|
||||||
|
))
|
||||||
|
contacts))))))
|
||||||
|
|
||||||
|
(defn save-syng-contacts [syng-contacts]
|
||||||
|
(add-contacts syng-contacts))
|
|
@ -6,4 +6,10 @@
|
||||||
:get-greeting
|
:get-greeting
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(reaction
|
(reaction
|
||||||
(get @db :greeting))))
|
(get @db :greeting))))
|
||||||
|
|
||||||
|
(register-sub
|
||||||
|
:get-contacts
|
||||||
|
(fn [db _]
|
||||||
|
(reaction
|
||||||
|
(get @db :contacts))))
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns syng-im.utils.utils
|
||||||
|
(:require-macros
|
||||||
|
[natal-shell.async-storage :refer [get-item set-item]]
|
||||||
|
[natal-shell.alert :refer [alert]]
|
||||||
|
[natal-shell.toast-android :as toast]))
|
||||||
|
|
||||||
|
;; (def server-address "http://rpc0.syng.im:20000/")
|
||||||
|
(def server-address "http://10.0.3.2:3000/")
|
||||||
|
|
||||||
|
(defn log [obj]
|
||||||
|
(.log js/console obj))
|
||||||
|
|
||||||
|
(defn toast [s]
|
||||||
|
(toast/show s (toast/long)))
|
||||||
|
|
||||||
|
(defn on-error [error]
|
||||||
|
(toast (str "error: " error)))
|
||||||
|
|
||||||
|
(defn http-post
|
||||||
|
([action data on-success]
|
||||||
|
(http-post action data on-success nil))
|
||||||
|
([action data on-success on-error]
|
||||||
|
(-> (.fetch js/window
|
||||||
|
(str server-address action)
|
||||||
|
(clj->js {:method "POST"
|
||||||
|
:headers {:accept "application/json"
|
||||||
|
:content-type "application/json"}
|
||||||
|
:body (.stringify js/JSON (clj->js data))}))
|
||||||
|
(.then (fn [response]
|
||||||
|
(log response)
|
||||||
|
(.text response)))
|
||||||
|
(.then (fn [text]
|
||||||
|
(let [json (.parse js/JSON text)
|
||||||
|
obj (js->clj json :keywordize-keys true)]
|
||||||
|
(on-success obj))))
|
||||||
|
(.catch (or on-error
|
||||||
|
(fn [error]
|
||||||
|
(toast (str error))))))))
|