add contact to contact list only after pressing "Add to contacts"

add new contact bar & badges
This commit is contained in:
Roman Volosovskyi 2016-11-11 14:31:36 +02:00
parent 9e994a767e
commit 07301497ea
13 changed files with 240 additions and 87 deletions

View File

@ -238,7 +238,7 @@
(after (fn [_ [_ phone-number]]
(dispatch [:account-update {:phone phone-number}])))
(fn [db [_ phone-number message-id]]
(let [formatted (format-phone-number phone-number)]
(let [formatted (format-phone-number phone-number)]
(-> db
(assoc :user-phone-number formatted)
sign-up-service/start-listening-confirmation-code-sms
@ -288,13 +288,13 @@
(defn initialize-chats
[{:keys [loaded-chats account-creation? chats] :as db} _]
(let [chats' (if account-creation?
chats
(->> loaded-chats
(map (fn [{:keys [chat-id] :as chat}]
(let [last-message (messages/get-last-message db chat-id)]
[chat-id (assoc chat :last-message last-message)])))
(into {})))
ids (set (keys chats'))]
chats
(->> loaded-chats
(map (fn [{:keys [chat-id] :as chat}]
(let [last-message (messages/get-last-message db chat-id)]
[chat-id (assoc chat :last-message last-message)])))
(into {})))
ids (set (keys chats'))]
(-> db
(assoc :chats chats')
@ -399,6 +399,12 @@
(dispatch [::start-chat! contact-id options navigation-type])))))
(register-handler :add-chat
(u/side-effect!
(fn [{:keys [chats]} [_ chat-id chat]]
(when-not (get chats chat-id)
(dispatch [::add-chat chat-id chat])))))
(register-handler ::add-chat
(-> add-new-chat
((enrich add-chat))
((after save-new-chat!))))

View File

@ -98,6 +98,16 @@
[view st/action
[chat-icon]]]))))
(defview add-contact-bar []
[pending-contact? [:chat :pending-contact?]
chat-id [:get :current-chat-id]]
(when pending-contact?
[touchable-highlight
{:on-press #(dispatch [:add-pending-contact chat-id])}
[view st/add-contact
[text {:style st/add-contact-text}
(label :t/add-to-contacts)]]]))
(defview chat-toolbar []
[show-actions? [:chat-ui-props :show-actions?]
accounts [:get :accounts]]
@ -106,8 +116,8 @@
[toolbar {:hide-nav? (or (empty? accounts) show-actions?)
:custom-content [toolbar-content-view]
:custom-action [toolbar-action]
:style (get-in platform-specific [:component-styles :toolbar])}]])
:style (get-in platform-specific [:component-styles :toolbar])}]
[add-contact-bar]])
(defn get-intro-status-message [all-messages]
(let [{:keys [timestamp content-type] :as last-message} (last all-messages)]
(when (not= content-type content-type-status)

View File

@ -139,9 +139,9 @@
:backgroundColor selected-message-color})
(def typing-text
{:marginTop -2
:fontSize 12
:color text2-color})
{:marginTop -2
:fontSize 12
:color text2-color})
(def overlay-highlight
{:flex 1})
@ -155,7 +155,7 @@
:left -16
:right -16
:background-color "#00000055"
:elevation 8})
:elevation 8})
(defn bottom-info-container [height]
{:backgroundColor toolbar-background1
@ -194,7 +194,17 @@
(def chat-modal
{:position :absolute
:left 0
:top 0
:right 0
:bottom 0})
:left 0
:top 0
:right 0
:bottom 0})
(def add-contact
{:height 35
:background-color :white
:justify-content :center})
(def add-contact-text
{:text-align :center
:text-align-vertical :center
:color :#7099e6})

View File

@ -44,13 +44,6 @@
:height 19}
:handler #(dispatch [:show-profile chat-id])})
(defn item-add-to-contacts [contact]
{:title (label :t/add-to-contacts)
:icon :menu_group
:icon-style {:width 20
:height 17}
:handler #(dispatch [:add-pending-contact contact])})
(def item-search
{:title (label :t/search-chat)
:subtitle (label :t/not-implemented)
@ -83,9 +76,8 @@
item-notifications
item-settings])
(defn user-chat-items [chat-id {:keys [pending] :as contact}]
(defn user-chat-items [chat-id]
[(item-user chat-id)
(if pending (item-add-to-contacts contact) nil)
item-search
item-notifications
item-settings])
@ -123,12 +115,13 @@
subtitle])]]])
(defn actions-list-view []
(let [{:keys [group-chat chat-id]} (subscribe [:chat-properties [:group-chat :chat-id]])
(let [{:keys [group-chat chat-id]}
(subscribe [:chat-properties [:group-chat :chat-id]])
members (subscribe [:current-chat-contacts])
status-bar-height (get-in platform-specific [:component-styles :status-bar :default :height])]
(when-let [actions (if @group-chat
(group-chat-items @members)
(user-chat-items @chat-id (first @members)))]
(user-chat-items @chat-id))]
[view (-> (st/actions-wrapper status-bar-height)
(merge (get-in platform-specific [:component-styles :actions-list-view])))
[view st/actions-separator]

View File

@ -16,7 +16,7 @@
[text {:style (:default-chat-icon-text styles)}
(first name)]])
(defn chat-icon [photo-path {:keys [size border]}]
(defn chat-icon [photo-path {:keys [size]}]
[image {:source {:uri photo-path}
:style (merge st/default-image-style
(st/image-style size))}])
@ -39,6 +39,14 @@
[oct-icon {:name :pencil
:style st/photo-pencil}]])]))
(defview pending-contact-badge
[chat-id {:keys [pending-wrapper pending-outer-circle pending-inner-circle]}]
[pending-contact? [:get-in [:chats chat-id :pending-contact?]]]
(when pending-contact?
[view pending-wrapper
[view pending-outer-circle
[view pending-inner-circle]]]))
(defview chat-icon-view [chat-id group-chat name online styles]
[photo-path [:chat-photo chat-id]
dapp? [:get-in [:contacts chat-id :dapp?]]]
@ -47,7 +55,8 @@
[chat-icon photo-path styles]
[default-chat-icon name styles])
(when dapp?
[dapp-badge styles])])
[dapp-badge styles])
[pending-contact-badge chat-id styles]])
(defn chat-icon-view-chat-list [chat-id group-chat name color online]
[chat-icon-view chat-id group-chat name online
@ -56,6 +65,9 @@
:online-view st/online-view
:online-dot-left st/online-dot-left
:online-dot-right st/online-dot-right
:pending-wrapper st/pending-wrapper
:pending-outer-circle st/pending-outer-circle
:pending-inner-circle st/pending-inner-circle
:size 40
:chat-icon st/chat-icon-chat-list
:default-chat-icon (st/default-chat-icon-chat-list color)
@ -68,6 +80,9 @@
:online-view st/online-view
:online-dot-left st/online-dot-left
:online-dot-right st/online-dot-right
:pending-wrapper st/pending-wrapper
:pending-outer-circle st/pending-outer-circle
:pending-inner-circle st/pending-inner-circle
:size 36
:chat-icon st/chat-icon-view-action
:default-chat-icon (st/default-chat-icon-view-action color)
@ -80,6 +95,9 @@
: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
:pending-wrapper st/pending-view-menu-wrapper
:pending-outer-circle st/pending-outer-circle
:pending-inner-circle st/pending-inner-circle
:size 24
:chat-icon st/chat-icon-menu-item
:default-chat-icon (st/default-chat-icon-view-action color)
@ -92,6 +110,9 @@
:online-view st/online-view
:online-dot-left st/online-dot-left
:online-dot-right st/online-dot-right
:pending-wrapper st/pending-wrapper
:pending-outer-circle st/pending-outer-circle
:pending-inner-circle st/pending-inner-circle
:size 64
:chat-icon st/chat-icon-message-status
:default-chat-icon (st/default-chat-icon-message-status color)

View File

@ -119,8 +119,8 @@
{:width 14
:height 14
:border-radius 7
:bottom 1
:right 1}))
:bottom 1
:right 1}))
(def online-view-profile
(merge online-view
@ -201,3 +201,39 @@
{:width image-size
:height image-size
:border-radius (/ image-size 2)}))
(def pending-wrapper
{:position :absolute
:bottom 4
:right 5
:width 12
:height 12
:border-radius 6
:background-color :white
:align-items :center
:justify-content :center})
(def pending-view-menu-wrapper
{:position :absolute
:bottom 2
:right 2
:width 12
:height 12
:border-radius 6
:background-color :white
:align-items :center
:justify-content :center})
(def pending-outer-circle
{:background-color online-color
:width 8
:height 8
:border-radius 4
:align-items :center
:justify-content :center})
(def pending-inner-circle
{:background-color :white
:width 4
:height 4
:border-radius 2})

