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

@ -399,6 +399,12 @@
(dispatch [::start-chat! contact-id options navigation-type]))))) (dispatch [::start-chat! contact-id options navigation-type])))))
(register-handler :add-chat (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 (-> add-new-chat
((enrich add-chat)) ((enrich add-chat))
((after save-new-chat!)))) ((after save-new-chat!))))

View File

@ -98,6 +98,16 @@
[view st/action [view st/action
[chat-icon]]])))) [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 [] (defview chat-toolbar []
[show-actions? [:chat-ui-props :show-actions?] [show-actions? [:chat-ui-props :show-actions?]
accounts [:get :accounts]] accounts [:get :accounts]]
@ -106,8 +116,8 @@
[toolbar {:hide-nav? (or (empty? accounts) show-actions?) [toolbar {:hide-nav? (or (empty? accounts) show-actions?)
:custom-content [toolbar-content-view] :custom-content [toolbar-content-view]
:custom-action [toolbar-action] :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] (defn get-intro-status-message [all-messages]
(let [{:keys [timestamp content-type] :as last-message} (last all-messages)] (let [{:keys [timestamp content-type] :as last-message} (last all-messages)]
(when (not= content-type content-type-status) (when (not= content-type content-type-status)

View File

@ -198,3 +198,13 @@
:top 0 :top 0
:right 0 :right 0
:bottom 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} :height 19}
:handler #(dispatch [:show-profile chat-id])}) :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 (def item-search
{:title (label :t/search-chat) {:title (label :t/search-chat)
:subtitle (label :t/not-implemented) :subtitle (label :t/not-implemented)
@ -83,9 +76,8 @@
item-notifications item-notifications
item-settings]) item-settings])
(defn user-chat-items [chat-id {:keys [pending] :as contact}] (defn user-chat-items [chat-id]
[(item-user chat-id) [(item-user chat-id)
(if pending (item-add-to-contacts contact) nil)
item-search item-search
item-notifications item-notifications
item-settings]) item-settings])
@ -123,12 +115,13 @@
subtitle])]]]) subtitle])]]])
(defn actions-list-view [] (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]) members (subscribe [:current-chat-contacts])
status-bar-height (get-in platform-specific [:component-styles :status-bar :default :height])] status-bar-height (get-in platform-specific [:component-styles :status-bar :default :height])]
(when-let [actions (if @group-chat (when-let [actions (if @group-chat
(group-chat-items @members) (group-chat-items @members)
(user-chat-items @chat-id (first @members)))] (user-chat-items @chat-id))]
[view (-> (st/actions-wrapper status-bar-height) [view (-> (st/actions-wrapper status-bar-height)
(merge (get-in platform-specific [:component-styles :actions-list-view]))) (merge (get-in platform-specific [:component-styles :actions-list-view])))
[view st/actions-separator] [view st/actions-separator]

View File

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

View File

@ -201,3 +201,39 @@
{:width image-size {:width image-size
:height image-size :height image-size
:border-radius (/ image-size 2)})) :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

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

View File

@ -26,10 +26,10 @@
:background-color "#5fc48d" :background-color "#5fc48d"
:height 2}) :height 2})
(defn offline-wrapper [top opacity window-width] (defn offline-wrapper [top opacity window-width pending?]
{:opacity opacity {:opacity opacity
:width window-width :width window-width
:top (+ 56 top) :top (+ (+ 56 top) (if pending? 35 0))
:position :absolute :position :absolute
:background-color "#828b92cc" :background-color "#828b92cc"
:height 35}) :height 35})

View File

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

View File

@ -1,7 +1,9 @@
(ns status-im.data-store.realm.schemas.account.core (ns status-im.data-store.realm.schemas.account.core
(:require [status-im.data-store.realm.schemas.account.v1.core :as v1] (: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.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 ; put schemas ordered by version
(def schemas [{:schema v1/schema (def schemas [{:schema v1/schema
@ -12,4 +14,7 @@
:migration v2/migration} :migration v2/migration}
{:schema v3/schema {:schema v3/schema
:schemaVersion 3 :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 (register-handler :contact-request-received
(u/side-effect! (u/side-effect!
(fn [_ [_ {:keys [from payload]}]] (fn [{:keys [contacts]} [_ {:keys [from payload]}]]
(when from (when from
(let [{{:keys [name profile-image address]} :contact (let [{{:keys [name profile-image address status]} :contact
{:keys [public private]} :keypair} payload {:keys [public private]} :keypair} payload
contact {:whisper-identity from contact {:whisper-identity from
:public-key public :public-key public
:private-key private :private-key private
:address address :address address
:status status
:photo-path profile-image :photo-path profile-image
:name name :name name}
:pending true}] contact-exist? (get contacts from)
(dispatch [:watch-contact contact]) chat {:name name
(dispatch [:add-contacts [contact]])))))) :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])))))))