diff --git a/.re-natal b/.re-natal
index 526a5b4820..1455b14c43 100644
--- a/.re-natal
+++ b/.re-natal
@@ -15,7 +15,8 @@
"react-native-circle-checkbox",
"react-native-randombytes",
"dismissKeyboard",
- "react-native-linear-gradient"
+ "react-native-linear-gradient",
+ "react-native-android-sms-listener"
],
"imageDirs": [
"images"
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 377ee75866..379551061c 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -129,6 +129,7 @@ dependencies {
compile project(':react-native-contacts')
compile project(':react-native-i18n')
compile project(':react-native-linear-gradient')
+ compile project(':ReactNativeAndroidSmsListener')
// compile(name:'geth', ext:'aar')
compile(group: 'status-im', name: 'android-geth', version: '1.4.0-201604110816-a97a114', ext: 'aar')
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index a7eb44af57..d8e1a14016 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -4,6 +4,7 @@
+
(fn [db [_ phone-number]]
- ;; todo save phone number to db
- (assoc db :user-phone-number phone-number))
- ((after (fn [& _] (sign-up-service/on-sign-up-response))))))
+ (fn [db [_ phone-number]]
+ ;; todo save phone number to db
+ (let [formatted (format-phone-number phone-number)]
+ (-> db
+ (assoc :user-phone-number formatted)
+ sign-up-service/start-listening-confirmation-code-sms
+ (server/sign-up formatted sign-up-service/on-sign-up-response)))))
+
+(register-handler :stop-listening-confirmation-code-sms
+ (fn [db [_]]
+ (sign-up-service/stop-listening-confirmation-code-sms db)))
(register-handler :sign-up-confirm
(fn [db [_ confirmation-code]]
- (sign-up-service/on-send-code-response confirmation-code)
- (sign-up-service/set-signed-up db true)))
+ (server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response)
+ db))
(register-handler :set-signed-up
(fn [db [_ signed-up]]
@@ -299,6 +311,7 @@
(let [name (get-in contacts [contcat-id :name])
chat {:chat-id contcat-id
:name name
+ :color default-chat-color
:group-chat false
:is-active true
:timestamp (.getTime (js/Date.))
diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs
index f292983cc7..19723aba22 100644
--- a/src/status_im/chat/screen.cljs
+++ b/src/status_im/chat/screen.cljs
@@ -1,7 +1,7 @@
(ns status-im.chat.screen
(:require-macros [status-im.utils.views :refer [defview]])
- (:require [clojure.string :as s]
- [re-frame.core :refer [subscribe dispatch]]
+ (:require [re-frame.core :refer [subscribe dispatch]]
+ [clojure.string :as s]
[status-im.components.react :refer [view
text
image
@@ -9,9 +9,11 @@
touchable-highlight
list-view
list-item]]
+ [status-im.components.chat-icon.screen :refer [chat-icon-view-action
+ chat-icon-view-menu-item]]
[status-im.chat.styles.screen :as st]
- [status-im.resources :as res]
[status-im.utils.listview :refer [to-datasource]]
+ [status-im.utils.utils :refer [truncate-str]]
[status-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.chat.views.message :refer [chat-message]]
@@ -32,19 +34,13 @@
(assoc msg :text-color text-color
:background-color background-color))))
-(defn chat-photo [{:keys [photo-path]}]
- [view {:margin 10
- :borderRadius 50}
- [image {:source (if (s/blank? photo-path)
- res/user-no-photo
- {:uri photo-path})
- :style st/chat-photo}]])
-
-(defn contact-online [{:keys [online]}]
- (when online
- [view st/online-view
- [view st/online-dot-left]
- [view st/online-dot-right]]))
+(defview chat-icon []
+ [chat-id [:chat :chat-id]
+ group-chat [:chat :group-chat]
+ name [:chat :name]
+ color [:chat :color]]
+ ;; TODO stub data ('online' property)
+ [chat-icon-view-action chat-id group-chat name color true])
(defn typing [member]
[view st/typing-view
@@ -54,6 +50,7 @@
(defn typing-all []
[view st/typing-all
+ ;; TODO stub data
(for [member ["Geoff" "Justas"]]
^{:key member} [typing member])])
@@ -94,43 +91,44 @@
[text {:style st/action-subtitle}
subtitle])]]])
-(defn menu-item-contact-photo [{:keys [photo-path]}]
- [image {:source (if (s/blank? photo-path)
- res/user-no-photo
- {:uri photo-path})
- :style st/menu-item-profile-contact-photo}])
+(defview menu-item-icon-profile []
+ [chat-id [:chat :chat-id]
+ group-chat [:chat :group-chat]
+ name [:chat :name]
+ color [:chat :color]]
+ ;; TODO stub data ('online' property)
+ [chat-icon-view-menu-item chat-id group-chat name color true])
-(defn menu-item-contact-online [{:keys [online]}]
- (when online
- [view st/menu-item-profile-online-view
- [view st/menu-item-profile-online-dot-left]
- [view st/menu-item-profile-online-dot-right]]))
-
-(defn menu-item-icon-profile []
- [view st/icon-view
- [menu-item-contact-photo {}]
- [menu-item-contact-online {:online true}]])
+(defn members-text [members]
+ (truncate-str (str (s/join ", " (map #(:name %) members)) " and you") 35))
(defn actions-list-view []
(let [{:keys [group-chat chat-id]}
- (subscribe [:chat-properties [:group-chat :chat-id]])]
+ (subscribe [:chat-properties [:group-chat :chat-id]])
+ members (subscribe [:current-chat-contacts])]
(when-let [actions (if @group-chat
- [{:title "Add Contact to chat"
+ [{:title "Members"
+ :subtitle (members-text @members)
:icon :menu_group
:icon-style {:width 25
:height 19}
- :handler #(dispatch [:navigate-to :add-participants])}
- {:title "Remove Contact from chat"
- :subtitle "Alex, John"
+ ;; TODO not implemented: action Members
+ :handler nil}
+ {:title "Search chat"
+ :subtitle "!not implemented"
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
- :handler #(dispatch [:navigate-to :remove-participants])}
- {:title "Leave Chat"
+ ;; TODO not implemented: action Search chat
+ :handler nil}
+ {:title "Notifications and sounds"
+ :subtitle "!not implemented"
+ ;;:subtitle "Chat muted"
:icon :muted
:icon-style {:width 18
:height 21}
- :handler #(dispatch [:leave-group-chat])}
+ ;; TODO not implemented: action Notifications
+ :handler nil}
{:title "Settings"
:icon :settings
:icon-style {:width 20
@@ -147,19 +145,23 @@
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
+ ;; TODO not implemented: action Search chat
:handler nil}
{:title "Notifications and sounds"
:subtitle "!not implemented"
+ ;;:subtitle "Notifications on"
:icon :muted
:icon-style {:width 18
:height 21}
+ ;; TODO not implemented: action Notifications
:handler nil}
{:title "Settings"
:subtitle "!not implemented"
:icon :settings
:icon-style {:width 20
:height 13}
- :handler (fn [])}])]
+ ;; TODO not implemented: action Settings
+ :handler nil}])]
[view st/actions-wrapper
[view st/actions-separator]
[view st/actions-view
@@ -177,17 +179,19 @@
(fn []
[view (st/chat-name-view @show-actions)
[text {:style st/chat-name-text}
- (or @name "Chat name")]
+ (truncate-str (or @name "Chat name") 30)]
(if @group-chat
[view {:flexDirection :row}
[icon :group st/group-icon]
[text {:style st/members}
- (let [cnt (count @contacts)]
+ (let [cnt (inc (count @contacts))]
(str cnt
(if (< 1 cnt)
" members"
" member")
+ ;; TODO stub data: active members
", " cnt " active"))]]
+ ;; TODO stub data: last activity
[text {:style st/last-activity} "Active a minute ago"])])))
(defn toolbar-action []
@@ -196,13 +200,12 @@
(if @show-actions
[touchable-highlight
{:on-press #(dispatch [:set-show-actions false])}
- [view st/icon-view
+ [view st/action
[icon :up st/up-icon]]]
[touchable-highlight
{:on-press #(dispatch [:set-show-actions true])}
- [view st/icon-view
- [chat-photo {}]
- [contact-online {:online true}]]]))))
+ [view st/action
+ [chat-icon]]]))))
(defn chat-toolbar []
(let [{:keys [group-chat name contacts]}
diff --git a/src/status_im/chat/sign_up.cljs b/src/status_im/chat/sign_up.cljs
index 3b50530b28..ef855d0021 100644
--- a/src/status_im/chat/sign_up.cljs
+++ b/src/status_im/chat/sign_up.cljs
@@ -4,13 +4,16 @@
[status-im.persistence.simple-kv-store :as kv]
[status-im.protocol.state.storage :as s]
[status-im.models.chats :as c]
+ [status-im.components.styles :refer [default-chat-color]]
[status-im.utils.utils :refer [log on-error http-post toast]]
[status-im.utils.random :as random]
+ [status-im.utils.sms-listener :refer [add-sms-listener
+ remove-sms-listener]]
[status-im.utils.phone-number :refer [format-phone-number]]
[status-im.constants :refer [text-content-type
- content-type-command
- content-type-command-request
- content-type-status]]))
+ content-type-command
+ content-type-command-request
+ content-type-status]]))
(defn send-console-msg [text]
{:msg-id (random/id)
@@ -37,19 +40,22 @@
(dispatch [:set-signed-up true]))
(defn sync-contacts []
+ ;; TODO 'on-sync-contacts' is never called
(dispatch [:sync-contacts on-sync-contacts]))
(defn on-send-code-response [body]
(dispatch [:received-msg
{:msg-id (random/id)
- ;; todo replace by real check
- :content (if (= "1111" body)
- "Confirmed"
- "Wrong code")
+ :content (:message body)
:content-type text-content-type
:outgoing false
:from "console"
- :to "me"}]))
+ :to "me"}])
+ (when (:confirmed body)
+ (dispatch [:stop-listening-confirmation-code-sms])
+ (sync-contacts)
+ ;; TODO should be called after sync-contacts?
+ (dispatch [:set-signed-up true])))
; todo fn name is not too smart, but...
(defn command-content
@@ -71,9 +77,22 @@
:from "console"
:to "me"}])))
+(defn handle-sms [{body :body}]
+ (when-let [matches (re-matches #"(\d{4})" body)]
+ (dispatch [:sign-up-confirm (second matches)])))
+
+(defn start-listening-confirmation-code-sms [db]
+ (when (not (:confirmation-code-sms-listener db))
+ (assoc db :confirmation-code-sms-listener (add-sms-listener handle-sms))))
+
+(defn stop-listening-confirmation-code-sms [db]
+ (when-let [listener (:confirmation-code-sms-listener db)]
+ (remove-sms-listener listener)
+ (dissoc db :confirmation-code-sms-listener)))
+
;; -- Saving password ----------------------------------------
(defn save-password [password]
- ;; TODO validate and save password
+ ;; TODO validate and save password
(dispatch [:received-msg
{:msg-id (random/id)
:content (str "OK great! Your password has been saved. Just to let you "
@@ -174,6 +193,7 @@
(def console-chat
{:chat-id "console"
:name "console"
+ :color default-chat-color
:group-chat false
:is-active true
:timestamp (.getTime (js/Date.))
diff --git a/src/status_im/chat/styles/screen.cljs b/src/status_im/chat/styles/screen.cljs
index 5faa905fd6..35e4d0b3d7 100644
--- a/src/status_im/chat/styles/screen.cljs
+++ b/src/status_im/chat/styles/screen.cljs
@@ -20,6 +20,12 @@
:backgroundColor toolbar-background1
:elevation 2})
+(def action
+ {:width 56
+ :height 56
+ :alignItems :center
+ :justifyContent :center})
+
(def icon-view
{:width 56
:height 56})
@@ -48,10 +54,8 @@
:height 9})
(def up-icon
- {:marginTop 23
- :marginLeft 21
- :width 14
- :height 8})
+ {:width 14
+ :height 8})
(def members
{:marginTop -0.5
@@ -108,28 +112,6 @@
:fontSize 12
:fontFamily font})
-(def online-view
- {:position :absolute
- :top 30
- :left 30
- :width 20
- :height 20
- :borderRadius 50
- :backgroundColor online-color
- :borderWidth 2
- :borderColor color-white})
-
-(def online-dot
- {:position :absolute
- :top 6
- :width 4
- :height 4
- :borderRadius 50
- :backgroundColor color-white})
-
-(def online-dot-left (merge online-dot {:left 3}))
-(def online-dot-right (merge online-dot {:left 9}))
-
(def typing-all
{:marginBottom 20})
@@ -153,11 +135,6 @@
:fontFamily font
:color text2-color})
-(def chat-photo
- {:borderRadius 50
- :width 36
- :height 36})
-
(def actions-overlay
{:position :absolute
:top 0
@@ -167,34 +144,3 @@
(def overlay-highlight
{:flex 1})
-
-;;----- Menu item Profile ----------------
-
-(def menu-item-profile-contact-photo
- {:marginTop 13
- :marginLeft 16
- :borderRadius 50
- :width 24
- :height 24})
-
-(def menu-item-profile-online-view
- {:position :absolute
- :top 26
- :left 29
- :width 15
- :height 15
- :borderRadius 50
- :backgroundColor online-color
- :borderWidth 2
- :borderColor color-white})
-
-(def menu-item-profile-online-dot
- {:position :absolute
- :top 4
- :width 3
- :height 3
- :borderRadius 50
- :backgroundColor color-white})
-
-(def menu-item-profile-online-dot-left (merge menu-item-profile-online-dot {:left 1.7}))
-(def menu-item-profile-online-dot-right (merge menu-item-profile-online-dot {:left 6.3}))
diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs
index 9b6bea54c5..eaece17dfb 100644
--- a/src/status_im/chat/views/plain_input.cljs
+++ b/src/status_im/chat/views/plain_input.cljs
@@ -45,6 +45,7 @@
:onSubmitEditing #(try-send @chat @staged-commands-atom
input-message)}
input-message]
+ ;; TODO emoticons: not implemented
[icon :smile st/smile-icon]
(when (message-valid? @staged-commands-atom input-message)
[touchable-highlight {:on-press #(send @chat input-message)}
diff --git a/src/status_im/chats_list/screen.cljs b/src/status_im/chats_list/screen.cljs
index 32a7ce6ab2..48babbcee1 100644
--- a/src/status_im/chats_list/screen.cljs
+++ b/src/status_im/chats_list/screen.cljs
@@ -12,7 +12,8 @@
[status-im.components.action-button :refer [action-button
action-button-item]]
[status-im.components.drawer.view :refer [drawer-view open-drawer]]
- [status-im.components.styles :refer [color-blue]]
+ [status-im.components.styles :refer [color-blue
+ toolbar-background2]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.components.main-tabs :refer [main-tabs]]
[status-im.components.icons.ionicons :refer [icon]]
@@ -23,6 +24,8 @@
:style st/hamburger-icon}
:handler open-drawer}
:title "Chats"
+ :background-color toolbar-background2
+ ;; TODO implement search
:action {:image {:source {:uri :icon_search}
:style st/search-icon}
:handler (fn [])}}])
diff --git a/src/status_im/chats_list/styles.cljs b/src/status_im/chats_list/styles.cljs
index 592a882d3e..0fae1d82fd 100644
--- a/src/status_im/chats_list/styles.cljs
+++ b/src/status_im/chats_list/styles.cljs
@@ -9,49 +9,17 @@
new-messages-count-color]]
[status-im.components.tabs.styles :refer [tab-height]]))
-(def contact-photo-container
- {:borderRadius 50})
-
-(def contact-photo-image
- {:borderRadius 50
- :width 40
- :height 40})
-
-(def online-container
- {:position :absolute
- :top 24
- :left 24
- :width 20
- :height 20
- :borderRadius 50
- :backgroundColor online-color
- :borderWidth 2
- :borderColor color-white})
-
-(def online-dot
- {:position :absolute
- :top 6
- :width 4
- :height 4
- :borderRadius 50
- :backgroundColor color-white})
-
-(def online-dot-left
- (assoc online-dot :left 3))
-
-(def online-dot-right
- (assoc online-dot :left 9))
-
(def chat-container
{:flexDirection :row
:paddingVertical 15
:paddingHorizontal 16
:height 90})
-(def photo-container
- {:marginTop 2
- :width 44
- :height 44})
+(def chat-icon-container
+ {:marginTop -2
+ :marginLeft -4
+ :width 48
+ :height 48})
(def item-container
{:flexDirection :column
diff --git a/src/status_im/chats_list/views/chat_list_item.cljs b/src/status_im/chats_list/views/chat_list_item.cljs
index 412979d42b..0c343f9b59 100644
--- a/src/status_im/chats_list/views/chat_list_item.cljs
+++ b/src/status_im/chats_list/views/chat_list_item.cljs
@@ -11,10 +11,7 @@
(defn chat-list-item [{:keys [chat-id] :as chat}]
[touchable-highlight
{:on-press #(dispatch [:navigate-to :chat chat-id])}
- ;; TODO add [photo-path delivery-status new-messages-count online] values to chat-obj
[view [chat-list-item-inner-view (merge chat
- {:photo-path nil
- :delivery-status :seen
- :new-messages-count 3
- :timestamp "13:54"
+ ;; TODO stub data
+ {:new-messages-count 3
:online true})]]])
diff --git a/src/status_im/chats_list/views/inner_item.cljs b/src/status_im/chats_list/views/inner_item.cljs
index fc0851183a..e3fc322bb7 100644
--- a/src/status_im/chats_list/views/inner_item.cljs
+++ b/src/status_im/chats_list/views/inner_item.cljs
@@ -1,52 +1,45 @@
(ns status-im.chats-list.views.inner-item
- (:require [clojure.string :as s]
- [status-im.components.react :refer [view image icon text]]
+ (:require-macros [status-im.utils.views :refer [defview]])
+ (:require [status-im.components.react :refer [view image icon text]]
+ [status-im.components.chat-icon.screen :refer [chat-icon-view-chat-list]]
[status-im.chats-list.styles :as st]
- [status-im.resources :as res]))
-
-
-(defn contact-photo [photo-path]
- [view st/contact-photo-container
- [image {:source (if (s/blank? photo-path)
- res/user-no-photo
- {:uri photo-path})
- :style st/contact-photo-image}]])
-
-(defn contact-online [online]
- (when online
- [view st/online-container
- [view st/online-dot-left]
- [view st/online-dot-right]]))
+ [status-im.utils.utils :refer [truncate-str]]
+ [status-im.utils.datetime :as time]))
(defn chat-list-item-inner-view
- [{:keys [name photo-path delivery-status timestamp new-messages-count online
- group-chat contacts]}]
- [view st/chat-container
- [view st/photo-container
- [contact-photo photo-path]
- [contact-online online]]
- [view st/item-container
- [view st/name-view
- [text {:style st/name-text} name]
- (when group-chat
- [icon :group st/group-icon])
- (when group-chat
- [text {:style st/memebers-text}
- (if (< 1 (count contacts))
- (str (count contacts) " members")
- "1 member")])]
- [text {:style st/last-message-text
- :numberOfLines 2}
- (repeatedly 5 #(str "Hi, I'm " name "! "))]]
- [view
- [view st/status-container
- (when delivery-status
- [image {:source (if (= (keyword delivery-status) :seen)
- {:uri :icon_ok_small}
- ;; todo change icon
- {:uri :icon_ok_small})
- :style st/status-image}])
- [text {:style st/datetime-text} timestamp]]
- (when (pos? new-messages-count)
- [view st/new-messages-container
- [text {:style st/new-messages-text} new-messages-count]])]])
+ [{:keys [chat-id name color photo-path new-messages-count
+ online group-chat contacts] :as chat}]
+ (let [last-message (first (:messages chat))]
+ [view st/chat-container
+ [view st/chat-icon-container
+ [chat-icon-view-chat-list chat-id group-chat name color online]]
+ [view st/item-container
+ [view st/name-view
+ [text {:style st/name-text} (truncate-str name 20)]
+ (when group-chat
+ [icon :group st/group-icon])
+ (when group-chat
+ [text {:style st/memebers-text}
+ (if (< 0 (count contacts))
+ (str (inc (count contacts)) " members")
+ "1 member")])]
+ [text {:style st/last-message-text
+ :numberOfLines 2}
+ (when last-message
+ (:content last-message))]]
+ [view
+ (when last-message
+ [view st/status-container
+ ;; TODO currently there is not :delivery-status in last-message
+ (when (:delivery-status last-message)
+ [image {:source (if (= (keyword (:delivery-status last-message)) :seen)
+ {:uri :icon_ok_small}
+ ;; todo change icon
+ {:uri :icon_ok_small})
+ :style st/status-image}])
+ (when (:timestamp last-message)
+ [text {:style st/datetime-text}
+ (time/to-short-str (:timestamp last-message))])])
+ (when (pos? new-messages-count)
+ [view st/new-messages-container
+ [text {:style st/new-messages-text} new-messages-count]])]]))
diff --git a/src/status_im/components/chat_icon/screen.cljs b/src/status_im/components/chat_icon/screen.cljs
new file mode 100644
index 0000000000..e44d334e33
--- /dev/null
+++ b/src/status_im/components/chat_icon/screen.cljs
@@ -0,0 +1,92 @@
+(ns status-im.components.chat-icon.screen
+ (:require-macros [status-im.utils.views :refer [defview]])
+ (:require [re-frame.core :refer [subscribe dispatch]]
+ [status-im.components.react :refer [view
+ text
+ image
+ icon]]
+ [status-im.components.chat-icon.styles :as st]
+ [status-im.components.styles :refer [color-purple]]))
+
+(defn default-chat-icon [name styles]
+ [view (:default-chat-icon styles)
+ [text {:style (:default-chat-icon-text styles)}
+ (first name)]])
+
+(defn chat-icon [photo-path styles]
+ [image {:source {:uri photo-path}
+ :style (:chat-icon styles)}])
+
+(defn contact-online [online styles]
+ (when online
+ [view (:online-view styles)
+ [view (:online-dot-left styles)]
+ [view (:online-dot-right styles)]]))
+
+(defview chat-icon-view [chat-id group-chat name online styles]
+ [photo-path [:chat-photo chat-id]]
+ [view (:container styles)
+ (if (and photo-path (not (empty? photo-path)))
+ [chat-icon photo-path styles]
+ [default-chat-icon name styles])
+ (when (not group-chat)
+ [contact-online online styles])])
+
+(defn chat-icon-view-chat-list [chat-id group-chat name color online]
+ [chat-icon-view chat-id group-chat name online
+ {:container st/container-chat-list
+ :online-view st/online-view
+ :online-dot-left st/online-dot-left
+ :online-dot-right st/online-dot-right
+ :chat-icon st/chat-icon-chat-list
+ :default-chat-icon (st/default-chat-icon-chat-list color)
+ :default-chat-icon-text st/default-chat-icon-text}])
+
+(defn chat-icon-view-action [chat-id group-chat name color online]
+ [chat-icon-view chat-id group-chat name online
+ {:container st/container
+ :online-view st/online-view
+ :online-dot-left st/online-dot-left
+ :online-dot-right st/online-dot-right
+ :chat-icon st/chat-icon
+ :default-chat-icon (st/default-chat-icon color)
+ :default-chat-icon-text st/default-chat-icon-text}])
+
+(defn chat-icon-view-menu-item [chat-id group-chat name color online]
+ [chat-icon-view chat-id group-chat name online
+ {:container st/container-menu-item
+ :online-view st/online-view-menu-item
+ :online-dot-left st/online-dot-left-menu-item
+ :online-dot-right st/online-dot-right-menu-item
+ :chat-icon st/chat-icon-menu-item
+ :default-chat-icon (st/default-chat-icon-menu-item color)
+ :default-chat-icon-text st/default-chat-icon-text}])
+
+(defn profile-icon-view [photo-path name color online]
+ (let [styles {:container st/container-profile
+ :online-view st/online-view-profile
+ :online-dot-left st/online-dot-left-profile
+ :online-dot-right st/online-dot-right-profile
+ :chat-icon st/chat-icon-profile
+ :default-chat-icon (st/default-chat-icon-profile color)
+ :default-chat-icon-text st/default-chat-icon-text}]
+ [view (:container styles)
+ (if (and photo-path (not (empty? photo-path)))
+ [chat-icon photo-path styles]
+ [default-chat-icon name styles])
+ [contact-online online styles]]))
+
+(defview profile-icon []
+ [contact [:contact]]
+ (let [;; TODO stub data
+ online true
+ color color-purple]
+ [profile-icon-view (:photo-path contact) (:name contact) color online]))
+
+(defview my-profile-icon []
+ [name [:get :username]
+ photo-path [:get :photo-path]]
+ (let [;; TODO stub data
+ online true
+ color color-purple]
+ [profile-icon-view photo-path name color online]))
diff --git a/src/status_im/components/chat_icon/styles.cljs b/src/status_im/components/chat_icon/styles.cljs
new file mode 100644
index 0000000000..41fbcf75ee
--- /dev/null
+++ b/src/status_im/components/chat_icon/styles.cljs
@@ -0,0 +1,130 @@
+(ns status-im.components.chat-icon.styles
+ (:require [status-im.components.styles :refer [font
+ title-font
+ color-white
+ chat-background
+ online-color
+ selected-message-color
+ separator-color
+ text1-color
+ text2-color
+ toolbar-background1]]))
+
+(defn default-chat-icon [color]
+ {:margin 4
+ :width 36
+ :height 36
+ :alignItems :center
+ :justifyContent :center
+ :borderRadius 50
+ :backgroundColor color})
+
+(defn default-chat-icon-chat-list [color]
+ (merge (default-chat-icon color)
+ {:width 40
+ :height 40}))
+
+(defn default-chat-icon-menu-item [color]
+ (merge (default-chat-icon color)
+ {:width 24
+ :height 24}))
+
+(defn default-chat-icon-profile [color]
+ (merge (default-chat-icon color)
+ {:width 64
+ :height 64}))
+
+(def default-chat-icon-text
+ {:marginTop -2
+ :color color-white
+ :fontFamily font
+ :fontSize 16
+ :lineHeight 20})
+
+(def chat-icon
+ {:margin 4
+ :borderRadius 50
+ :width 36
+ :height 36})
+
+(def chat-icon-chat-list
+ (merge chat-icon
+ {:width 40
+ :height 40}))
+
+(def chat-icon-menu-item
+ (merge chat-icon
+ {:width 24
+ :height 24}))
+
+(def chat-icon-profile
+ (merge chat-icon
+ {:width 64
+ :height 64}))
+
+(def online-view
+ {:position :absolute
+ :bottom 0
+ :right 0
+ :width 20
+ :height 20
+ :borderRadius 50
+ :backgroundColor online-color
+ :borderWidth 2
+ :borderColor color-white})
+
+(def online-view-menu-item
+ (merge online-view
+ {:width 15
+ :height 15}))
+
+(def online-view-profile
+ (merge online-view
+ {:width 24
+ :height 24}))
+
+(def online-dot
+ {:position :absolute
+ :top 6
+ :width 4
+ :height 4
+ :borderRadius 50
+ :backgroundColor color-white})
+(def online-dot-left (merge online-dot {:left 3}))
+(def online-dot-right (merge online-dot {:left 9}))
+
+(def online-dot-menu-item
+ (merge online-dot
+ {:top 4
+ :width 3
+ :height 3}))
+(def online-dot-left-menu-item
+ (merge online-dot-menu-item {:left 1.7}))
+(def online-dot-right-menu-item
+ (merge online-dot-menu-item {:left 6.3}))
+
+(def online-dot-profile
+ (merge online-dot
+ {:top 8
+ :width 4
+ :height 4}))
+(def online-dot-left-profile
+ (merge online-dot-profile {:left 5}))
+(def online-dot-right-profile
+ (merge online-dot-profile {:left 11}))
+
+(def container
+ {:width 44
+ :height 44})
+
+(def container-chat-list
+ {:width 48
+ :height 48})
+
+(def container-menu-item
+ {:width 32
+ :height 32})
+
+(def container-profile
+ {:width 72
+ :height 72})
diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs
index 421224dc92..6ccb836e02 100644
--- a/src/status_im/components/styles.cljs
+++ b/src/status_im/components/styles.cljs
@@ -26,3 +26,4 @@
(def separator-color "#0000001f")
(def toolbar-background1 color-white)
(def toolbar-background2 color-light-gray)
+(def default-chat-color color-purple)
diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs
index abfd54bf77..a684182899 100644
--- a/src/status_im/constants.cljs
+++ b/src/status_im/constants.cljs
@@ -4,18 +4,9 @@
(def server-address "http://rpc0.status.im:20000/")
;; (def server-address "http://10.0.3.2:3000/")
+;; (def server-address "http://localhost:3000/")
(def text-content-type "text/plain")
(def content-type-command "command")
(def content-type-command-request "command-request")
(def content-type-status "status")
-
-
-(comment
-
- (map (fn [c]
- {:background c
- :foreground c}) group-chat-colors)
- (reverse group-chat-colors)
-
- )
diff --git a/src/status_im/contacts/handlers.cljs b/src/status_im/contacts/handlers.cljs
index 7a384d04fd..268b701815 100644
--- a/src/status_im/contacts/handlers.cljs
+++ b/src/status_im/contacts/handlers.cljs
@@ -73,7 +73,7 @@
(defn request-stored-contacts [contacts]
(let [contacts-by-hash (get-contacts-by-hash contacts)
- data (keys contacts-by-hash)]
+ data (or (keys contacts-by-hash) ())]
(http-post "get-contacts" {:phone-number-hashes data}
(fn [{:keys [contacts]}]
(let [contacts' (add-identity contacts-by-hash contacts)]
diff --git a/src/status_im/contacts/subs.cljs b/src/status_im/contacts/subs.cljs
index a85f20866a..76803f74dd 100644
--- a/src/status_im/contacts/subs.cljs
+++ b/src/status_im/contacts/subs.cljs
@@ -12,18 +12,21 @@
(let [contacts (reaction (:contacts @db))]
(reaction (sort-by :name (vals @contacts))))))
-(defn contacts-by-current-chat [fn db]
- (let [current-chat-id (:current-chat-id @db)
- chat (reaction (get-in @db [:chats current-chat-id]))
- contacts (reaction (:contacts @db))]
+(defn contacts-by-chat [fn db chat-id]
+ (let [chat (reaction (get-in @db [:chats chat-id]))
+ contacts (reaction (:contacts @db))]
(reaction
- (when @chat
- (let [current-participants (->> @chat
- :contacts
- (map :identity)
- set)]
- (fn #(current-participants (:whisper-identity %))
- (vals @contacts)))))))
+ (when @chat
+ (let [current-participants (->> @chat
+ :contacts
+ (map :identity)
+ set)]
+ (fn #(current-participants (:whisper-identity %))
+ (vals @contacts)))))))
+
+(defn contacts-by-current-chat [fn db]
+ (let [current-chat-id (:current-chat-id @db)]
+ (contacts-by-chat fn db current-chat-id)))
(register-sub :contact
(fn [db _]
@@ -37,3 +40,15 @@
(register-sub :current-chat-contacts
(fn [db _]
(contacts-by-current-chat filter db)))
+
+(register-sub :chat-photo
+ (fn [db [_ chat-id]]
+ (let [chat-id (or chat-id (:current-chat-id @db))
+ chat (reaction (get-in @db [:chats chat-id]))
+ contacts (contacts-by-chat filter db chat-id)]
+ (reaction
+ (when @chat
+ (if (:group-chat @chat)
+ ;; TODO return group chat icon
+ nil
+ (:photo-path (first @contacts))))))))
diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs
index a6b34c65ef..a46c61f087 100644
--- a/src/status_im/db.cljs
+++ b/src/status_im/db.cljs
@@ -23,6 +23,7 @@
:view-id default-view
:navigation-stack (list default-view)
;; TODO fix hardcoded values
+ :photo-path nil
:username "My Name"
:phone-number "3147984309"
:email "myemail@gmail.com"
diff --git a/src/status_im/group_settings/screen.cljs b/src/status_im/group_settings/screen.cljs
index 86c38a77de..1c49c4f094 100644
--- a/src/status_im/group_settings/screen.cljs
+++ b/src/status_im/group_settings/screen.cljs
@@ -2,16 +2,17 @@
(:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view
- text-input
- text
- image
- icon
- modal
- picker
- picker-item
- scroll-view
- touchable-highlight]]
+ text-input
+ text
+ image
+ icon
+ modal
+ picker
+ picker-item
+ scroll-view
+ touchable-highlight]]
[status-im.components.toolbar :refer [toolbar]]
+ [status-im.components.chat-icon.screen :refer [chat-icon-view-action]]
[status-im.group-settings.styles.group-settings :as st]
[status-im.group-settings.views.member :refer [member-view]]))
@@ -21,6 +22,7 @@
(defn close-member-menu []
(dispatch [:set :selected-participants #{}]))
+;; TODO not in design
(defview member-menu []
[{:keys [name] :as participant} [:selected-participant]]
(when participant
@@ -61,6 +63,7 @@
(close-chat-color-picker)
(dispatch [:set-chat-color]))
+;; TODO not in design
(defview chat-color-picker []
[show-color-picker [:group-settings :show-color-picker]
new-color [:get :new-chat-color]]
@@ -88,10 +91,10 @@
(dispatch [:group-settings :show-color-picker true]))
(defn settings-view []
- ;; TODO implement settings handlers
(let [settings [{:custom-icon [chat-color-icon]
:title "Change color"
:handler show-chat-color-picker}
+ ;; TODO not implemented: Notifications
(merge {:title "Notifications and sounds"
:subtitle "!not implemented"
:handler nil}
@@ -106,21 +109,25 @@
:icon-style {:width 12
:height 12}
:title "Clear history"
+ ;; TODO show confirmation dialog?
:handler #(dispatch [:clear-history])}
{:icon :bin
:icon-style {:width 12
:height 18}
:title "Delete and leave"
+ ;; TODO show confirmation dialog?
:handler #(dispatch [:leave-group-chat])}]]
[view st/settings-container
(for [setting settings]
^{:key setting} [setting-view setting])]))
(defview chat-icon []
- [name [:chat :name]
- color [:chat :color]]
- [view (st/chat-icon color)
- [text {:style st/chat-icon-text} (first name)]])
+ [chat-id [:chat :chat-id]
+ group-chat [:chat :group-chat]
+ name [:chat :name]
+ color [:chat :color]]
+ [view st/action
+ [chat-icon-view-action chat-id group-chat name color false]])
(defn new-group-toolbar []
[toolbar {:title "Chat settings"
@@ -164,6 +171,7 @@
[chat-name]
[text {:style st/members-text} "Members"]
[touchable-highlight {:on-press #(dispatch [:navigate-to :add-participants])}
+ ;; TODO add participants view is not in design
[view st/add-members-container
[icon :add-gray st/add-members-icon]
[text {:style st/add-members-text}
diff --git a/src/status_im/group_settings/styles/group_settings.cljs b/src/status_im/group_settings/styles/group_settings.cljs
index 20b2a42d30..91d407c604 100644
--- a/src/status_im/group_settings/styles/group_settings.cljs
+++ b/src/status_im/group_settings/styles/group_settings.cljs
@@ -52,20 +52,11 @@
(def chat-members-container
{:marginBottom 10})
-(defn chat-icon [color]
- {:margin 10
- :width 36
- :height 36
- :borderRadius 50
- :backgroundColor color})
-
-(def chat-icon-text
- {:marginTop 7
- :marginLeft 13
- :color color-white
- :fontFamily font
- :fontSize 16
- :lineHeight 20})
+(def action
+ {:width 56
+ :height 56
+ :alignItems :center
+ :justifyContent :center})
(def group-settings
{:flex 1
diff --git a/src/status_im/new_group/handlers.cljs b/src/status_im/new_group/handlers.cljs
index 4a48a3ebd1..0c34111405 100644
--- a/src/status_im/new_group/handlers.cljs
+++ b/src/status_im/new_group/handlers.cljs
@@ -1,6 +1,7 @@
(ns status-im.new-group.handlers
(:require [status-im.protocol.api :as api]
[re-frame.core :refer [register-handler after dispatch debug enrich]]
+ [status-im.components.styles :refer [default-chat-color]]
[status-im.models.chats :as chats]
[clojure.string :as s]))
@@ -37,6 +38,7 @@
(group-name-from-contacts db))]
(assoc db :new-chat {:chat-id new-group-id
:name chat-name
+ :color default-chat-color
:group-chat true
:is-active true
:timestamp (.getTime (js/Date.))
diff --git a/src/status_im/persistence/realm.cljs b/src/status_im/persistence/realm.cljs
index 242f98bb9c..a7d564f143 100644
--- a/src/status_im/persistence/realm.cljs
+++ b/src/status_im/persistence/realm.cljs
@@ -1,5 +1,6 @@
(ns status-im.persistence.realm
(:require [cljs.reader :refer [read-string]]
+ [status-im.components.styles :refer [default-chat-color]]
[status-im.utils.logging :as log]
[status-im.utils.types :refer [to-string]])
(:refer-clojure :exclude [exists?]))
@@ -44,7 +45,7 @@
:properties {:chat-id "string"
:name "string"
:color {:type "string"
- :default "#a187d5"}
+ :default default-chat-color}
:group-chat {:type "bool"
:indexed true}
:is-active "bool"
diff --git a/src/status_im/profile/screen.cljs b/src/status_im/profile/screen.cljs
index 40d10c44a1..83470681dc 100644
--- a/src/status_im/profile/screen.cljs
+++ b/src/status_im/profile/screen.cljs
@@ -1,7 +1,6 @@
(ns status-im.profile.screen
(:require-macros [status-im.utils.views :refer [defview]])
- (:require [clojure.string :as s]
- [re-frame.core :refer [subscribe dispatch]]
+ (:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view
text
image
@@ -9,21 +8,10 @@
scroll-view
touchable-highlight
touchable-opacity]]
- [status-im.resources :as res]
+ [status-im.components.chat-icon.screen :refer [profile-icon
+ my-profile-icon]]
[status-im.profile.styles :as st]))
-(defn user-photo [{:keys [photo-path]}]
- [image {:source (if (s/blank? photo-path)
- res/user-no-photo
- {:uri photo-path})
- :style st/user-photo}])
-
-(defn user-online [{:keys [online]}]
- (when online
- [view st/user-online-container
- [view st/user-online-dot-left]
- [view st/user-online-dot-right]]))
-
(defn profile-property-view [{:keys [name value]}]
[view st/profile-property-view-container
[view st/profile-property-view-sub-container
@@ -43,9 +31,9 @@
[icon :back st/back-btn-icon]]]
[view st/status-block
[view st/user-photo-container
- [user-photo {}]
- [user-online {:online true}]]
+ [profile-icon]]
[text {:style st/user-name} name]
+ ;; TODO stub data
[text {:style st/status} "!not implemented"]
[view st/btns-container
[touchable-highlight {:onPress #(message-user whisper-identity)}
@@ -61,17 +49,21 @@
:value name}]
[profile-property-view {:name "Phone number"
:value phone-number}]
+ ;; TODO stub data
[profile-property-view {:name "Email"
:value "!not implemented"}]
[view st/report-user-container
- [touchable-opacity {}
+ [touchable-highlight {:on-press (fn []
+ ;; TODO not implemented
+ )}
[text {:style st/report-user-text} "REPORT USER"]]]]])
(defview my-profile []
- [username [:get :username]
+ [username [:get :username]
+ photo-path [:get :photo-path]
phone-number [:get :phone-number]
- email [:get :email]
- status [:get :status]]
+ email [:get :email]
+ status [:get :status]]
[scroll-view {:style st/profile}
[touchable-highlight {:style st/back-btn-touchable
:on-press #(dispatch [:navigate-back])}
@@ -85,8 +77,7 @@
[icon :dots st/actions-btn-icon]]]
[view st/status-block
[view st/user-photo-container
- [user-photo {}]
- [user-online {:online true}]]
+ [my-profile-icon]]
[text {:style st/user-name} username]
[text {:style st/status} status]]
[view st/profile-properties-container
diff --git a/src/status_im/profile/styles.cljs b/src/status_im/profile/styles.cljs
index fe2c71a76e..95d230920e 100644
--- a/src/status_im/profile/styles.cljs
+++ b/src/status_im/profile/styles.cljs
@@ -11,37 +11,6 @@
text1-color
text2-color]]))
-(def user-photo
- {:borderRadius 50
- :width 64
- :height 64})
-
-(def user-online-container
- {:position :absolute
- :top 44
- :left 44
- :width 24
- :height 24
- :borderRadius 50
- :backgroundColor online-color
- :borderWidth 2
- :borderColor color-white})
-
-(def user-online-dot
- {:position :absolute
- :top 8
- :left 5
- :width 4
- :height 4
- :borderRadius 50
- :backgroundColor color-white})
-
-(def user-online-dot-left
- (assoc user-online-dot :left 5))
-
-(def user-online-dot-right
- (assoc user-online-dot :left 11))
-
(def profile-property-view-container
{:height 85
:paddingHorizontal 16})
@@ -101,10 +70,10 @@
:width 249})
(def user-photo-container
- {:marginTop 26})
+ {:marginTop 22})
(def user-name
- {:marginTop 20
+ {:marginTop 16
:fontSize 18
:fontFamily font
:color text1-color})
diff --git a/src/status_im/utils/datetime.cljs b/src/status_im/utils/datetime.cljs
new file mode 100644
index 0000000000..03695b427a
--- /dev/null
+++ b/src/status_im/utils/datetime.cljs
@@ -0,0 +1,24 @@
+(ns status-im.utils.datetime
+ (:require [cljs-time.core :as t :refer [date-time now plus days hours before?]]
+ [cljs-time.coerce :refer [from-long to-long]]
+ [cljs-time.format :as format :refer [formatters
+ formatter
+ unparse]]))
+
+(def time-zone-offset (hours (- (/ (.getTimezoneOffset (js/Date.)) 60))))
+
+(defn to-short-str [ms]
+ (let [date (from-long ms)
+ local (plus date time-zone-offset)
+ today-date (t/today)
+ today (date-time (t/year today-date)
+ (t/month today-date)
+ (t/day today-date))
+ yesterday (plus today (days -1))]
+ (cond
+ (before? local yesterday) (unparse (formatter "dd MMM") local)
+ (before? local today) "Yesterday"
+ :else (unparse (formatters :hour-minute) local))))
+
+(defn now-ms []
+ (to-long (now)))
diff --git a/src/status_im/utils/sms_listener.cljs b/src/status_im/utils/sms_listener.cljs
new file mode 100644
index 0000000000..f00d54b7e9
--- /dev/null
+++ b/src/status_im/utils/sms_listener.cljs
@@ -0,0 +1,19 @@
+(ns status-im.utils.sms-listener
+ (:require [status-im.components.react :refer [android?]]))
+
+(def sms-listener (.-default (js/require "react-native-android-sms-listener")))
+
+;; Only android is supported!
+
+(defn add-sms-listener
+ "Message format: {:originatingAddress string, :body string}. Returns
+ cancelable subscription."
+ [listen-fn]
+ (when android?
+ (.addListener sms-listener
+ (fn [message]
+ (listen-fn (js->clj message :keywordize-keys true))))))
+
+(defn remove-sms-listener [subscription]
+ (when android?
+ (.remove subscription)))
diff --git a/src/status_im/utils/utils.cljs b/src/status_im/utils/utils.cljs
index 8a0be411d7..02d54d3f88 100644
--- a/src/status_im/utils/utils.cljs
+++ b/src/status_im/utils/utils.cljs
@@ -47,3 +47,8 @@
(.catch (or on-error
(fn [error]
(toast (str error))))))))
+
+(defn truncate-str [s max]
+ (if (< max (count s))
+ (str (subs s 0 (- max 3)) "...")
+ s))