Merge pull request #85 from status-im/real-data

Listen sms. Comment/replace placeholders.

Former-commit-id: eb72ea776f
This commit is contained in:
Jarrad 2016-05-24 10:52:21 +02:00
commit bc1f9dcedd
32 changed files with 525 additions and 332 deletions

View File

@ -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"

View File

@ -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')

View File

@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application

View File

@ -11,6 +11,7 @@ import android.os.Environment;
import com.github.ethereum.go_ethereum.cmd.Geth;
import com.bitgo.randombytes.RandomBytesPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.centaurwarchief.smslistener.SmsListener;
import java.util.Arrays;
import java.util.List;
@ -80,7 +81,8 @@ public class MainActivity extends ReactActivity {
new ReactNativeContacts(),
new ReactNativeI18n(),
new RandomBytesPackage(),
new LinearGradientPackage()
new LinearGradientPackage(),
new SmsListener(this)
);
}
}

View File

@ -16,3 +16,5 @@ include ':randombytes'
project(':randombytes').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-randombytes/app')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':ReactNativeAndroidSmsListener'
project(':ReactNativeAndroidSmsListener').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-android-sms-listener/android')

View File

@ -10,6 +10,7 @@
"react": "^0.14.5",
"react-native": "^0.24.1",
"react-native-action-button": "^1.1.4",
"react-native-android-sms-listener": "^0.1.3",
"react-native-circle-checkbox": "^0.1.3",
"react-native-contacts": "^0.2.4",
"react-native-i18n": "0.0.8",

View File

@ -11,7 +11,8 @@
^{:voom {:repo "https://github.com/status-im/status-lib.git"
:branch "syng-rename"}}
[status-im/protocol "0.1.1-20160519_164302-g92930a0"]
[natal-shell "0.1.6"]]
[natal-shell "0.1.6"]
[com.andrewmcveigh/cljs-time "0.4.0"]]
:plugins [[lein-cljsbuild "1.1.1"]
[lein-figwheel "0.5.0-2"]]
:clean-targets ["target/" "index.ios.js" "index.android.js"]

View File

@ -2,6 +2,7 @@
(:require [re-frame.core :refer [register-handler enrich after debug dispatch]]
[status-im.models.commands :as commands]
[clojure.string :as str]
[status-im.components.styles :refer [default-chat-color]]
[status-im.chat.suggestions :as suggestions]
[status-im.protocol.api :as api]
[status-im.models.messages :as messages]
@ -12,7 +13,10 @@
[status-im.models.chats :as chats]
[status-im.navigation.handlers :as nav]
[status-im.utils.handlers :as u]
[status-im.persistence.realm :as r]))
[status-im.persistence.realm :as r]
[status-im.handlers.server :as server]
[status-im.utils.phone-number :refer [format-phone-number]]
[status-im.utils.datetime :as time]))
(register-handler :set-show-actions
(fn [db [_ show-actions]]
@ -104,7 +108,8 @@
:to current-chat-id
:from identity
:content-type text-content-type
:outgoing true})]
:outgoing true
:timestamp (time/now-ms)})]
(if command
(commands/set-chat-command db command)
(assoc db :new-message (when-not (str/blank? text) message)))))
@ -213,15 +218,22 @@
(assoc db :password-saved true)))
(register-handler :sign-up
(-> (fn [db [_ phone-number]]
(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))))))
(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.))

View File

@ -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]}

View File

@ -4,8 +4,11 @@
[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
@ -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,6 +77,19 @@
: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
@ -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.))

View File

@ -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,9 +54,7 @@
:height 9})
(def up-icon
{:marginTop 23
:marginLeft 21
:width 14
{:width 14
:height 8})
(def members
@ -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}))

View File

@ -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)}

View File

@ -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 [])}}])

View File

@ -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

View File

@ -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})]]])

View File

@ -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]}]
[{: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/photo-container
[contact-photo photo-path]
[contact-online online]]
[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} name]
[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 (< 1 (count contacts))
(str (count contacts) " members")
(if (< 0 (count contacts))
(str (inc (count contacts)) " members")
"1 member")])]
[text {:style st/last-message-text
:numberOfLines 2}
(repeatedly 5 #(str "Hi, I'm " name "! "))]]
(when last-message
(:content last-message))]]
[view
(when last-message
[view st/status-container
(when delivery-status
[image {:source (if (= (keyword delivery-status) :seen)
;; 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}])
[text {:style st/datetime-text} timestamp]]
(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]])]])
[text {:style st/new-messages-text} new-messages-count]])]]))

View File

@ -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]))

View File

@ -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})

View File

@ -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)

View File

@ -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)
)

View File

@ -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)]

View File

@ -12,9 +12,8 @@
(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]))
(defn contacts-by-chat [fn db chat-id]
(let [chat (reaction (get-in @db [:chats chat-id]))
contacts (reaction (:contacts @db))]
(reaction
(when @chat
@ -25,6 +24,10 @@
(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 _]
(let [identity (:contact-identity @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))))))))

View File

@ -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"

View File

@ -12,6 +12,7 @@
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]
[chat-id [:chat :chat-id]
group-chat [:chat :group-chat]
name [:chat :name]
color [:chat :color]]
[view (st/chat-icon color)
[text {:style st/chat-icon-text} (first name)]])
[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}

View File

@ -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

View File

@ -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.))

View File

@ -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"

View File

@ -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,14 +49,18 @@
: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]
photo-path [:get :photo-path]
phone-number [:get :phone-number]
email [:get :email]
status [:get :status]]
@ -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

View File

@ -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})

View File

@ -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)))

View File

@ -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)))

View File

@ -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))