View File

@ -18,13 +18,15 @@
:duration 250})))
(defn offline-view [_]
(let [sync-state (subscribe [:get :sync-state])
network-status (subscribe [:get :network-status])
offline-opacity (anim/create-value 0.0)
on-update (fn [_ _]
(anim/set-value offline-opacity 0)
(when (or (= @network-status :offline) (= @sync-state :offline))
(start-offline-animation offline-opacity)))]
(let [sync-state (subscribe [:get :sync-state])
network-status (subscribe [:get :network-status])
offline-opacity (anim/create-value 0.0)
on-update (fn [_ _]
(anim/set-value offline-opacity 0)
(when (or (= @network-status :offline) (= @sync-state :offline))
(start-offline-animation offline-opacity)))
pending-contact? (subscribe [:chat :pending-contact?])
view-id (subscribe [:get :view-id])]
(r/create-class
{:component-did-mount
on-update
@ -33,7 +35,8 @@
:reagent-render
(fn [{:keys [top]}]
(when (or (= @network-status :offline) (= @sync-state :offline))
[animated-view {:style (st/offline-wrapper top offline-opacity window-width)}
[view
[text {:style st/offline-text}
(label :t/offline)]]]))})))
(let [pending? (and @pending-contact? (= :chat @view-id))]
[animated-view {:style (st/offline-wrapper top offline-opacity window-width pending?)}
[view
[text {:style st/offline-text}
(label :t/offline)]]])))})))

View File

@ -26,10 +26,10 @@
:background-color "#5fc48d"
:height 2})
(defn offline-wrapper [top opacity window-width]
(defn offline-wrapper [top opacity window-width pending?]
{:opacity opacity
:width window-width
:top (+ 56 top)
:top (+ (+ 56 top) (if pending? 35 0))
:position :absolute
:background-color "#828b92cc"
:height 35})
@ -38,4 +38,4 @@
{:text-align :center
:color :white
:font-size 14
:top 8})
:top 8})

View File

@ -11,7 +11,8 @@
[status-im.utils.utils :refer [require]]
[status-im.navigation.handlers :as nav]
[status-im.utils.random :as random]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[cljs.reader :refer [read-string]]))
(defmethod nav/preload-data! :group-contacts
@ -55,7 +56,8 @@
(defn send-contact-request
[{:keys [current-public-key web3 current-account-id accounts]} [_ contact]]
(let [{:keys [whisper-identity]} contact
{:keys [name photo-path updates-public-key updates-private-key]} (get accounts current-account-id)]
{:keys [name photo-path updates-public-key updates-private-key status]}
(get accounts current-account-id)]
(protocol/contact-request!
{:web3 web3
:message {:from current-public-key
@ -63,7 +65,8 @@
:message-id (random/id)
:payload {:contact {:name name
:profile-image photo-path
:address current-account-id}
:address current-account-id
:status status}
:keypair {:public updates-public-key
:private updates-private-key}}}})))
@ -132,7 +135,7 @@
(defn request-stored-contacts [contacts]
(let [contacts-by-hash (get-contacts-by-hash contacts)
data (or (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)]
@ -156,7 +159,7 @@
(defn add-new-contacts
[{:keys [contacts] :as db} [_ new-contacts]]
(let [identities (set (map :whisper-identity contacts))
(let [identities (set (map :whisper-identity contacts))
new-contacts' (->> new-contacts
(map #(update-pending-status contacts %))
(remove #(identities (:whisper-identity %)))
@ -193,22 +196,13 @@
(register-handler :add-pending-contact
(u/side-effect!
(fn [{:keys [current-public-key web3 current-account-id accounts]}
[_ {:keys [whisper-identity] :as contact}]]
(let [contact (assoc contact :pending false)
{:keys [name photo-path updates-public-key updates-private-key]}
(accounts current-account-id)]
(protocol/contact-request!
{:web3 web3
:message {:from current-public-key
:to whisper-identity
:message-id (random/id)
:payload {:contact {:name name
:profile-image photo-path
:address current-account-id}
:keypair {:public updates-public-key
:private updates-private-key}}}})
(dispatch [::update-pending-contact contact])))))
(fn [{:keys [chats]} [_ chat-id]]
(let [contact (read-string (get-in chats [chat-id :contact-info]))]
(dispatch [::prepare-contact contact])
(dispatch [:update-chat! {:chat-id chat-id
:contact-info nil
:pending-contact? false}])
(dispatch [:watch-contact contact])))))
(defn set-contact-identity-from-qr
[db [_ _ contact-identity]]

View File

@ -1,15 +1,20 @@
(ns status-im.data-store.realm.schemas.account.core
(:require [status-im.data-store.realm.schemas.account.v1.core :as v1]
[status-im.data-store.realm.schemas.account.v2.core :as v2]
[status-im.data-store.realm.schemas.account.v3.core :as v3]))
[status-im.data-store.realm.schemas.account.v3.core :as v3]
[status-im.data-store.realm.schemas.account.v4.core :as v4]
))
; put schemas ordered by version
(def schemas [{:schema v1/schema
(def schemas [{:schema v1/schema
:schemaVersion 1
:migration v1/migration}
{:schema v2/schema
:migration v1/migration}
{:schema v2/schema
:schemaVersion 2
:migration v2/migration}
{:schema v3/schema
:migration v2/migration}
{:schema v3/schema
:schemaVersion 3
:migration v3/migration}])
:migration v3/migration}
{:schema v4/schema
:schemaVersion 4
:migration v4/migration}])

View File

@ -0,0 +1,38 @@
(ns status-im.data-store.realm.schemas.account.v4.chat
(:require [taoensso.timbre :as log]
[status-im.components.styles :refer [default-chat-color]]))
(def schema {:name :chat
:primaryKey :chat-id
:properties {:chat-id :string
:name :string
:color {:type :string
:default default-chat-color}
:group-chat {:type :bool
:indexed true}
:is-active :bool
:timestamp :int
:contacts {:type :list
:objectType :chat-contact}
:dapp-url {:type :string
:optional true}
:dapp-hash {:type :int
:optional true}
:removed-at {:type :int
:optional true}
:last-message-id :string
:public-key {:type :string
:optional true}
:private-key {:type :string
:optional true}
:clock-value {:type :int
:default 0}
:pending-contact? {:type :bool
:default false}
:contact-info {:type :string
:optional true}}})
(defn migration [_ new-realm]
(let [new-objs (.objects new-realm "chat")]
(dotimes [i (range (.-length new-objs))]
(aset (aget new-objs i) "pending-contact?" false))))

View File

@ -0,0 +1,29 @@
(ns status-im.data-store.realm.schemas.account.v4.core
(:require [taoensso.timbre :as log]
[status-im.data-store.realm.schemas.account.v4.chat :as chat]
[status-im.data-store.realm.schemas.account.v3.message :as message]
[status-im.data-store.realm.schemas.account.v2.contact :as contact]
[status-im.data-store.realm.schemas.account.v1.chat-contact :as chat-contact]
[status-im.data-store.realm.schemas.account.v1.command :as command]
[status-im.data-store.realm.schemas.account.v1.discovery :as discovery]
[status-im.data-store.realm.schemas.account.v1.kv-store :as kv-store]
[status-im.data-store.realm.schemas.account.v1.pending-message :as pending-message]
[status-im.data-store.realm.schemas.account.v1.request :as request]
[status-im.data-store.realm.schemas.account.v1.tag :as tag]
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]))
(def schema [chat/schema
chat-contact/schema
command/schema
contact/schema
discovery/schema
kv-store/schema
message/schema
pending-message/schema
request/schema
tag/schema
user-status/schema])
(defn migration [old-realm new-realm]
(log/debug "migrating v4 account database: " old-realm new-realm)
(chat/migration old-realm new-realm))

View File

@ -288,17 +288,25 @@
(register-handler :contact-request-received
(u/side-effect!
(fn [_ [_ {:keys [from payload]}]]
(fn [{:keys [contacts]} [_ {:keys [from payload]}]]
(when from
(let [{{:keys [name profile-image address]} :contact
{:keys [public private]} :keypair} payload
(let [{{:keys [name profile-image address status]} :contact
{:keys [public private]} :keypair} payload
contact {:whisper-identity from
:public-key public
:private-key private
:address address
:photo-path profile-image
:name name
:pending true}]
(dispatch [:watch-contact contact])
(dispatch [:add-contacts [contact]]))))))
contact {:whisper-identity from
:public-key public
:private-key private
:address address
:status status
:photo-path profile-image
:name name}
contact-exist? (get contacts from)
chat {:name name
:chat-id from
:contact-info (prn-str contact)
:pending-contact? true}]
(if contact-exist?
(do
(dispatch [:update-contact! contact])
(dispatch [:watch-contact contact]))
(dispatch [:add-chat from chat])))))))