[#15056] Can't see display/ens/name when mentioning in community (#15085)

This commit is contained in:
flexsurfer 2023-02-27 12:51:53 +01:00 committed by GitHub
parent 69c3a72357
commit 80f063d0dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 920 additions and 1319 deletions

View File

@ -0,0 +1,67 @@
(ns quo2.components.list-items.user-list
(:require [react-native.core :as rn]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.markdown.text :as text]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[quo2.components.messages.author.view :as author]
[quo2.components.selectors.selectors :as selectors]))
(def container-style
{:margin-horizontal 8
:padding-vertical 8
:padding-horizontal 12
:border-radius 12
:flex 1
:flex-direction :row
:align-items :center})
(defn action-icon
[{:keys [type on-press on-check disabled? checked?]}]
[rn/touchable-opacity
{:on-press (when on-press on-press)
:style {:position :absolute :right 20}}
(case type
:options
[icons/icon :i/options
{:size 20
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
:checkbox
[selectors/checkbox
{:checked? checked?
:accessibility-label :user-list-toggle-check
:disabled? disabled?
:on-change (when on-check on-check)}]
:close
[text/text "not implemented"]
[rn/view])])
(defn user-list
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
untrustworthy? on-press on-long-press accessory]}]
[rn/touchable-opacity
{:style container-style
:accessibility-label :user-list
:on-press (when on-press on-press)
:on-long-press (when on-long-press on-long-press)}
[user-avatar/user-avatar
{:full-name primary-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small
:ring? false}]
[rn/view {:style {:margin-left 8}}
[author/author
{:primary-name primary-name
:secondary-name secondary-name
:contact? contact?
:verified? verified?
:untrustworthy? untrustworthy?}]
(when short-chat-key
[text/text
{:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
short-chat-key])]
(when accessory
[action-icon accessory])])

View File

@ -7,14 +7,6 @@
:flex-direction :row :flex-direction :row
:align-items :center}) :align-items :center})
(defn ens-text
[]
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(defn nickname-text
[]
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(def middle-dot-nickname (def middle-dot-nickname
{:color colors/neutral-50 {:color colors/neutral-50
:margin-horizontal 4}) :margin-horizontal 4})
@ -27,12 +19,6 @@
{:color colors/neutral-50 {:color colors/neutral-50
:margin-left 4}) :margin-left 4})
(defn profile-name-text
[nickname?]
{:color (if nickname?
(colors/theme-colors colors/neutral-60 colors/neutral-40)
(colors/theme-colors colors/neutral-100 colors/white))})
(def icon-container (def icon-container
{:margin-left 4}) {:margin-left 4})

View File

@ -3,97 +3,64 @@
[quo2.components.icon :as icons] [quo2.components.icon :as icons]
[quo2.components.markdown.text :as text] [quo2.components.markdown.text :as text]
[quo2.components.messages.author.style :as style] [quo2.components.messages.author.style :as style]
[react-native.core :as rn])) [react-native.core :as rn]
[quo2.foundations.colors :as colors]))
(def middle-dot "·") (def middle-dot "·")
(defn display-name
[{:keys [profile-name nickname ens-name text-style]}]
(let [ens? (-> ens-name string/blank? not)
nickname? (-> nickname string/blank? not)]
(if ens?
[text/text
(merge {:weight :semi-bold
:size :paragraph-2
:style (style/ens-text)}
text-style)
ens-name]
[:<>
(if nickname?
[text/text
(merge {:weight :semi-bold
:size :paragraph-2
:style (style/nickname-text)}
text-style)
nickname]
[text/text
(merge {:weight :semi-bold
:size :paragraph-2
:style (style/profile-name-text nickname?)}
text-style)
profile-name])])))
(defn author (defn author
[{:keys [profile-name nickname short-chat-key ens-name time-str contact? verified? untrustworthy?]}] [{:keys [primary-name secondary-name short-chat-key time-str contact? verified? untrustworthy?]}]
[:f> [:f>
(fn [] (fn []
(let [ens? (-> ens-name string/blank? not) [rn/view {:style style/container}
nickname? (-> nickname string/blank? not)] [:<>
[rn/view {:style style/container} [text/text
(if ens? {:weight :semi-bold
:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-100 colors/white)}}
primary-name]
(when (not (string/blank? secondary-name))
[:<>
[text/text [text/text
{:weight :semi-bold {:size :paragraph-2
:style style/middle-dot-nickname}
middle-dot]
[text/text
{:weight :medium
:size :paragraph-2 :size :paragraph-2
:style (style/ens-text)} :style {:color (colors/theme-colors colors/neutral-60 colors/neutral-40)}}
ens-name] secondary-name]])]
[:<> (when contact?
(when nickname? [icons/icon :main-icons2/contact
[:<> {:size 12
[text/text :no-color true
{:weight :semi-bold :container-style style/icon-container}])
:size :paragraph-2 (cond
:style (style/nickname-text)} verified?
nickname] [icons/icon :main-icons2/verified
[text/text {:size 12
{:size :paragraph-2 :no-color true
:style style/middle-dot-nickname} :container-style style/icon-container}]
middle-dot]]) untrustworthy?
[text/text [icons/icon :main-icons2/untrustworthy
{:weight (if nickname? :medium :semi-bold) {:size 12
:size :paragraph-2 :no-color true
:style (style/profile-name-text nickname?)} :container-style style/icon-container}])
profile-name]]) (when-not verified?
(when contact?
[icons/icon :main-icons2/contact
{:size 12
:no-color true
:container-style style/icon-container}])
(cond
verified?
[icons/icon :main-icons2/verified
{:size 12
:no-color true
:container-style style/icon-container}]
untrustworthy?
[icons/icon :main-icons2/untrustworthy
{:size 12
:no-color true
:container-style style/icon-container}])
(when-not ens?
[text/text
{:monospace true
:size :paragraph-2
:style style/chat-key-text}
short-chat-key])
(when-not ens?
[text/text
{:monospace true
:size :paragraph-2
:style style/middle-dot-chat-key}
middle-dot])
[text/text [text/text
{:monospace true {:monospace true
:size :paragraph-2 :size :paragraph-2
:accessibility-label :message-timestamp :style style/chat-key-text}
:style (style/time-text ens?)} short-chat-key])
time-str]]))]) (when (and (not verified?) time-str)
[text/text
{:monospace true
:size :paragraph-2
:style style/middle-dot-chat-key}
middle-dot])
[text/text
{:monospace true
:size :paragraph-2
:accessibility-label :message-timestamp
:style (style/time-text verified?)}
time-str]])])

View File

@ -62,7 +62,8 @@
quo2.components.tags.permission-tag quo2.components.tags.permission-tag
quo2.components.tags.tag quo2.components.tags.tag
quo2.components.tags.tags quo2.components.tags.tags
quo2.components.tags.token-tag)) quo2.components.tags.token-tag
quo2.components.list-items.user-list))
(def toast quo2.components.notifications.toast/toast) (def toast quo2.components.notifications.toast/toast)
(def button quo2.components.buttons.button/button) (def button quo2.components.buttons.button/button)
@ -93,7 +94,6 @@
(def filter quo2.components.selectors.filter.view/view) (def filter quo2.components.selectors.filter.view/view)
(def skeleton quo2.components.loaders.skeleton/skeleton) (def skeleton quo2.components.loaders.skeleton/skeleton)
(def author quo2.components.messages.author.view/author) (def author quo2.components.messages.author.view/author)
(def display-name quo2.components.messages.author.view/display-name)
;;;; AVATAR ;;;; AVATAR
(def account-avatar quo2.components.avatars.account-avatar/account-avatar) (def account-avatar quo2.components.avatars.account-avatar/account-avatar)
@ -141,6 +141,7 @@
(def channel-list-item quo2.components.list-items.channel/list-item) (def channel-list-item quo2.components.list-items.channel/list-item)
(def menu-item quo2.components.list-items.menu-item/menu-item) (def menu-item quo2.components.list-items.menu-item/menu-item)
(def preview-list quo2.components.list-items.preview-list/preview-list) (def preview-list quo2.components.list-items.preview-list/preview-list)
(def user-list quo2.components.list-items.user-list/user-list)
;;;; NOTIFICATIONS ;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-log.view/view) (def activity-log quo2.components.notifications.activity-log.view/view)

View File

@ -19,8 +19,8 @@
(defn- wrap-key-fn (defn- wrap-key-fn
[f] [f]
(fn [data index] (fn [data index]
{:post [(some? %)]} (when f
(f data index))) (f data index))))
(defn base-list-props (defn base-list-props
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn] [{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn]

View File

@ -3,7 +3,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.add-new.db :as db] [status-im.add-new.db :as db]
[status-im2.contexts.chat.events :as chat] [status-im2.contexts.chat.events :as chat]
[status-im.contact.core :as contact] [status-im2.contexts.contacts.events :as contact]
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens] [status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus] [status-im.ethereum.stateofus :as stateofus]

View File

@ -41,11 +41,11 @@
(rf/defn select-mention (rf/defn select-mention
{:events [:chat.ui/select-mention]} {:events [:chat.ui/select-mention]}
[{:keys [db] :as cofx} text-input-ref {:keys [alias name searched-text match] :as user}] [{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match] :as user}]
(let [chat-id (:current-chat-id db) (let [chat-id (:current-chat-id db)
new-text (mentions/new-input-text-with-mention cofx user) new-text (mentions/new-input-text-with-mention cofx user)
at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx]) at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx])
cursor (+ at-sign-idx (count name) 2)] cursor (+ at-sign-idx (count primary-name) 2)]
(rf/merge (rf/merge
cofx cofx
{:db (-> db {:db (-> db
@ -63,15 +63,14 @@
;; NOTE(roman): on-text-input event is not dispatched when we change input ;; NOTE(roman): on-text-input event is not dispatched when we change input
;; programmatically, so we have to call `on-text-input` manually ;; programmatically, so we have to call `on-text-input` manually
(mentions/on-text-input (mentions/on-text-input
(let [match-len (count match) (let [match-len (count match)
searched-text-len (count searched-text) start (inc at-sign-idx)
start (inc at-sign-idx) end (+ start match-len)]
end (+ start match-len)]
{:new-text match {:new-text match
:previous-text searched-text :previous-text searched-text
:start start :start start
:end end})) :end end}))
(mentions/recheck-at-idxs {alias user})))) (mentions/recheck-at-idxs {primary-name user}))))
(rf/defn disable-chat-cooldown (rf/defn disable-chat-cooldown
"Turns off chat cooldown (protection against message spamming)" "Turns off chat cooldown (protection against message spamming)"

View File

@ -120,7 +120,7 @@
(get-in db [:pagination-info chat-id :messages-initialized?]))) (get-in db [:pagination-info chat-id :messages-initialized?])))
(let [already-loaded-messages (get-in db [:messages chat-id]) (let [already-loaded-messages (get-in db [:messages chat-id])
;; We remove those messages that are already loaded, as we might get some duplicates ;; We remove those messages that are already loaded, as we might get some duplicates
{:keys [all-messages new-messages senders contacts]} {:keys [all-messages new-messages contacts]}
(reduce (fn [{:keys [all-messages] :as acc} (reduce (fn [{:keys [all-messages] :as acc}
{:keys [message-id from] {:keys [message-id from]
:as message}] :as message}]
@ -143,25 +143,23 @@
:cursor-clock-value]) :cursor-clock-value])
clock-value (when cursor (cursor->clock-value cursor)) clock-value (when cursor (cursor->clock-value cursor))
new-messages (map mark-album new-messages)] new-messages (map mark-album new-messages)]
{:dispatch [:chat/add-senders-to-chat-users (vals senders)] {:db (-> db
:db (-> db (update-in [:pagination-info chat-id :cursor-clock-value]
(update-in [:pagination-info chat-id :cursor-clock-value] #(if (and (seq cursor) (or (not %) (< clock-value %)))
#(if (and (seq cursor) (or (not %) (< clock-value %))) clock-value
clock-value %))
%)) (update-in [:pagination-info chat-id :cursor]
#(if (or (empty? cursor)
(update-in [:pagination-info chat-id :cursor] (not current-clock-value)
#(if (or (empty? cursor) (< clock-value current-clock-value))
(not current-clock-value) cursor
(< clock-value current-clock-value)) %))
cursor (assoc-in [:pagination-info chat-id :loading-messages?] false)
%)) (assoc-in [:messages chat-id] all-messages)
(assoc-in [:pagination-info chat-id :loading-messages?] false) (update-in [:message-lists chat-id] message-list/add-many new-messages)
(assoc-in [:messages chat-id] all-messages) (assoc-in [:pagination-info chat-id :all-loaded?]
(update-in [:message-lists chat-id] message-list/add-many new-messages) (empty? cursor))
(assoc-in [:pagination-info chat-id :all-loaded?] (update :contacts/contacts merge contacts))})))
(empty? cursor))
(update :contacts/contacts merge contacts))})))
(rf/defn load-more-messages (rf/defn load-more-messages
{:events [:chat.ui/load-more-messages]} {:events [:chat.ui/load-more-messages]}

View File

@ -9,13 +9,10 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
(def at-sign "@") (def at-sign "@")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn re-pos (defn re-pos
[re s] [re s]
(loop [res [] (loop [res []
@ -177,43 +174,25 @@
:else (recur data (inc idx))))))))) :else (recur data (inc idx)))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn add-searchable-phrases
[{:keys [alias name nickname] :as user}]
(reduce
(fn [user s]
(if (nil? s)
user
(let [new-words (concat
[s]
(rest (string/split s " ")))]
(update user :searchable-phrases (fnil concat []) new-words))))
user
[alias name nickname]))
(defn add-searchable-phrases-to-contact (defn add-searchable-phrases-to-contact
[{:keys [alias name added? blocked? identicon public-key nickname ens-verified]} community-chat?] [{:keys [primary-name secondary-name blocked?] :as contact}]
(when (and alias (when (not blocked?)
(not (string/blank? alias)) (reduce
(or name (fn [user s]
nickname (if (nil? s)
added? user
community-chat?) (let [new-words (concat
(not blocked?)) [s]
(add-searchable-phrases (rest (string/split s " ")))]
{:alias alias (update user :searchable-phrases (fnil concat []) new-words))))
:name (or (and ens-verified (utils/safe-replace name ".stateofus.eth" "")) alias) contact
:identicon identicon [primary-name secondary-name])))
:nickname nickname
:ens-verified ens-verified
:public-key public-key})))
(defn mentionable-contacts (defn mentionable-contacts
[contacts] [contacts]
(reduce (reduce
(fn [acc [key contact]] (fn [acc [key contact]]
(let [mentionable-contact (add-searchable-phrases-to-contact contact false)] (let [mentionable-contact (add-searchable-phrases-to-contact contact)]
(if (nil? mentionable-contact) (if (nil? mentionable-contact)
acc acc
(assoc acc key mentionable-contact)))) (assoc acc key mentionable-contact))))
@ -223,17 +202,8 @@
(defn mentionable-contacts-from-identites (defn mentionable-contacts-from-identites
[contacts my-public-key identities] [contacts my-public-key identities]
(reduce (fn [acc identity] (reduce (fn [acc identity]
(let [contact (multiaccounts/contact-by-identity (let [contact (multiaccounts/contact-by-identity contacts identity)
contacts mentionable-contact (add-searchable-phrases-to-contact contact)]
identity)
contact (if (string/blank? (:alias contact))
(assoc contact
:alias
(get-in contact [:names :three-words-name]))
contact)
mentionable-contact (add-searchable-phrases-to-contact
contact
true)]
(if (nil? mentionable-contact) (if (nil? mentionable-contact)
acc acc
(assoc acc identity mentionable-contact)))) (assoc acc identity mentionable-contact))))
@ -247,9 +217,9 @@
mentionable-contacts (mentionable-contacts all-contacts) mentionable-contacts (mentionable-contacts all-contacts)
mentionable-users (assoc users mentionable-users (assoc users
public-key public-key
{:alias name {:secondary-name name
:name (or preferred-name name) :primary-name (or preferred-name name)
:public-key public-key})] :public-key public-key})]
(cond (cond
(= chat-type constants/private-group-chat-type) (= chat-type constants/private-group-chat-type)
(merge mentionable-users (merge mentionable-users
@ -273,30 +243,31 @@
(= chat-type constants/public-chat-type) (= chat-type constants/public-chat-type)
(merge mentionable-users (select-keys mentionable-contacts (keys mentionable-users))) (merge mentionable-users (select-keys mentionable-contacts (keys mentionable-users)))
:else mentionable-users))) :else
mentionable-users)))
(def ending-chars "[\\s\\.,;:]") (def ending-chars "[\\s\\.,;:]")
(def ending-chars-regex (re-pattern ending-chars)) (def ending-chars-regex (re-pattern ending-chars))
(def word-regex (re-pattern (str "^[\\w\\d]*" ending-chars "|^[\\S]*$"))) (def word-regex (re-pattern (str "^[\\w\\d]*" ending-chars "|^[\\S]*$")))
(defn mentioned? (defn mentioned?
[{:keys [alias name]} text] [{:keys [primary-name secondary-name]} text]
(let [lcase-name (string/lower-case name) (let [lcase-fname (string/lower-case primary-name)
lcase-alias (string/lower-case alias) lcase-sname (when secondary-name (string/lower-case secondary-name))
regex (re-pattern regex (re-pattern
(string/join (string/join
"|" "|"
[(str "^" lcase-name ending-chars) [(str "^" lcase-fname ending-chars)
(str "^" lcase-name "$") (str "^" lcase-fname "$")
(str "^" lcase-alias ending-chars) (str "^" lcase-sname ending-chars)
(str "^" lcase-alias "$")])) (str "^" lcase-sname "$")]))
lcase-text (string/lower-case text)] lcase-text (string/lower-case text)]
(re-find regex lcase-text))) (re-find regex lcase-text)))
(defn get-user-suggestions (defn get-user-suggestions
[users searched-text] [users searched-text]
(reduce (reduce
(fn [acc [k {:keys [alias name nickname searchable-phrases] :as user}]] (fn [acc [k {:keys [primary-name secondary-name searchable-phrases] :as user}]]
(if-let [match (if-let [match
(if (seq searchable-phrases) (if (seq searchable-phrases)
(when (some (when (some
@ -305,27 +276,23 @@
(string/lower-case s) (string/lower-case s)
searched-text)) searched-text))
searchable-phrases) searchable-phrases)
(or name alias)) (or primary-name secondary-name))
(cond (cond
(and nickname (and primary-name
(string/starts-with? (string/starts-with?
(string/lower-case nickname) (string/lower-case primary-name)
searched-text)) searched-text))
(or name alias) (or primary-name secondary-name)
(and alias (and secondary-name
(string/starts-with? (string/starts-with?
(string/lower-case alias) (string/lower-case secondary-name)
searched-text)) searched-text))
alias secondary-name))]
(string/starts-with?
(string/lower-case name)
searched-text)
name))]
(assoc acc (assoc acc
k k
(assoc user (assoc user
:key k
:match match :match match
:searched-text searched-text)) :searched-text searched-text))
acc)) acc))
@ -642,7 +609,7 @@
(assoc-in [:chats/mention-suggestions chat-id] mentions))})))) (assoc-in [:chats/mention-suggestions chat-id] mentions))}))))
(defn new-input-text-with-mention (defn new-input-text-with-mention
[{:keys [db]} {:keys [name]}] [{:keys [db]} {:keys [primary-name]}]
(let [chat-id (:current-chat-id db) (let [chat-id (:current-chat-id db)
text (get-in db [:chat/inputs chat-id :input-text]) text (get-in db [:chat/inputs chat-id :input-text])
{:keys [mention-end at-sign-idx]} {:keys [mention-end at-sign-idx]}
@ -652,7 +619,7 @@
new-input-text-with-mention) new-input-text-with-mention)
(string/join (string/join
[(subs text 0 (inc at-sign-idx)) [(subs text 0 (inc at-sign-idx))
name primary-name
(let [next-char (get text mention-end)] (let [next-char (get text mention-end)]
(when (or (not next-char) (when (or (not next-char)
(and next-char (and next-char

View File

@ -9,6 +9,7 @@
"@helpinghand.eth"] "@helpinghand.eth"]
[:text [:text
" "]]) " "]])
(def ->info-expected (def ->info-expected
{:at-sign-idx 2 {:at-sign-idx 2
:mention-end 19 :mention-end 19
@ -75,17 +76,16 @@
(test/deftest test-replace-mentions (test/deftest test-replace-mentions
(let [users {"User Number One" (let [users {"User Number One"
{:name "User Number One" {:primary-name "User Number One"
:alias "User Number One" :public-key "0xpk1"}
:public-key "0xpk1"}
"User Number Two" "User Number Two"
{:name "user2" {:primary-name "user2"
:alias "User Number Two" :secondary-name "User Number Two"
:public-key "0xpk2"} :public-key "0xpk2"}
"User Number Three" "User Number Three"
{:name "user3" {:primary-name "user3"
:alias "User Number Three" :secondary-name "User Number Three"
:public-key "0xpk3"}}] :public-key "0xpk3"}}]
(test/testing "empty string" (test/testing "empty string"
(let [text "" (let [text ""
result (mentions/replace-mentions text users)] result (mentions/replace-mentions text users)]

View File

@ -2,10 +2,8 @@
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.chat.models.loading :as chat.loading] [status-im.chat.models.loading :as chat.loading]
[status-im.chat.models.mentions :as mentions]
[status-im.data-store.messages :as data-store.messages] [status-im.data-store.messages :as data-store.messages]
[status-im.transport.message.protocol :as protocol] [status-im.transport.message.protocol :as protocol]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im2.contexts.chat.messages.delete-message.events :as delete-message] [status-im2.contexts.chat.messages.delete-message.events :as delete-message]
@ -34,26 +32,6 @@
;; TODO this is too expensive, probably we could mark message somehow and just hide it in the UI ;; TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
(message-list/rebuild-message-list {:db (update-in db [:messages chat-id] dissoc message-id)} chat-id)) (message-list/rebuild-message-list {:db (update-in db [:messages chat-id] dissoc message-id)} chat-id))
(rf/defn add-senders-to-chat-users
{:events [:chat/add-senders-to-chat-users]}
[{:keys [db]} messages]
(reduce (fn [acc {:keys [chat-id alias name identicon from]}]
(let [alias (if (string/blank? alias)
(gfycat/generate-gfy from)
alias)]
(update-in acc
[:db :chats chat-id :users]
assoc
from
(mentions/add-searchable-phrases
{:alias alias
:name (or name alias)
:identicon identicon
:public-key from
:nickname (get-in db [:contacts/contacts from :nickname])}))))
{:db db}
messages))
(defn add-message (defn add-message
[{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value] [{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
(let [{:keys [replace from clock-value] :as message} (let [{:keys [replace from clock-value] :as message}
@ -118,7 +96,7 @@
(defn receive-many (defn receive-many
[{:keys [db]} ^js response-js] [{:keys [db]} ^js response-js]
(let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10)) (let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10))
{:keys [db senders]} {:keys [db]}
(reduce reduce-js-messages (reduce reduce-js-messages
{:db db :chats #{} :senders {} :transactions #{}} {:db db :chats #{} :senders {} :transactions #{}}
messages-js)] messages-js)]
@ -128,9 +106,7 @@
:utils/dispatch-later :utils/dispatch-later
(concat [{:ms 20 :dispatch [:process-response response-js]}] (concat [{:ms 20 :dispatch [:process-response response-js]}]
(when (and (:current-chat-id db) (= "active" (:app-state db))) (when (and (:current-chat-id db) (= "active" (:app-state db)))
[{:ms 100 :dispatch [:chat/mark-all-as-read (:current-chat-id db)]}]) [{:ms 100 :dispatch [:chat/mark-all-as-read (:current-chat-id db)]}]))}))
(when (seq senders)
[{:ms 100 :dispatch [:chat/add-senders-to-chat-users (vals senders)]}]))}))
(rf/defn update-db-message-status (rf/defn update-db-message-status
[{:keys [db] :as cofx} chat-id message-id status] [{:keys [db] :as cofx} chat-id message-id status]

View File

@ -3,14 +3,14 @@
[status-im2.contexts.chat.messages.list.events :as message-list] [status-im2.contexts.chat.messages.list.events :as message-list]
[status-im.contact.db :as contact.db] [status-im.contact.db :as contact.db]
[status-im.data-store.chats :as chats-store] [status-im.data-store.chats :as chats-store]
[status-im.data-store.contacts :as contacts-store] [status-im2.contexts.contacts.events :as contacts-store]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im2.contexts.activity-center.events :as activity-center] [status-im2.contexts.activity-center.events :as activity-center]
[status-im2.navigation.events :as navigation])) [status-im2.navigation.events :as navigation]))
(rf/defn clean-up-chat (rf/defn clean-up-chat
[{:keys [db] :as cofx} [{:keys [db]}
public-key public-key
{:keys [chat-id {:keys [chat-id
unviewed-messages-count unviewed-messages-count
@ -35,18 +35,18 @@
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))})) (message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
(rf/defn contact-blocked (rf/defn contact-blocked
{:events [::contact-blocked]} {:events [:contacts/blocked]}
[{:keys [db] :as cofx} {:keys [public-key]} chats] [{:keys [db] :as cofx} {:keys [public-key]} chats-js]
(let [fxs (when chats (let [fxs (when chats-js
(map #(->> (chats-store/<-rpc %) (map #(->> (chats-store/<-rpc %)
(clean-up-chat public-key)) (clean-up-chat public-key))
(types/js->clj chats)))] (types/js->clj chats-js)))]
(apply rf/merge (apply rf/merge
cofx cofx
{:db (-> db {:db (-> db
(update :chats dissoc public-key) (update :chats dissoc public-key)
(update :chats-home-list disj public-key) (update :chats-home-list disj public-key)
(assoc-in [:contacts/contacts public-key :added] false)) (assoc-in [:contacts/contacts public-key :added?] false))
:dispatch [:shell/close-switcher-card public-key] :dispatch [:shell/close-switcher-card public-key]
:clear-message-notifications :clear-message-notifications
[[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]} [[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
@ -59,19 +59,15 @@
(let [contact (-> (contact.db/public-key->contact (let [contact (-> (contact.db/public-key->contact
(:contacts/contacts db) (:contacts/contacts db)
public-key) public-key)
(assoc :blocked true (assoc :blocked? true
:added false)) :added? false))
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))] from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))]
(rf/merge cofx (rf/merge cofx
{:db (-> db {:db (assoc-in db [:contacts/contacts public-key] contact)}
;; add the contact to blocked contacts
(update :contacts/blocked (fnil conj #{}) public-key)
;; update the contact in contacts list
(assoc-in [:contacts/contacts public-key] contact))}
(contacts-store/block (contacts-store/block
public-key public-key
(fn [^js block-contact] (fn [^js block-contact]
(re-frame/dispatch [::contact-blocked contact (.-chats block-contact)]) (re-frame/dispatch [:contacts/blocked contact (.-chats block-contact)])
(re-frame/dispatch [:sanitize-messages-and-process-response block-contact]) (re-frame/dispatch [:sanitize-messages-and-process-response block-contact])
(re-frame/dispatch [:hide-popover]))) (re-frame/dispatch [:hide-popover])))
;; reset navigation to avoid going back to non existing one to one chat ;; reset navigation to avoid going back to non existing one to one chat
@ -80,13 +76,11 @@
(navigation/navigate-back))))) (navigation/navigate-back)))))
(rf/defn contact-unblocked (rf/defn contact-unblocked
{:events [::contact-unblocked]} {:events [:contacts/unblocked]}
[{:keys [db]} contact-id] [{:keys [db]} contact-id]
(let [contact (-> (get-in db [:contacts/contacts contact-id]) (let [contact (-> (get-in db [:contacts/contacts contact-id])
(assoc :blocked false))] (assoc :blocked? false))]
{:db (-> db {:db (assoc-in db [:contacts/contacts contact-id] contact)}))
(update :contacts/blocked disj contact-id)
(assoc-in [:contacts/contacts contact-id] contact))}))
(rf/defn unblock-contact (rf/defn unblock-contact
{:events [:contact.ui/unblock-contact-pressed]} {:events [:contact.ui/unblock-contact-pressed]}
@ -94,4 +88,4 @@
(contacts-store/unblock (contacts-store/unblock
cofx cofx
contact-id contact-id
#(re-frame/dispatch [::contact-unblocked contact-id]))) #(re-frame/dispatch [:contacts/unblocked contact-id])))

View File

@ -1,6 +1,6 @@
(ns status-im.contact.chat (ns status-im.contact.chat
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.contact.core :as contact] [status-im2.contexts.contacts.events :as contact]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im2.navigation.events :as navigation])) [status-im2.navigation.events :as navigation]))

View File

@ -1,86 +1,6 @@
(ns status-im.contact.core (ns status-im.contact.core
(:require [re-frame.core :as re-frame] (:require [utils.re-frame :as rf]
[status-im2.constants :as constants] [status-im2.navigation.events :as navigation]))
[status-im.contact.block :as contact.block]
[status-im.contact.db :as contact.db]
[status-im.data-store.contacts :as contacts-store]
[utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]))
(defn build-contact
[{{:keys [multiaccount]
:contacts/keys [contacts]}
:db} public-key]
(cond-> (contact.db/public-key->contact contacts public-key)
(= public-key (:public-key multiaccount))
(assoc :name (:name multiaccount))))
(rf/defn ensure-contacts
[{:keys [db]} contacts chats]
(let [events
(reduce
(fn [acc {:keys [public-key] :as contact}]
(let [added (:added contact)
was-added (contact.db/added? db public-key)
blocked (:blocked contact)
was-blocked (contact.db/blocked? db public-key)]
(cond-> acc
(and (not (:has-added-us contact))
(= constants/contact-request-state-none (:contact-request-state contact)))
(conj [:activity-center/remove-pending-contact-request (:public-key contact)])
(and was-added (not added))
(conj nil)
(and blocked (not was-blocked))
(conj [::contact.block/contact-blocked contact chats]))))
[[:chat/offload-messages constants/timeline-chat-id]
[:activity-center.notifications/fetch-unread-count]]
contacts)]
(merge
{:db (update db
:contacts/contacts
#(reduce (fn [acc {:keys [public-key] :as contact}]
(-> acc
(update public-key merge contact)
(assoc-in [public-key :nickname] (:nickname contact))))
%
contacts))}
(when (> (count events) 1)
{:dispatch-n events}))))
(rf/defn add-contact
"Add a contact and set pending to false"
{:events [:contact.ui/add-contact-pressed]}
[{:keys [db] :as cofx} public-key nickname ens-name]
(when (not= (get-in db [:multiaccount :public-key]) public-key)
(contacts-store/add
cofx
public-key
nickname
ens-name
#(do
(re-frame/dispatch [:sanitize-messages-and-process-response %])
(re-frame/dispatch [:chat/offload-messages constants/timeline-chat-id])))))
(rf/defn remove-contact
"Remove a contact from current account's contact list"
{:events [:contact.ui/remove-contact-pressed]}
[{:keys [db]} {:keys [public-key]}]
{:db (-> db
(assoc-in [:contacts/contacts public-key :added] false)
(assoc-in [:contacts/contacts public-key :contact-request-state]
constants/contact-request-state-none))
:json-rpc/call [{:method "wakuext_retractContactRequest"
:params [{:id public-key}]
:on-success #(log/debug "contact removed successfully")}]
:dispatch [:chat/offload-messages constants/timeline-chat-id]})
(rf/defn initialize-contacts
[cofx]
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))
(rf/defn open-contact-toggle-list (rf/defn open-contact-toggle-list
{:events [:contact.ui/start-group-chat-pressed]} {:events [:contact.ui/start-group-chat-pressed]}
@ -90,18 +10,3 @@
:group/selected-contacts #{} :group/selected-contacts #{}
:new-chat-name "")} :new-chat-name "")}
(navigation/navigate-to-cofx :contact-toggle-list nil))) (navigation/navigate-to-cofx :contact-toggle-list nil)))
(rf/defn update-nickname
{:events [:contacts/update-nickname]}
[{:keys [db] :as cofx} public-key nickname]
(rf/merge cofx
(contacts-store/set-nickname
public-key
nickname
#(re-frame/dispatch [:sanitize-messages-and-process-response %]))
(navigation/navigate-back)))
(rf/defn set-search-query
{:events [:contacts/set-search-query]}
[{:keys [db] :as cofx} value]
{:db (assoc db :contacts/search-query value)})

View File

@ -1,2 +0,0 @@
(ns status-im.contact.core-test)

View File

@ -3,17 +3,17 @@
[clojure.string :as string] [clojure.string :as string]
[status-im2.constants :as constants] [status-im2.constants :as constants]
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon])) [status-im.utils.identicon :as identicon]))
(defn public-key->new-contact (defn public-key->new-contact
[public-key] [public-key]
(let [alias (gfycat/generate-gfy public-key)] (let [alias (gfycat/generate-gfy public-key)]
{:alias alias {:alias alias
:name alias :name alias
:identicon (identicon/identicon public-key) :primary-name alias
:public-key public-key})) :identicon (identicon/identicon public-key)
:public-key public-key}))
(defn public-key-and-ens-name->new-contact (defn public-key-and-ens-name->new-contact
[public-key ens-name] [public-key ens-name]
@ -43,84 +43,45 @@
(defn sort-contacts (defn sort-contacts
[contacts] [contacts]
(sort (fn [c1 c2] (sort (fn [c1 c2]
(let [name1 (first (:two-names c1)) (let [name1 (:primary-name c1)
name2 (first (:two-names c2))] name2 (:primary-name c2)]
(compare (string/lower-case name1) (when (and name1 name2)
(string/lower-case name2)))) (compare (string/lower-case name1)
(string/lower-case name2)))))
(vals contacts))) (vals contacts)))
(defn filter-dapps
[v dev-mode?]
(remove #(when-not dev-mode? (true? (:developer? %))) v))
(defn filter-group-contacts
[group-contacts contacts]
(let [group-contacts' (into #{} group-contacts)]
(filter #(group-contacts' (:public-key %)) contacts)))
(defn query-chat-contacts (defn query-chat-contacts
[{:keys [contacts]} all-contacts query-fn] [{:keys [contacts]} all-contacts query-fn]
(let [participant-set (into #{} (filter identity) contacts)] (let [participant-set (into #{} (filter identity) contacts)]
(query-fn (comp participant-set :public-key) (vals all-contacts)))) (query-fn (comp participant-set :public-key) (vals all-contacts))))
(defn get-all-contacts-in-group-chat (defn get-all-contacts-in-group-chat
[members admins contacts {:keys [public-key] :as current-account}] [members admins contacts {:keys [public-key preferred-name name] :as current-account}]
(let [current-contact (some-> (let [current-contact (some->
current-account current-account
(select-keys [:name :preferred-name :public-key :identicon :images]) (select-keys [:name :preferred-name :public-key :identicon :images])
(set/rename-keys {:name :alias (set/rename-keys {:name :alias :preferred-name :name})
:preferred-name :name})) (assoc :primary-name (or preferred-name name)))
all-contacts (cond-> contacts all-contacts (cond-> contacts
current-contact current-contact
(assoc public-key current-contact))] (assoc public-key current-contact))]
(->> members (->> members
(map #(or (get all-contacts %) (map #(or (get all-contacts %)
(public-key->new-contact %))) (public-key->new-contact %)))
(sort-by (comp string/lower-case #(or (:name %) (:alias %)))) (sort-by (comp string/lower-case #(or (:primary-name %) (:name %) (:alias %))))
(map #(if (get admins (:public-key %)) (map #(if (get admins (:public-key %))
(assoc % :admin? true) (assoc % :admin? true)
%))))) %)))))
(defn contact-exists?
[db public-key]
(get-in db [:contacts/contacts public-key]))
(defn added?
([{:keys [contact-request-state]}]
(or (= constants/contact-request-state-mutual contact-request-state)
(= constants/contact-request-state-sent contact-request-state)))
([db public-key]
(added? (get-in db [:contacts/contacts public-key]))))
(defn blocked?
([contact]
(:blocked contact))
([db public-key]
(blocked? (get-in db [:contacts/contacts public-key]))))
(defn active?
"Checks that we are mutual contacts"
([contact]
(and (= constants/contact-request-state-mutual
(:contact-request-state contact))
(not (:blocked contact))))
([db public-key]
(active? (get-in db [:contacts/contacts public-key]))))
(defn enrich-contact (defn enrich-contact
([contact] (enrich-contact contact nil nil)) ([contact] (enrich-contact contact nil nil))
([{:keys [public-key] :as contact} setting own-public-key] ([{:keys [public-key] :as contact} setting own-public-key]
(cond-> (-> contact (cond-> contact
(dissoc :ens-verified-at :ens-verification-retries)
(assoc :blocked? (:blocked contact)
:active? (active? contact)
:added? (added? contact))
(multiaccounts/contact-with-names))
(and setting (and setting
(not= public-key own-public-key) (not= public-key own-public-key)
(or (= setting constants/profile-pictures-visibility-none) (or (= setting constants/profile-pictures-visibility-none)
(and (= setting constants/profile-pictures-visibility-contacts-only) (and (= setting constants/profile-pictures-visibility-contacts-only)
(not (added? contact))))) (not (:added? contact)))))
(dissoc :images)))) (dissoc :images))))
(defn enrich-contacts (defn enrich-contacts
@ -134,15 +95,8 @@
(defn get-blocked-contacts (defn get-blocked-contacts
[contacts] [contacts]
(reduce (fn [acc {:keys [public-key] :as contact}] (reduce (fn [acc {:keys [public-key] :as contact}]
(if (:blocked contact) (if (:blocked? contact)
(conj acc public-key) (conj acc public-key)
acc)) acc))
#{} #{}
contacts)) contacts))
(defn get-active-contacts
[contacts]
(->> contacts
(filter (fn [[_ contact]]
(active? contact)))
sort-contacts))

View File

@ -20,6 +20,7 @@
{"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f" {"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
{:last-updated 0 {:last-updated 0
:name "User B" :name "User B"
:primary-name "User B"
:identicon "photo1" :identicon "photo1"
:last-online 0 :last-online 0
:public-key :public-key
@ -28,6 +29,7 @@
{:last-updated 0 {:last-updated 0
:signed-up? true :signed-up? true
:sharing-usage-data? false :sharing-usage-data? false
:primary-name "User A"
:name "User A" :name "User A"
:identicon "photo2" :identicon "photo2"
:public-key :public-key
@ -39,17 +41,20 @@
contacts contacts
current-multiaccount) current-multiaccount)
[{:name "generated" [{:name "generated"
:primary-name "generated"
:identicon "generated" :identicon "generated"
:alias "generated" :alias "generated"
:admin? true :admin? true
:public-key :public-key
"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"} "0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
{:alias "User A" {:alias "User A"
:primary-name "User A"
:identicon "photo2" :identicon "photo2"
:public-key :public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"} "0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
{:last-updated 0 {:last-updated 0
:name "User B" :name "User B"
:primary-name "User B"
:identicon "photo1" :identicon "photo1"
:last-online 0 :last-online 0
:public-key :public-key

View File

@ -1,71 +0,0 @@
(ns status-im.data-store.contacts
(:require [clojure.set :as set]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
(defn <-rpc
[contact]
(-> contact
(set/rename-keys
{:id :public-key
:ensVerifiedAt :ens-verified-at
:compressedKey :compressed-key
:displayName :display-name
:ensVerified :ens-verified
:ensVerificationRetries :ens-verification-retries
:hasAddedUs :has-added-us
:contactRequestState :contact-request-state
:lastENSClockValue :last-ens-clock-value
:lastUpdated :last-updated
:localNickname :nickname})
(assoc :mutual?
(and (:added contact)
(:hasAddedUs contact)))))
(rf/defn fetch-contacts-rpc
[_ on-success]
{:json-rpc/call [{:method "wakuext_contacts"
:params []
:on-success #(on-success (map <-rpc %))
:on-error #(log/error "failed to fetch contacts" %)}]})
(rf/defn add
[_ public-key nickname ens-name on-success]
{:json-rpc/call [{:method "wakuext_addContact"
:params [{:id public-key :nickname nickname :ensName ens-name}]
:js-response true
:on-success #(do
(log/info "saved contact" public-key "successfuly")
(when on-success
(on-success %)))
:on-error #(log/error "failed to add contact" public-key %)}]})
(rf/defn set-nickname
[_ public-key nickname on-success]
{:json-rpc/call [{:method "wakuext_setContactLocalNickname"
:params [{:id public-key :nickname nickname}]
:js-response true
:on-success #(do
(log/debug "set contact nickname" public-key "successfuly" nickname)
(when on-success
(on-success %)))
:on-error #(log/error "failed to set contact nickname "
public-key
nickname
%)}]})
(rf/defn block
[_ contact-id on-success]
{:json-rpc/call [{:method "wakuext_blockContact"
:params [contact-id]
:js-response true
:on-success on-success
:on-error #(log/error "failed to block contact" % contact-id)}]})
(rf/defn unblock
[_ contact-id on-success]
{:json-rpc/call [{:method "wakuext_unblockContact"
:params [contact-id]
:on-success on-success
:js-response true
:on-error #(log/error "failed to unblock contact" % contact-id)}]})

View File

@ -1,22 +0,0 @@
(ns status-im.data-store.contacts-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.data-store.contacts :as c]))
(deftest contact<-rpc
(let [contact {:id "pk"
:address "address"
:name "name"
:displayName "display-name"
:compressedKey "compressed-key"
:identicon "identicon"
:lastUpdated 1}
expected-contact {:public-key "pk"
:address "address"
:compressed-key "compressed-key"
:display-name "display-name"
:mutual? nil
:name "name"
:identicon "identicon"
:last-updated 1}]
(testing "<-rpc"
(is (= expected-contact (c/<-rpc contact))))))

View File

@ -161,10 +161,10 @@
(rf/defn on-going-in-background (rf/defn on-going-in-background
[{:keys [db now]}] [{:keys [db now]}]
{:db (assoc db :app-in-background-since now) {:db (assoc db :app-in-background-since now)})
;; event not implemented ;; event not implemented
;; :dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]] ;; :dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]]
})
(rf/defn app-state-change (rf/defn app-state-change
{:events [:app-state-change]} {:events [:app-state-change]}

View File

@ -338,7 +338,7 @@
(rf-test/wait-for (rf-test/wait-for
[:contacts/contact-built] [:contacts/contact-built]
(let [contact @(rf/subscribe [:contacts/current-contact])] (let [contact @(rf/subscribe [:contacts/current-contact])]
(is (= three-words-name (:three-words-name (:names contact))))) (is (= three-words-name (:primary-name contact))))
(logout!) (logout!)
(rf-test/wait-for [::logout/logout-method] (rf-test/wait-for [::logout/logout-method]
(assert-logout)))))))))) (assert-logout))))))))))

View File

@ -3,7 +3,6 @@
[quo.platform :as platform] [quo.platform :as platform]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im2.common.bottom-sheet.events :as bottom-sheet] [status-im2.common.bottom-sheet.events :as bottom-sheet]
[status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as native-module] [status-im.native-module.core :as native-module]
[status-im.theme.core :as theme] [status-im.theme.core :as theme]
@ -12,11 +11,11 @@
[status-im2.constants :as constants] [status-im2.constants :as constants]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.utils.utils :as utils]
[status-im2.setup.hot-reload :as hot-reload] [status-im2.setup.hot-reload :as hot-reload]
[status-im2.common.theme.core :as utils.theme] [status-im2.common.theme.core :as utils.theme]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im2.contexts.shell.animation :as shell.animation])) [status-im2.contexts.shell.animation :as shell.animation]
[status-im.contact.db :as contact.db]))
;; validate that the given mnemonic was generated from Status Dictionary ;; validate that the given mnemonic was generated from Status Dictionary
(re-frame/reg-fx (re-frame/reg-fx
@ -24,47 +23,6 @@
(fn [[passphrase callback]] (fn [[passphrase callback]]
(native-module/validate-mnemonic passphrase callback))) (native-module/validate-mnemonic passphrase callback)))
(defn contact-names
"Returns map of all existing names for contact"
[{:keys [name
display-name
preferred-name
alias
public-key
ens-verified
nickname]}]
(let [ens-name (or preferred-name
name)]
(cond-> {:nickname nickname
:display-name display-name
:three-words-name (or alias (gfycat/generate-gfy public-key))}
;; Preferred name is our own otherwise we make sure it's verified
(or preferred-name (and ens-verified name))
(assoc :ens-name (or (stateofus/username ens-name) ens-name)))))
(defn contact-two-names
"Returns vector of two names in next order nickname, ens name, display-name, three word name, public key"
[{:keys [names
compressed-key
public-key]
:as contact} public-key?]
(let [{:keys [nickname
ens-name
display-name
three-words-name]}
(or names (contact-names contact))
non-empty-names (remove string/blank? [nickname ens-name display-name three-words-name])]
(if (> (count non-empty-names) 1)
(vec (take 2 non-empty-names))
[(first non-empty-names)
(when public-key? (utils/get-shortened-address (or compressed-key public-key)))])))
(defn contact-with-names
"Returns contact with :names map "
[contact]
(let [contact' (assoc contact :names (contact-names contact))]
(assoc contact' :two-names (contact-two-names contact' true))))
(defn displayed-name (defn displayed-name
"Use preferred name, display-name, name or alias in that order" "Use preferred name, display-name, name or alias in that order"
[{:keys [name display-name preferred-name alias public-key ens-verified]}] [{:keys [name display-name preferred-name alias public-key ens-verified]}]
@ -74,14 +32,13 @@
name)] name)]
;; Preferred name is our own otherwise we make sure it's verified ;; Preferred name is our own otherwise we make sure it's verified
(if (or preferred-name (and ens-verified name)) (if (or preferred-name (and ens-verified name))
(let [username (stateofus/username ens-name)] ens-name
(or username ens-name))
(or display-name alias (gfycat/generate-gfy public-key))))) (or display-name alias (gfycat/generate-gfy public-key)))))
(defn contact-by-identity (defn contact-by-identity
[contacts identity] [contacts identity]
(or (get contacts identity) (or (get contacts identity)
(contact-with-names {:public-key identity}))) (contact.db/public-key->new-contact identity)))
(defn contact-two-names-by-identity (defn contact-two-names-by-identity
[contact current-multiaccount identity] [contact current-multiaccount identity]
@ -89,7 +46,7 @@
(if me? (if me?
[(or (:preferred-name current-multiaccount) [(or (:preferred-name current-multiaccount)
(gfycat/generate-gfy identity))] (gfycat/generate-gfy identity))]
(contact-two-names contact false)))) [(:primary-name contact) (:secondary-name contact)])))
(def photo-quality-thumbnail :thumbnail) (def photo-quality-thumbnail :thumbnail)
(def photo-quality-large :large) (def photo-quality-large :large)

View File

@ -1,99 +0,0 @@
(ns status-im.multiaccounts.core-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.multiaccounts.core :as ma]))
(def compressed-key "zQsomething")
(def short-compressed-key "zQsome…ing")
(def public-key
"0x0461f576da67dc0bca9888cdb4cb28c80285b756b324109da94a081585ed6f007cf00afede6b3ee5638593674fee100b590318fc7bdb0054b8dd9445acea216ad2")
(def short-public-key "0x0461…ad2")
(def random-name "Studious Gold Mustang")
(def override-random-name (str "override" random-name))
(def nickname "nickname")
(def override-nickname (str nickname "override"))
(def display-name "display-name")
(def override-display-name (str display-name "override"))
(def ens-name "jakubgs.eth")
(def formatted-ens (str "@" ens-name))
(def override-ens-name (str "override" ens-name))
(def contact
{:nickname nickname
:name ens-name
:ens-verified true
:compressed-key compressed-key
:public-key public-key
:display-name display-name})
(deftest contact-two-names-test
(testing "names is nil"
(testing "nickname has precedence"
(is
(= [nickname ens-name]
(ma/contact-two-names contact public-key))))
(testing "ens name is second option"
(is
(= [ens-name display-name]
(ma/contact-two-names
(dissoc contact :nickname)
public-key))))
(testing "ens name is second option but not verified"
(is
(= [display-name random-name]
(ma/contact-two-names
(dissoc contact :nickname :ens-verified)
public-key))))
(testing "display name is third option"
(is
(= [display-name random-name]
(ma/contact-two-names
(dissoc contact :nickname :name)
public-key))))
(testing "3 random words is fallback"
(is
(= [random-name short-compressed-key]
(ma/contact-two-names
(dissoc contact
:nickname
:name
:display-name)
public-key)))))
(testing "public-key is the least favorite"
(is
(= [random-name short-public-key]
(ma/contact-two-names
(dissoc contact
:nickname
:name
:compressed-key
:display-name)
public-key))))
(testing "names is provided"
(let [names {:nickname override-nickname
:display-name override-display-name
:three-words-name override-random-name
:ens-name override-ens-name}
contact-with-names (assoc contact :names names)]
(testing "nickname has precedence"
(is
(= [override-nickname override-ens-name]
(ma/contact-two-names contact-with-names public-key))))
(testing "ens name is second option"
(is
(= [override-ens-name override-display-name]
(ma/contact-two-names
(update contact-with-names :names dissoc :nickname)
public-key))))
(testing "display name is third option"
(is
(= [override-display-name override-random-name]
(ma/contact-two-names
(update contact-with-names :names dissoc :nickname :ens-name)
public-key))))
(testing "3 random words is fallback"
(is
(= [override-random-name short-compressed-key]
(ma/contact-two-names
(update contact-with-names :names dissoc :nickname :ens-name :display-name)
public-key)))))))

View File

@ -7,7 +7,7 @@
:name "Darkviolet Lightgreen Halcyon" :name "Darkviolet Lightgreen Halcyon"
:identicon :identicon
"data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX///+M2KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdPOdBAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5UBARL8TK8AAAAASUVORK5CYII=" "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX///+M2KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdPOdBAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5UBARL8TK8AAAAASUVORK5CYII="
:added true :added? true
:last-online 0 :last-online 0
:public-key :public-key
"0x04d6e56a475cd35f512d6ce0bf76c2c2af435c85ff48c2b9bdefd129f620e051a436f50961eae5717b2a750e59c3f5b60647d927da46d0b8b11621640b5678fc24"} "0x04d6e56a475cd35f512d6ce0bf76c2c2af435c85ff48c2b9bdefd129f620e051a436f50961eae5717b2a750e59c3f5b60647d927da46d0b8b11621640b5678fc24"}
@ -16,7 +16,7 @@
:name "rv" :name "rv"
:identicon :identicon
"data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////VjNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwYzy6AAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6IYA4bRtf+EAAAAASUVORK5CYII=" "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////VjNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwYzy6AAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6IYA4bRtf+EAAAAASUVORK5CYII="
:added true :added? true
:last-online 0 :last-online 0
:public-key :public-key
"0x043ae31038ff45a31b096a91d3f8290e079366fbbae76a00fbbd349cd0e5b8d7598965d206772ec4504f68908649a08383cdc51a52cdae5e9ccc744ace4d37020f"}]) "0x043ae31038ff45a31b096a91d3f8290e079366fbbae76a00fbbd349cd0e5b8d7598965d206772ec4504f68908649a08383cdc51a52cdae5e9ccc744ace4d37020f"}])

View File

@ -2,7 +2,7 @@
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.data-store.contacts :as data-store.contacts] [status-im2.contexts.contacts.events :as data-store.contacts]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[utils.re-frame :as rf] [utils.re-frame :as rf]
@ -101,8 +101,9 @@
{:db (-> db {:db (-> db
(assoc :contacts/identity identity) (assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name)) (assoc :contacts/ens-name ens-name))
:json-rpc/call [{:method "wakuext_buildContact" :json-rpc/call [{:method "wakuext_buildContact"
:params [identity] :params [identity]
:on-success #(rf/dispatch [:contacts/contact-built :js-response true
identity :on-success #(rf/dispatch [:contacts/contact-built
(data-store.contacts/<-rpc %)])}]}))) identity
(data-store.contacts/<-rpc-js %)])}]})))

View File

@ -7,10 +7,9 @@
[status-im.chat.models.reactions :as models.reactions] [status-im.chat.models.reactions :as models.reactions]
[status-im.communities.core :as models.communities] [status-im.communities.core :as models.communities]
[status-im2.constants :as constants] [status-im2.constants :as constants]
[status-im.contact.core :as models.contact] [status-im2.contexts.contacts.events :as models.contact]
[status-im.data-store.activities :as data-store.activities] [status-im.data-store.activities :as data-store.activities]
[status-im.data-store.chats :as data-store.chats] [status-im.data-store.chats :as data-store.chats]
[status-im.data-store.contacts :as data-store.contacts]
[status-im.data-store.invitations :as data-store.invitations] [status-im.data-store.invitations :as data-store.invitations]
[status-im.data-store.messages :as data-store.messages] [status-im.data-store.messages :as data-store.messages]
[status-im.data-store.reactions :as data-store.reactions] [status-im.data-store.reactions :as data-store.reactions]
@ -84,15 +83,7 @@
(models.pairing/handle-installations installations-clj))) (models.pairing/handle-installations installations-clj)))
(seq contacts) (seq contacts)
(let [contacts-clj (types/js->clj contacts) (models.contact/process-js-contacts cofx response-js)
^js chats (.-chatsForContacts response-js)]
(js-delete response-js "contacts")
(js-delete response-js "chatsForContacts")
(rf/merge cofx
(process-next response-js sync-handler)
(models.contact/ensure-contacts
(map data-store.contacts/<-rpc contacts-clj)
chats)))
(seq communities) (seq communities)
(let [communities-clj (types/js->clj communities)] (let [communities-clj (types/js->clj communities)]

View File

@ -29,13 +29,12 @@
(defn- render-row (defn- render-row
[row] [row]
(let [first-name (first (multiaccounts/contact-two-names row false))] [quo/list-item
[quo/list-item {:title (:primary-name row)
{:title first-name :icon [chat-icon/contact-icon-contacts-tab
:icon [chat-icon/contact-icon-contacts-tab (multiaccounts/displayed-photo row)]
(multiaccounts/displayed-photo row)] :on-press #(re-frame/dispatch [:chat.ui/start-chat
:on-press #(re-frame/dispatch [:chat.ui/start-chat (:public-key row)])}])
(:public-key row)])}]))
(defn- icon-wrapper (defn- icon-wrapper
[color icon] [color icon]

View File

@ -1,41 +1,38 @@
(ns status-im.ui.screens.chat.utils (ns status-im.ui.screens.chat.utils
(:require [quo.design-system.colors :as colors] (:require [quo.design-system.colors :as colors]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.react :as react]
[status-im.ui.components.react :as react])) [clojure.string :as string]))
(defn format-author-old (defn format-author-old
([contact] (format-author-old contact nil)) ([contact] (format-author-old contact nil))
([{:keys [names] :as contact} {:keys [modal profile? you?]}] ([{:keys [primary-name secondary-name nickname]} {:keys [modal profile? you?]}]
(let [{:keys [nickname ens-name]} names (if (not (string/blank? secondary-name))
[first-name second-name] (multiaccounts/contact-two-names contact false)] [react/nested-text
(if (or nickname ens-name) {:number-of-lines 2
[react/nested-text :style {:color (if modal colors/white-persist colors/blue)
{:number-of-lines 2 :font-size (if profile? 15 13)
:style {:color (if modal colors/white-persist colors/blue) :line-height (if profile? 22 18)
:font-size (if profile? 15 13) :font-weight "500"}}
:line-height (if profile? 22 18) (subs primary-name 0 81)
:font-weight "500"}} (when you?
(subs first-name 0 81) [{:style {:color colors/gray :font-weight "400" :font-size 13}}
(when you? (str " " (i18n/label :t/You))])
[{:style {:color colors/gray :font-weight "400" :font-size 13}} (when nickname
(str " " (i18n/label :t/You))]) [{:style {:color colors/gray :font-weight "400"}}
(when nickname (str " " (subs secondary-name 0 81))])]
[{:style {:color colors/gray :font-weight "400"}} [react/text
(str " " (subs second-name 0 81))])] {:style {:color (if modal colors/white-persist colors/gray)
[react/text :font-size (if profile? 15 12)
{:style {:color (if modal colors/white-persist colors/gray) :line-height (if profile? 22 18)
:font-size (if profile? 15 12) :font-weight "400"}}
:line-height (if profile? 22 18) primary-name])))
:font-weight "400"}}
first-name]))))
(defn format-author (defn format-author
([contact] (format-author contact nil nil)) ([contact] (format-author contact nil nil))
([{:keys [names] :as contact} {:keys [modal profile? you?]} max-length] ([contact {:keys [modal profile? you?]} max-length]
(let [{:keys [nickname ens-name]} names (let [{:keys [primary-name secondary-name]} contact]
[first-name second-name] (multiaccounts/contact-two-names contact false)] (if secondary-name
(if (or nickname ens-name)
[react/nested-text [react/nested-text
{:number-of-lines 2 {:number-of-lines 2
:style {:color (if modal colors/white-persist colors/black) :style {:color (if modal colors/white-persist colors/black)
@ -43,13 +40,12 @@
:line-height (if profile? 22 18) :line-height (if profile? 22 18)
:letter-spacing -0.2 :letter-spacing -0.2
:font-weight "600"}} :font-weight "600"}}
(subs first-name 0 81) (subs primary-name 0 81)
(when you? (when you?
[{:style {:color colors/black-light :font-weight "500" :font-size 13}} [{:style {:color colors/black-light :font-weight "500" :font-size 13}}
(str " " (i18n/label :t/You))]) (str " " (i18n/label :t/You))])
(when nickname [{:style {:color colors/black-light :font-weight "500"}}
[{:style {:color colors/black-light :font-weight "500"}} (str " " (subs secondary-name 0 81))]]
(str " " (subs second-name 0 81))])]
[react/text [react/text
{:style {:color (if modal colors/white-persist colors/black) {:style {:color (if modal colors/white-persist colors/black)
:font-size (if profile? 15 13) :font-size (if profile? 15 13)
@ -57,6 +53,6 @@
:font-weight "600" :font-weight "600"
:letter-spacing -0.2} :letter-spacing -0.2}
:number-of-lines 1} :number-of-lines 1}
(if (and max-length (> (count first-name) max-length)) (if (and max-length (> (count primary-name) max-length))
(str (subs first-name 0 max-length) "...") (str (subs primary-name 0 max-length) "...")
first-name)])))) primary-name)]))))

View File

@ -30,10 +30,10 @@
(defn contacts-list-item (defn contacts-list-item
[{:keys [public-key active] :as contact} _ _ {:keys [selected]}] [{:keys [public-key active] :as contact} _ _ {:keys [selected]}]
(let [[first-name second-name] (multiaccounts/contact-two-names contact true)] (let [{:keys [primary-name secondary-name]} contact]
[quo/list-item [quo/list-item
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:icon [chat-icon.screen/contact-icon-contacts-tab :icon [chat-icon.screen/contact-icon-contacts-tab
(multiaccounts/displayed-photo contact)] (multiaccounts/displayed-photo contact)]
:accessory :checkbox :accessory :checkbox

View File

@ -18,13 +18,13 @@
(rf/dispatch event)) (rf/dispatch event))
(defn member-sheet (defn member-sheet
[first-name {:keys [public-key] :as member} community-id can-kick-users? can-manage-users? admin?] [primary-name {:keys [public-key] :as member} community-id can-kick-users? can-manage-users? admin?]
[:<> [:<>
[quo/list-item [quo/list-item
{:theme :accent {:theme :accent
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)] (multiaccounts/displayed-photo member)]
:title first-name :title primary-name
:subtitle (i18n/label :t/view-profile) :subtitle (i18n/label :t/view-profile)
:accessibility-label :view-chat-details-button :accessibility-label :view-chat-details-button
:chevron true :chevron true
@ -60,11 +60,11 @@
can-manage-users? can-manage-users?
can-kick-users? can-kick-users?
admin?]}] admin?]}]
(let [member (rf/sub [:contacts/contact-by-identity public-key]) (let [member (rf/sub [:contacts/contact-by-identity public-key])
[first-name second-name] (rf/sub [:contacts/contact-two-names-by-identity public-key])] [primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity public-key])]
[quo/list-item [quo/list-item
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:accessibility-label :member-item :accessibility-label :member-item
:icon [chat-icon/profile-photo-plus-dot-view :icon [chat-icon/profile-photo-plus-dot-view
{:public-key public-key {:public-key public-key
@ -74,7 +74,7 @@
{:on-press {:on-press
#(rf/dispatch [:bottom-sheet/show-sheet #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] {:content (fn []
[member-sheet first-name member community-id [member-sheet primary-name member community-id
can-kick-users? can-manage-users? admin?])}]) can-kick-users? can-manage-users? admin?])}])
:type :icon :type :icon
:theme :icon :theme :icon

View File

@ -12,10 +12,10 @@
(defn contacts-list-item (defn contacts-list-item
[{:keys [public-key] :as contact}] [{:keys [public-key] :as contact}]
(let [[first-name second-name] (multiaccounts/contact-two-names contact true)] (let [{:keys [primary-name secondary-name]} contact]
[quo/list-item [quo/list-item
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:icon [chat-icon.screen/profile-photo-plus-dot-view :icon [chat-icon.screen/profile-photo-plus-dot-view
{:public-key public-key {:public-key public-key
:photo-path (multiaccounts/displayed-photo contact)}] :photo-path (multiaccounts/displayed-photo contact)}]

View File

@ -11,7 +11,6 @@
[status-im.ethereum.stateofus :as stateofus] [status-im.ethereum.stateofus :as stateofus]
[status-im.ethereum.tokens :as tokens] [status-im.ethereum.tokens :as tokens]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.react-native.resources :as resources] [status-im.react-native.resources :as resources]
[status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.checkbox.view :as checkbox] [status-im.ui.components.checkbox.view :as checkbox]
@ -20,7 +19,6 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar] [status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui.screens.chat.utils :as chat.utils] [status-im.ui.screens.chat.utils :as chat.utils]
[status-im.ui.screens.profile.components.views :as profile.components] [status-im.ui.screens.profile.components.views :as profile.components]
[status-im.ui.screens.wallet.send.sheets :as sheets] [status-im.ui.screens.wallet.send.sheets :as sheets]
@ -717,13 +715,13 @@
[] []
(views/letsubs [contact-name [:multiaccount/preferred-name]] (views/letsubs [contact-name [:multiaccount/preferred-name]]
(when-not (string/blank? contact-name) (when-not (string/blank? contact-name)
(chat.utils/format-author-old {:names {:ens-name (chat.utils/format-author-old {:primary-name
(str "@" (str "@"
(or (stateofus/username contact-name) (or (stateofus/username contact-name)
contact-name))}})))) contact-name))}))))
(views/defview registered (views/defview registered
[names {:keys [preferred-name] :as account} _ registrations] [names {:keys [preferred-name]} _ registrations]
[react/view {:style {:flex 1}} [react/view {:style {:flex 1}}
[react/scroll-view [react/scroll-view
[react/view {:style {:margin-top 8}} [react/view {:style {:margin-top 8}}
@ -759,13 +757,7 @@
:value preferred-name :value preferred-name
:action-fn #(re-frame/dispatch [:bottom-sheet/show-sheet :action-fn #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content {:content
(fn [] (name-list names preferred-name))}])}]])] (fn [] (name-list names preferred-name))}])}]])]]])
[react/view
[react/view {:padding-left 72}
[my-name]]
[react/view {:flex-direction :row}
[react/view {:padding-left 16 :padding-top 4}
[photos/photo (multiaccounts/displayed-photo account) {:size 36}]]]]]])
(views/defview main (views/defview main
[] []

View File

@ -20,10 +20,10 @@
(defn- render-contact (defn- render-contact
[row] [row]
(let [[first-name second-name] (multiaccounts/contact-two-names row false)] (let [{:keys [primary-name secondary-name]} row]
[quo/list-item [quo/list-item
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo row)]}])) (multiaccounts/displayed-photo row)]}]))
@ -54,11 +54,11 @@
(defn- toggle-item (defn- toggle-item
[] []
(fn [allow-new-users? subs-name {:keys [public-key] :as contact} on-toggle] (fn [allow-new-users? subs-name {:keys [public-key] :as contact} on-toggle]
(let [contact-selected? @(re-frame/subscribe [subs-name public-key]) (let [contact-selected? @(re-frame/subscribe [subs-name public-key])
[first-name second-name] (multiaccounts/contact-two-names contact true)] {:keys [primary-name secondary-name]} contact]
[quo/list-item [quo/list-item
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo contact)] (multiaccounts/displayed-photo contact)]
:on-press #(on-toggle allow-new-users? contact-selected? public-key) :on-press #(on-toggle allow-new-users? contact-selected? public-key)

View File

@ -12,8 +12,8 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar] [status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.profile.components.sheets :as sheets]) [status-im.ui.screens.profile.components.sheets :as sheets]
(:require-macros [status-im.utils.views :as views])) [utils.re-frame :as rf]))
(defn actions (defn actions
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?] [{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
@ -71,19 +71,21 @@
:chevron true}]) :chevron true}])
(defn nickname-settings (defn nickname-settings
[{:keys [names]}] [{:keys [nickname]}]
(println "NUCKNAME" nickname)
[quo/list-item [quo/list-item
{:title (i18n/label :t/nickname) {:title (i18n/label :t/nickname)
:size :small :size :small
:accessibility-label :profile-nickname-item :accessibility-label :profile-nickname-item
:accessory :text :accessory :text
:accessory-text (or (:nickname names) (i18n/label :t/none)) :accessory-text (or nickname (i18n/label :t/none))
:on-press #(re-frame/dispatch [:open-modal :nickname]) :on-press #(re-frame/dispatch [:open-modal :nickname])
:chevron true}]) :chevron true}])
(defn save-nickname (defn save-nickname
[public-key nickname] [public-key nickname]
(re-frame/dispatch [:contacts/update-nickname public-key nickname])) (re-frame/dispatch [:contacts/update-nickname public-key nickname])
(re-frame/dispatch [:navigate-back]))
(defn valid-nickname? (defn valid-nickname?
[nickname] [nickname]
@ -105,15 +107,16 @@
:auto-correct false}]) :auto-correct false}])
(defn nickname-view (defn nickname-view
[public-key {:keys [nickname ens-name three-words-name]}] []
(let [entered-nickname (reagent/atom nickname)] (let [{:keys [public-key primary-name nickname]} (rf/sub [:contacts/current-contact])
entered-nickname (reagent/atom nickname)]
(fn [] (fn []
[kb-presentation/keyboard-avoiding-view [kb-presentation/keyboard-avoiding-view
{:style {:flex 1} {:style {:flex 1}
:ignore-offset true} :ignore-offset true}
[topbar/topbar [topbar/topbar
{:title (i18n/label :t/nickname) {:title (i18n/label :t/nickname)
:subtitle (or ens-name three-words-name) :subtitle primary-name
:modal? true}] :modal? true}]
[react/view {:flex 1 :padding 16} [react/view {:flex 1 :padding 16}
[react/text {:style {:color colors/gray :margin-bottom 16}} [react/text {:style {:color colors/gray :margin-bottom 16}}
@ -132,11 +135,6 @@
:on-press #(save-nickname public-key @entered-nickname)} :on-press #(save-nickname public-key @entered-nickname)}
(i18n/label :t/done)]}]]))) (i18n/label :t/done)]}]])))
(views/defview nickname
[]
(views/letsubs [{:keys [public-key names]} [:contacts/current-contact]]
[nickname-view public-key names]))
(defn button-item (defn button-item
[{:keys [icon label action selected disabled negative]}] [{:keys [icon label action selected disabled negative]}]
[react/touchable-highlight [react/touchable-highlight
@ -180,7 +178,7 @@
[:contacts/current-contact]) [:contacts/current-contact])
muted? @(re-frame/subscribe [:chats/muted muted? @(re-frame/subscribe [:chats/muted
public-key]) public-key])
[first-name second-name] (multiaccounts/contact-two-names contact true) {:keys [primary-name secondary-name]} contact
on-share #(re-frame/dispatch on-share #(re-frame/dispatch
[:show-popover [:show-popover
(merge (merge
@ -202,10 +200,10 @@
[(profile-header/extended-header [(profile-header/extended-header
{:on-press on-share {:on-press on-share
:bottom-separator false :bottom-separator false
:title first-name :title primary-name
:photo (multiaccounts/displayed-photo contact) :photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified) :monospace (not ens-verified)
:subtitle second-name :subtitle secondary-name
:compressed-key compressed-key :compressed-key compressed-key
:public-key public-key})] :public-key public-key})]
[react/view [react/view

View File

@ -20,45 +20,44 @@
(defn member-sheet (defn member-sheet
[chat-id member us-admin?] [chat-id member us-admin?]
(let [[first-name _] (multiaccounts/contact-two-names member false)] [react/view
[react/view [quo/list-item
{:theme :accent
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)]
:title (:primary-name member)
:subtitle (i18n/label :t/view-profile)
:accessibility-label :view-chat-details-button
:chevron true
:on-press #(chat.sheets/hide-sheet-and-dispatch
[:chat.ui/show-profile
(:public-key member)])}]
(when (and us-admin?
(not (:admin? member)))
[quo/list-item [quo/list-item
{:theme :accent {:theme :accent
:icon [chat-icon/contact-icon-contacts-tab :title (i18n/label :t/make-admin)
(multiaccounts/displayed-photo member)] :accessibility-label :make-admin
:title first-name :icon :main-icons/make-admin
:subtitle (i18n/label :t/view-profile) :on-press #(chat.sheets/hide-sheet-and-dispatch [:group-chats.ui/make-admin-pressed
:accessibility-label :view-chat-details-button chat-id (:public-key member)])}])
:chevron true (when-not (:admin? member)
[quo/list-item
{:theme :accent
:title (i18n/label :t/remove-from-chat)
:accessibility-label :remove-from-chat
:icon :main-icons/remove-contact
:on-press #(chat.sheets/hide-sheet-and-dispatch :on-press #(chat.sheets/hide-sheet-and-dispatch
[:chat.ui/show-profile [:group-chats.ui/remove-member-pressed chat-id
(:public-key member)])}] (:public-key member)])}])])
(when (and us-admin?
(not (:admin? member)))
[quo/list-item
{:theme :accent
:title (i18n/label :t/make-admin)
:accessibility-label :make-admin
:icon :main-icons/make-admin
:on-press #(chat.sheets/hide-sheet-and-dispatch [:group-chats.ui/make-admin-pressed
chat-id (:public-key member)])}])
(when-not (:admin? member)
[quo/list-item
{:theme :accent
:title (i18n/label :t/remove-from-chat)
:accessibility-label :remove-from-chat
:icon :main-icons/remove-contact
:on-press #(chat.sheets/hide-sheet-and-dispatch
[:group-chats.ui/remove-member-pressed chat-id
(:public-key member)])}])]))
(defn render-member (defn render-member
[{:keys [public-key] :as member} _ _ {:keys [chat-id admin? current-user-identity]}] [{:keys [public-key] :as member} _ _ {:keys [chat-id admin? current-user-identity]}]
(let [[first-name second-name] (multiaccounts/contact-two-names member false)] (let [{:keys [primary-name secondary-name]} member]
[quo/list-item [quo/list-item
(merge (merge
{:title first-name {:title primary-name
:subtitle second-name :subtitle secondary-name
:accessibility-label :member-item :accessibility-label :member-item
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)] (multiaccounts/displayed-photo member)]

View File

@ -565,7 +565,7 @@
:insets {:bottom true} :insets {:bottom true}
;;TODO dyn subtitle ;;TODO dyn subtitle
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component contact/nickname} :component contact/nickname-view}
{:name :new-chat-aio {:name :new-chat-aio
:on-focus [:contacts/new-chat-focus] :on-focus [:contacts/new-chat-focus]

View File

@ -91,16 +91,15 @@
(defn contacts-list-item (defn contacts-list-item
[{:keys [name] :as contact}] [{:keys [name] :as contact}]
(let [[first-name second-name] (multiaccounts/contact-two-names contact true)] [quo/list-item
[quo/list-item {:title (:primary-name contact)
{:title first-name :subtitle (:secondary-name contact)
:subtitle second-name :on-press #(do
:on-press #(do (some-> ^js @scroll-view-ref
(some-> ^js @scroll-view-ref (.scrollTo #js {:x 0 :animated true}))
(.scrollTo #js {:x 0 :animated true})) (re-frame/dispatch [:wallet.recipient/address-changed name]))
(re-frame/dispatch [:wallet.recipient/address-changed name])) :icon [chat-icon/contact-icon-contacts-tab
:icon [chat-icon/contact-icon-contacts-tab (multiaccounts/displayed-photo contact)]}])
(multiaccounts/displayed-photo contact)]}]))
(defn empty-items (defn empty-items
[icon title] [icon title]

View File

@ -3,33 +3,22 @@
[quo2.core :as quo2] [quo2.core :as quo2]
[quo2.foundations.colors :as quo2.colors] [quo2.foundations.colors :as quo2.colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im2.constants :as constants] [status-im2.constants :as constants]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[react-native.core :as rn] [react-native.core :as rn]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[clojure.string :as string]
[status-im2.common.contact-list.view :as contact-list] [status-im2.common.contact-list.view :as contact-list]
[quo2.components.markdown.text :as text] [quo2.components.markdown.text :as text]
[status-im.ui.components.invite.events :as invite.events] [status-im.ui.components.invite.events :as invite.events]
[status-im.ui2.screens.chat.components.new-chat.styles :as style] [status-im.ui2.screens.chat.components.new-chat.styles :as style]
[status-im.react-native.resources :as resources])) [status-im.react-native.resources :as resources]
[status-im2.common.contact-list-item.view :as contact-list-item]))
(defn- hide-sheet-and-dispatch (defn- hide-sheet-and-dispatch
[event] [event]
(rf/dispatch [:bottom-sheet/hide]) (rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event)) (rf/dispatch event))
(defn- on-toggle
[allow-new-users? checked? public-key]
(cond
checked?
(re-frame/dispatch [:deselect-contact public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(re-frame/dispatch [:select-contact public-key allow-new-users?])))
(defn- no-contacts-view (defn- no-contacts-view
[] []
[rn/view [rn/view
@ -59,28 +48,34 @@
:on-press #(hide-sheet-and-dispatch [:open-modal :new-contact])} :on-press #(hide-sheet-and-dispatch [:open-modal :new-contact])}
(i18n/label :t/add-a-contact)]]) (i18n/label :t/add-a-contact)]])
(defn contact-item-render
[_]
(fn [{:keys [public-key] :as item}]
(let [user-selected? (rf/sub [:is-contact-selected? public-key])
on-toggle #(if user-selected?
(re-frame/dispatch [:deselect-contact public-key])
(re-frame/dispatch [:select-contact public-key]))]
[contact-list-item/contact-list-item
{:on-press on-toggle
:accessory {:type :checkbox
:checked? user-selected?
:on-check on-toggle}}
item])))
(defn contact-selection-list (defn contact-selection-list
[] []
[:f> [:f>
(fn [] (fn []
(let [contacts (rf/sub (let [contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter])
[:contacts/sorted-and-grouped-by-first-letter]) selected-contacts-count (rf/sub [:selected-contacts-count])
selected-contacts-count (rf/sub [:selected-contacts-count]) selected-contacts (rf/sub [:group/selected-contacts])
selected-contacts (rf/sub [:group/selected-contacts]) window-height (rf/sub [:dimensions/window-height])
window-height (rf/sub [:dimensions/window-height]) one-contact-selected? (= selected-contacts-count 1)
one-contact-selected? (= selected-contacts-count 1) contacts-selected? (pos? selected-contacts-count)
contacts-selected? (pos? selected-contacts-count) {:keys [primary-name public-key]} (when one-contact-selected?
{:keys [names public-key]} (when one-contact-selected? (rf/sub [:contacts/contact-by-identity
(rf/sub [:contacts/contact-by-identity (first selected-contacts)]))
(first selected-contacts)])) no-contacts? (empty? contacts)]
added? (reagent/atom '())
{:keys [nickname ens-name display-name
three-words-name]} names
first-username (or nickname
ens-name
(when-not (string/blank? display-name) display-name)
three-words-name)
no-contacts? (empty? contacts)]
[rn/view {:style {:height (* window-height 0.9)}} [rn/view {:style {:height (* window-height 0.9)}}
[quo2/button [quo2/button
{:type :grey {:type :grey
@ -102,20 +97,19 @@
:weight :regular :weight :regular
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-40 quo2.colors/neutral-50)}} :style {:color (quo2.colors/theme-colors quo2.colors/neutral-40 quo2.colors/neutral-50)}}
(i18n/label :t/selected-count-from-max (i18n/label :t/selected-count-from-max
{:selected (inc selected-contacts-count) {:selected selected-contacts-count
:max constants/max-group-chat-participants})])] :max constants/max-group-chat-participants})])]
[rn/view [rn/view
{:style {:flex 1}} {:style {:flex 1}}
(if no-contacts? (if no-contacts?
[no-contacts-view] [no-contacts-view]
[contact-list/contact-list [rn/section-list
{:icon :check {:key-fn :title
:group nil :sticky-section-headers-enabled false
:added? added? :sections (rf/sub [:contacts/filtered-active-sections])
:search? false :render-section-header-fn contact-list/contacts-section-header
:start-a-new-chat? true :content-container-style {:padding-bottom 70}
:on-toggle on-toggle} :render-fn contact-item-render}])]
70])]
(when contacts-selected? (when contacts-selected?
[button/button [button/button
{:type :primary {:type :primary
@ -128,5 +122,5 @@
(hide-sheet-and-dispatch [:navigate-to (hide-sheet-and-dispatch [:navigate-to
:new-group])))} :new-group])))}
(if one-contact-selected? (if one-contact-selected?
(i18n/label :t/chat-with {:selected-user first-username}) (i18n/label :t/chat-with {:selected-user primary-name})
(i18n/label :t/setup-group-chat))])]))]) (i18n/label :t/setup-group-chat))])]))])

View File

@ -76,7 +76,6 @@
(defn on-text-change (defn on-text-change
[val chat-id] [val chat-id]
(println "on=text-change" val)
(swap! input-texts assoc chat-id val) (swap! input-texts assoc chat-id val)
;;we still store it in app-db for mentions, we don't have reactions in views ;;we still store it in app-db for mentions, we don't have reactions in views
(rf/dispatch [:chat.ui/set-chat-input-text val])) (rf/dispatch [:chat.ui/set-chat-input-text val]))

View File

@ -1,51 +1,2 @@
(ns status-im.ui2.screens.chat.composer.mentions (ns status-im.ui2.screens.chat.composer.mentions)
(:require [quo.components.list.item :as list-item]
[quo.components.text :as text]
[quo.react]
[quo.react-native :as rn]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.chat.photos :as photos]
[utils.re-frame :as rf]))
(defn mention-item
[[public-key {:keys [alias name nickname] :as user}] _ _ text-input-ref]
(let [ens-name? (not= alias name)]
[rn/touchable-opacity
{:on-press #(rf/dispatch [:chat.ui/select-mention text-input-ref user])
:accessibility-label :mention-item}
;;TODO quo2 item should be used
[list-item/list-item
(cond->
{:icon [photos/member-photo public-key]
:size :small
:text-size :small
:title [text/text
{:weight :medium
:ellipsize-mode :tail
:number-of-lines 1
:size :small}
(or nickname name)
(when nickname
[text/text
{:weight :regular
:color :secondary
:ellipsize-mode :tail
:size :small}
" "
(when ens-name?
"@")
name])]
:title-text-weight :medium}
ens-name?
(assoc :subtitle alias))]]))
(defn autocomplete-mentions
[suggestions text-input-ref]
[list/flat-list
{:keyboardShouldPersistTaps :always
:data suggestions
:key-fn first
:render-fn mention-item
:render-data text-input-ref
:content-container-style {:padding-bottom 12}
:accessibility-label :mentions-list}])

View File

@ -154,23 +154,12 @@
[rn/view style/not-sent-icon [rn/view style/not-sent-icon
[icons/icon :i/warning {:color quo.colors/red}]]]]) [icons/icon :i/warning {:color quo.colors/red}]]]])
(defn message-delivery-status
[{:keys [chat-id message-id outgoing-status message-type]}]
(when (and (not= constants/message-type-private-group-system-message message-type)
(= outgoing-status :not-sent))
[message-not-sent-text chat-id message-id]))
;; TODO (Omar): a reminder to clean these defviews ;; TODO (Omar): a reminder to clean these defviews
(defview message-author-name (defview message-author-name
[from opts max-length] [from opts max-length]
(letsubs [contact-with-names [:contacts/contact-by-identity from]] (letsubs [contact-with-names [:contacts/contact-by-identity from]]
(chat.utils/format-author contact-with-names opts max-length))) (chat.utils/format-author contact-with-names opts max-length)))
(defview message-my-name
[opts]
(letsubs [contact-with-names [:multiaccount/contact]]
(chat.utils/format-author contact-with-names opts nil)))
(defn display-name-view (defn display-name-view
[display-name contact timestamp show-key?] [display-name contact timestamp show-key?]
[rn/view {:style {:flex-direction :row}} [rn/view {:style {:flex-direction :row}}

View File

@ -1,23 +1,6 @@
(ns status-im2.common.contact-list.view (ns status-im2.common.contact-list.view
(:require [quo2.core :as quo] (:require [quo2.core :as quo]))
[react-native.core :as rn]
[status-im2.common.contact-list-item.view :as contact-list-item]
[utils.re-frame :as rf]))
(defn contacts-section-header (defn contacts-section-header
[{:keys [title]}] [{:keys [title]}]
[quo/divider-label {:label title}]) [quo/divider-label {:label title}])
(defn contact-list
[data padding-bottom]
(let [contacts (if (:group data)
(rf/sub [:contacts/grouped-by-first-letter])
(rf/sub [:contacts/filtered-active-sections]))]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections contacts
:render-section-header-fn contacts-section-header
:content-container-style {:padding-bottom (or padding-bottom 20)}
:render-data data
:render-fn contact-list-item/contact-list-item}]))

View File

@ -1,10 +0,0 @@
(ns status-im2.common.contact-list-item.style)
(def container
{:margin-top 8
:margin-horizontal 8
:padding-vertical 8
:padding-horizontal 12
:border-radius 12
:flex-direction :row
:align-items :center})

View File

@ -1,119 +1,21 @@
(ns status-im2.common.contact-list-item.view (ns status-im2.common.contact-list-item.view
(:require [quo2.core :as quo] (:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[status-im2.common.home.actions.view :as actions]
[status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.address :as utils.address]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[reagent.core :as reagent])) [utils.address :as address]))
(defn group-chat-member-toggle
[member? selected? public-key]
(if-not member?
(if selected?
(rf/dispatch [:select-participant public-key true])
(rf/dispatch [:deselect-participant public-key true]))
(if selected?
(rf/dispatch [:undo-deselect-member public-key true])
(rf/dispatch [:deselect-member public-key true]))))
(defn open-chat
[public-key member? selected? current-pk]
(let [view-id (rf/sub [:view-id])]
(when (not= current-pk public-key)
(case view-id
:shell-stack (do (rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:chat.ui/show-profile public-key])
(rf/dispatch [:search/home-filter-changed nil]))
:group-chat-profile (group-chat-member-toggle member? selected? public-key)))))
(defn action-icon
[{:keys [public-key]
:as item}
{:keys [icon start-a-new-chat?]
:as extra-data} on-toggle admin? member?
checked?]
(let [on-check (fn []
(if start-a-new-chat?
(on-toggle true @checked? public-key)
(group-chat-member-toggle member? (swap! checked? not) public-key)))]
[:f>
(fn []
[rn/touchable-opacity
{:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item extra-data])}])
:style {:position :absolute
:right 20}}
(if (= icon :options)
[quo/icon :i/options
{:size 20
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
[quo/checkbox
{:checked? @checked?
:accessibility-label :contact-toggle-check
:disabled? (and member? (not admin?))
:on-change on-check}])])]))
(defn contact-list-item (defn contact-list-item
[item _ _ {:keys [start-a-new-chat? on-toggle group] :as extra-data}] [{:keys [on-press on-long-press accessory]}
(let [{:keys [public-key compressed-key ens-verified {:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}]
added? images]} item (let [photo-path (rf/sub [:chats/photo-path public-key])
display-name (first online? (rf/sub [:visibility-status-updates/online? public-key])]
(rf/sub [quo/user-list
[:contacts/contact-two-names-by-identity {:short-chat-key (address/get-shortened-key (or compressed-key public-key))
public-key])) :primary-name primary-name
photo-path (when (seq images) :secondary-name secondary-name
(rf/sub [:chats/photo-path public-key])) :photo-path photo-path
online? (rf/sub [:visibility-status-updates/online? :online? online?
public-key]) :verified? ens-verified
user-selected? (rf/sub [:is-contact-selected? public-key]) :contact? added?
{:keys [contacts admins]} group :on-press on-press
member? (contains? contacts public-key) :on-long-press on-long-press
current-pk (rf/sub [:multiaccount/public-key]) :accessory accessory}]))
admin? (get admins current-pk)
checked? (reagent/atom (if start-a-new-chat?
user-selected?
member?))]
[rn/touchable-opacity
(merge
{:style (style/container)
:accessibility-label :contact
:active-opacity 1
:on-press #(if start-a-new-chat?
(on-toggle true user-selected? public-key)
(open-chat public-key member? (swap! checked? not) current-pk))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item extra-data])}])})
[quo/user-avatar
{:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small
:ring? false}]
[rn/view {:style {:margin-left 8}}
[rn/view {:style {:flex-direction :row}}
[quo/text {:weight :semi-bold} display-name]
(if ens-verified
[rn/view
{:style {:margin-left 5
:margin-top 4}}
[quo/icon :i/verified
{:no-color true
:size 12
:color (colors/theme-colors colors/success-50 colors/success-60)}]]
(when added?
[rn/view
{:style {:margin-left 5
:margin-top 4}}
[quo/icon :i/contact
{:no-color true
:size 12
:color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
[quo/text
{:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(utils.address/get-shortened-address (or compressed-key public-key))]]
(when-not (= current-pk public-key)
[action-icon item extra-data on-toggle admin? member? checked?])]))

View File

@ -433,16 +433,15 @@
(leave-group-entry contact extra-data) (leave-group-entry contact extra-data)
(remove-from-group-entry contact chat-id))])]])) (remove-from-group-entry contact chat-id))])]]))
(defn actions (defn chat-actions
[{:keys [chat-type] :as item} {:keys [inside-chat?] :as extra-data}] [{:keys [chat-type] :as item} inside-chat?]
(case chat-type (case chat-type
constants/one-to-one-chat-type constants/one-to-one-chat-type
[one-to-one-actions item inside-chat?] [one-to-one-actions item inside-chat?]
constants/public-chat-type constants/public-chat-type
[public-chat-actions item inside-chat?] [public-chat-actions item inside-chat?]
constants/private-group-chat-type constants/private-group-chat-type
[private-group-chat-actions item inside-chat?] [private-group-chat-actions item inside-chat?]))
[contact-actions item extra-data]))
(defn group-details-actions (defn group-details-actions
[{:keys [admins] :as group}] [{:keys [admins] :as group}]

View File

@ -5,7 +5,6 @@
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im2.contexts.activity-center.notification.common.style :as style] [status-im2.contexts.activity-center.notification.common.style :as style]
[status-im2.contexts.activity-center.utils :as activity-center.utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -18,7 +17,7 @@
:size :small :size :small
:style style/user-avatar-tag :style style/user-avatar-tag
:text-style style/user-avatar-tag-text} :text-style style/user-avatar-tag-text}
(activity-center.utils/contact-name contact) (:primary-name contact)
(multiaccounts/displayed-photo contact)])) (multiaccounts/displayed-photo contact)]))
(defn- render-swipe-action (defn- render-swipe-action

View File

@ -1,11 +0,0 @@
(ns status-im2.contexts.activity-center.utils)
(defn contact-name
[contact]
(->> [(get-in contact [:names :nickname])
(get-in contact [:names :ens-name])
(get-in contact [:names :display-name])
(get-in contact [:names :three-words-name])]
(filter seq)
first))

View File

@ -10,9 +10,10 @@
[status-im2.constants :as constants] [status-im2.constants :as constants]
[status-im.chat.models.loading :as loading] [status-im.chat.models.loading :as loading]
[status-im.data-store.chats :as chats-store] [status-im.data-store.chats :as chats-store]
[status-im.data-store.contacts :as contacts-store] [status-im2.contexts.contacts.events :as contacts-store]
[status-im.multiaccounts.model :as multiaccounts.model] [status-im.multiaccounts.model :as multiaccounts.model]
[status-im.utils.clocks :as utils.clocks])) [status-im.utils.clocks :as utils.clocks]
[status-im.utils.types :as types]))
(defn- get-chat (defn- get-chat
[cofx chat-id] [cofx chat-id]
@ -221,10 +222,10 @@
(rf/defn handle-one-to-one-chat-created (rf/defn handle-one-to-one-chat-created
{:events [:chat/one-to-one-chat-created]} {:events [:chat/one-to-one-chat-created]}
[{:keys [db]} chat-id response] [{:keys [db]} chat-id response-js]
(let [chat (chats-store/<-rpc (first (:chats response))) (let [chat (chats-store/<-rpc (first (types/js->clj (.-chats ^js response-js))))
contact-rpc (first (:contacts response)) contact-js (first (.-contacts ^js response-js))
contact (when contact-rpc (contacts-store/<-rpc contact-rpc))] contact (when contact-js (contacts-store/<-rpc-js contact-js))]
{:db (cond-> db {:db (cond-> db
contact contact
(assoc-in [:contacts/contacts chat-id] contact) (assoc-in [:contacts/contacts chat-id] contact)
@ -253,10 +254,11 @@
{:events [:chat.ui/start-chat]} {:events [:chat.ui/start-chat]}
[cofx chat-id ens-name] [cofx chat-id ens-name]
(when (not= (multiaccounts.model/current-public-key cofx) chat-id) (when (not= (multiaccounts.model/current-public-key cofx) chat-id)
{:json-rpc/call [{:method "wakuext_createOneToOneChat" {:json-rpc/call [{:method "wakuext_createOneToOneChat"
:params [{:id chat-id :ensName ens-name}] :params [{:id chat-id :ensName ens-name}]
:on-success #(rf/dispatch [:chat/one-to-one-chat-created chat-id %]) :js-response true
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]})) :on-success #(rf/dispatch [:chat/one-to-one-chat-created chat-id %])
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]}))
(rf/defn clear-history-handler (rf/defn clear-history-handler
"Clears history of the particular chat" "Clears history of the particular chat"

View File

@ -1,30 +1,31 @@
(ns status-im2.contexts.chat.group-details.view (ns status-im2.contexts.chat.group-details.view
(:require [utils.i18n :as i18n] (:require [utils.i18n :as i18n]
[quo.components.safe-area :as safe-area] [quo.components.safe-area :as safe-area]
[quo2.core :as quo2] [quo2.core :as quo]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
[status-im2.contexts.chat.group-details.style :as style] [status-im2.contexts.chat.group-details.style :as style]
[status-im2.common.contact-list.view :as contact-list] [status-im2.common.contact-list.view :as contact-list]
[status-im2.common.contact-list-item.view :as contact-list-item] [status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.common.home.actions.view :as actions] [status-im2.common.home.actions.view :as actions]
[utils.re-frame :as rf])) [utils.re-frame :as rf]
[reagent.core :as reagent]))
(defn back-button (defn back-button
[] []
[quo2/button [quo/button
{:type :grey {:type :grey
:size 32 :size 32
:width 32 :width 32
:style {:margin-left 20} :style {:margin-left 20}
:accessibility-label :back-button :accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])} :on-press #(rf/dispatch [:navigate-back])}
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]]) [quo/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn options-button (defn options-button
[] []
(let [group (rf/sub [:chats/current-chat])] (let [group (rf/sub [:chats/current-chat])]
[quo2/button [quo/button
{:type :grey {:type :grey
:size 32 :size 32
:width 32 :width 32
@ -32,7 +33,7 @@
:accessibility-label :options-button :accessibility-label :options-button
:on-press #(rf/dispatch [:bottom-sheet/show-sheet :on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/group-details-actions group])}])} {:content (fn [] [actions/group-details-actions group])}])}
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]])) [quo/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]]))
(defn top-buttons (defn top-buttons
[] []
@ -47,7 +48,7 @@
[rn/view [rn/view
{:style (style/count-container) {:style (style/count-container)
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
[quo2/text [quo/text
{:size :label {:size :label
:weight :medium :weight :medium
:style {:text-align :center}} count]]) :style {:text-align :center}} count]])
@ -60,11 +61,37 @@
:border-top-color colors/neutral-20 :border-top-color colors/neutral-20
:padding-vertical 8 :padding-vertical 8
:margin-top 8}} :margin-top 8}}
[quo2/text [quo/text
{:size :paragraph-2 {:size :paragraph-2
:weight :medium :weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]]) :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]])
(defn group-chat-member-toggle
[member? selected? public-key]
(if-not member?
(if selected?
(rf/dispatch [:select-participant public-key true])
(rf/dispatch [:deselect-participant public-key true]))
(if selected?
(rf/dispatch [:undo-deselect-member public-key true])
(rf/dispatch [:deselect-member public-key true]))))
(defn add-member-contact-item-render
[{:keys [public-key] :as item} _ _ {:keys [group]}]
(let [current-pk (rf/sub [:multiaccount/public-key])
{:keys [contacts]} group
member? (contains? contacts public-key)
checked? (reagent/atom member?)]
(fn []
(let [on-toggle #(group-chat-member-toggle member? (swap! checked? not) public-key)]
[contact-list-item/contact-list-item
(when (not= current-pk public-key)
{:on-press on-toggle
:accessory {:type :checkbox
:checked? @checked?
:on-check on-toggle}})
item]))))
(defn add-members-sheet (defn add-members-sheet
[group admin?] [group admin?]
[:f> [:f>
@ -78,18 +105,22 @@
{:on-press #(rf/dispatch [:bottom-sheet/hide]) {:on-press #(rf/dispatch [:bottom-sheet/hide])
:accessibility-label :close-manage-members :accessibility-label :close-manage-members
:style (style/close-icon)} :style (style/close-icon)}
[quo2/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]] [quo/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[quo2/text [quo/text
{:size :heading-1 {:size :heading-1
:weight :semi-bold :weight :semi-bold
:style {:margin-left 20}} :style {:margin-left 20}}
(i18n/label (if admin? :t/manage-members :t/add-members))] (i18n/label (if admin? :t/manage-members :t/add-members))]
[contact-list/contact-list [rn/section-list
{:icon :check {:key-fn :title
:group group :sticky-section-headers-enabled false
:search? true}] :sections (rf/sub [:contacts/grouped-by-first-letter])
:render-section-header-fn contact-list/contacts-section-header
:content-container-style {:padding-bottom 20}
:render-data {:group group}
:render-fn add-member-contact-item-render}]
[rn/view {:style (style/bottom-container safe-area)} [rn/view {:style (style/bottom-container safe-area)}
[quo2/button [quo/button
{:style {:flex 1} {:style {:flex 1}
:accessibility-label :save :accessibility-label :save
:on-press (fn [] :on-press (fn []
@ -103,6 +134,20 @@
(zero? (count deselected-members)))} (zero? (count deselected-members)))}
(i18n/label :t/save)]]]))]) (i18n/label :t/save)]]]))])
(defn contact-item-render
[{:keys [public-key] :as item} _ _ extra-data]
(let [current-pk (rf/sub [:multiaccount/public-key])
show-profile-actions #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/contact-actions item
extra-data])}])]
[contact-list-item/contact-list-item
(when (not= public-key current-pk)
{:on-press #(rf/dispatch [:chat.ui/show-profile public-key])
:on-long-press show-profile-actions
:accessory {:type :options
:on-press show-profile-actions}})
item]))
(defn group-details (defn group-details
[] []
(let [{:keys [admins chat-id chat-name color public? (let [{:keys [admins chat-id chat-name color public?
@ -116,7 +161,7 @@
[rn/view [rn/view
{:style {:flex 1 {:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}} :background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header [quo/header
{:left-component [back-button] {:left-component [back-button]
:right-component [options-button] :right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}] :background (colors/theme-colors colors/white colors/neutral-95)}]
@ -124,15 +169,15 @@
{:style {:flex-direction :row {:style {:flex-direction :row
:margin-top 24 :margin-top 24
:padding-horizontal 20}} :padding-horizontal 20}}
[quo2/group-avatar [quo/group-avatar
{:color color {:color color
:size :medium}] :size :medium}]
[quo2/text [quo/text
{:weight :semi-bold {:weight :semi-bold
:size :heading-1 :size :heading-1
:style {:margin-horizontal 8}} chat-name] :style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}} [rn/view {:style {:margin-top 8}}
[quo2/icon (if public? :i/world :i/privacy) [quo/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]] {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)} [rn/view {:style (style/actions-view)}
[rn/touchable-opacity [rn/touchable-opacity
@ -144,17 +189,17 @@
[rn/view [rn/view
{:style {:flex-direction :row {:style {:flex-direction :row
:justify-content :space-between}} :justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] [quo/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages) :pinned-count]] [count-container (count pinned-messages) :pinned-count]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} [quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]] (i18n/label :t/pinned-messages)]]
[rn/touchable-opacity [rn/touchable-opacity
{:style (style/action-container color) {:style (style/action-container color)
:accessibility-label :toggle-mute :accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)])} :on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)])}
[quo2/icon (if muted :i/muted :i/activity-center) [quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} [quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]] (i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity [rn/touchable-opacity
{:style (style/action-container color) {:style (style/action-container color)
@ -168,16 +213,15 @@
[rn/view [rn/view
{:style {:flex-direction :row {:style {:flex-direction :row
:justify-content :space-between}} :justify-content :space-between}}
[quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] [quo/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts) :members-count]] [count-container (count contacts) :members-count]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} [quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]] (i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list [rn/section-list
{:key-fn :title {:key-fn :title
:sticky-section-headers-enabled false :sticky-section-headers-enabled false
:sections members :sections members
:render-section-header-fn contacts-section-header :render-section-header-fn contacts-section-header
:render-fn contact-list-item/contact-list-item
:render-data {:chat-id chat-id :render-data {:chat-id chat-id
:admin? admin? :admin? admin?}
:icon :options}}]])) :render-fn contact-item-render}]]))

View File

@ -127,7 +127,7 @@
(merge {:style (style/container) (merge {:style (style/container)
:on-press (open-chat chat-id) :on-press (open-chat chat-id)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item false])}])}) {:content (fn [] [actions/chat-actions item false])}])})
[avatar-view group-chat color display-name photo-path chat-id] [avatar-view group-chat color display-name photo-path chat-id]
[rn/view {:style {:margin-left 8}} [rn/view {:style {:margin-left 8}}
[name-view display-name contact timestamp] [name-view display-name contact timestamp]

View File

@ -8,7 +8,9 @@
[status-im2.common.home.view :as common.home] [status-im2.common.home.view :as common.home]
[status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item] [status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item]
[status-im2.contexts.chat.home.contact-request.view :as contact-request] [status-im2.contexts.chat.home.contact-request.view :as contact-request]
[utils.re-frame :as rf])) [utils.re-frame :as rf]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.common.home.actions.view :as actions]))
(defn get-item-layout (defn get-item-layout
[_ index] [_ index]
@ -50,6 +52,29 @@
[quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)] [quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)]
[quo/text (i18n/label :t/blank-contacts-text)]]) [quo/text (i18n/label :t/blank-contacts-text)]])
(defn contact-item-render
[{:keys [public-key] :as item}]
(let [current-pk (rf/sub [:multiaccount/public-key])
show-profile-actions #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/contact-actions item])}])]
[contact-list-item/contact-list-item
(when (not= public-key current-pk)
{:on-press #(rf/dispatch [:chat.ui/show-profile public-key])
:on-long-press show-profile-actions
:accessory {:type :options
:on-press show-profile-actions}})
item]))
(defn contacts-section-list
[sections]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections sections
:render-section-header-fn contact-list/contacts-section-header
:content-container-style {:padding-bottom 20}
:render-fn contact-item-render}])
(defn contacts (defn contacts
[pending-contact-requests] [pending-contact-requests]
(let [items (rf/sub [:contacts/active-sections])] (let [items (rf/sub [:contacts/active-sections])]
@ -59,7 +84,7 @@
(when (seq pending-contact-requests) (when (seq pending-contact-requests)
[contact-request/contact-requests pending-contact-requests]) [contact-request/contact-requests pending-contact-requests])
(when (seq items) (when (seq items)
[contact-list/contact-list {:icon :options}])]))) [contacts-section-list items])])))
(defn tabs (defn tabs
[] []

View File

@ -0,0 +1,37 @@
(ns status-im2.contexts.chat.messages.composer.mentions.view
(:require [utils.re-frame :as rf]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[status-im2.common.contact-list-item.view :as contact-list-item]))
(defn mention-item
[user _ _ text-input-ref]
[contact-list-item/contact-list-item
{:on-press #(rf/dispatch [:chat.ui/select-mention text-input-ref user])} user])
(defn mentions
[{:keys [refs suggestions max-y]} insets]
[:f>
(fn []
(let [translate-y (reanimated/use-shared-value 0)]
(rn/use-effect
(fn []
(reanimated/set-shared-value translate-y
(reanimated/with-timing (if (seq suggestions) 0 200)))))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
{:bottom (or (:bottom insets) 0)
:position :absolute
:left 0
:right 0
:z-index 5
:elevation 5
:max-height (/ max-y 2)})}
[rn/flat-list
{:keyboardShouldPersistTaps :always
:data (vals suggestions)
:key-fn :key
:render-fn mention-item
:render-data (:text-input-ref refs)
:accessibility-label :mentions-list}]]))])

View File

@ -9,9 +9,9 @@
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im2.contexts.chat.messages.composer.style :as style] [status-im2.contexts.chat.messages.composer.style :as style]
[status-im2.contexts.chat.messages.composer.controls.view :as controls] [status-im2.contexts.chat.messages.composer.controls.view :as controls]
[status-im2.contexts.chat.messages.composer.mentions.view :as mentions]
[status-im.ui2.screens.chat.composer.edit.view :as edit] [status-im.ui2.screens.chat.composer.edit.view :as edit]
[status-im.ui2.screens.chat.composer.input :as input] [status-im.ui2.screens.chat.composer.input :as input]
[status-im.ui2.screens.chat.composer.mentions :as mentions]
[status-im.ui2.screens.chat.composer.reply :as reply])) [status-im.ui2.screens.chat.composer.reply :as reply]))
(def initial-content-height (atom nil)) (def initial-content-height (atom nil))
@ -98,25 +98,6 @@
(update-y params)) (update-y params))
(reset! initial-content-height new-height))))) (reset! initial-content-height new-height)))))
(defn mentions
[{:keys [refs suggestions max-y]} insets]
[:f>
(fn []
(let [translate-y (reanimated/use-shared-value 0)]
(rn/use-effect
(fn []
(reanimated/set-shared-value translate-y
(reanimated/with-timing (if (seq suggestions) 0 200)))))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
{:bottom (or (:bottom insets) 0)
:position :absolute
:z-index 5
:elevation 5
:max-height (/ max-y 2)})}
[mentions/autocomplete-mentions suggestions (:text-input-ref refs)]]))])
(defn effect! (defn effect!
[{:keys [keyboard-shown reply edit suggestions images] :as params}] [{:keys [keyboard-shown reply edit suggestions images] :as params}]
(rn/use-effect (rn/use-effect
@ -241,7 +222,7 @@
:sending-image (seq images) :sending-image (seq images)
:refs refs}]]]] :refs refs}]]]]
(if suggestions? (if suggestions?
[mentions params insets] [mentions/mentions params insets]
[controls/view send-ref params insets chat-id images #(clean-and-minimize params)]) [controls/view send-ref params insets chat-id images #(clean-and-minimize params)])
;;;;black background ;;;;black background
[reanimated/view [reanimated/view

View File

@ -7,7 +7,7 @@
(defn user-xxx-deleted-this-message (defn user-xxx-deleted-this-message
[{:keys [display-name profile-picture]}] [{:keys [display-name profile-picture]}]
[rn/view {:style {:flex-direction :row :align-items :center}} [rn/view {:style {:flex-direction :row :align-items :center :flex 1 :flex-wrap :wrap}}
[rn/view {:style {:margin-right 4}} [rn/view {:style {:margin-right 4}}
[quo/user-avatar [quo/user-avatar
{:full-name display-name {:full-name display-name
@ -15,9 +15,7 @@
:status-indicator? false :status-indicator? false
:ring? false :ring? false
:size :xxxs}]] :size :xxxs}]]
[quo/display-name [quo/author {:primary-name display-name}]
{:profile-name display-name
:text-style {}}]
[quo/text {:style {:margin-left 4} :size :paragraph-2} [quo/text {:style {:margin-left 4} :size :paragraph-2}
(i18n/label :t/deleted-this-message)]]) (i18n/label :t/deleted-this-message)]])

View File

@ -1,7 +1,6 @@
(ns status-im2.contexts.chat.messages.content.view (ns status-im2.contexts.chat.messages.content.view
(:require [react-native.core :as rn] (:require [react-native.core :as rn]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[status-im.utils.utils :as utils]
[status-im2.contexts.chat.messages.content.style :as style] [status-im2.contexts.chat.messages.content.style :as style]
[status-im2.contexts.chat.messages.content.pin.view :as pin] [status-im2.contexts.chat.messages.content.pin.view :as pin]
[status-im2.constants :as constants] [status-im2.constants :as constants]
@ -18,7 +17,8 @@
[status-im.ui2.screens.chat.messages.message :as old-message] [status-im.ui2.screens.chat.messages.message :as old-message]
[status-im2.common.not-implemented :as not-implemented] [status-im2.common.not-implemented :as not-implemented]
[utils.datetime :as datetime] [utils.datetime :as datetime]
[reagent.core :as reagent])) [reagent.core :as reagent]
[utils.address :as address]))
(def delivery-state-showing-time-ms 3000) (def delivery-state-showing-time-ms 3000)
@ -52,12 +52,12 @@
from from
timestamp]}] timestamp]}]
(when (or (and (seq response-to) quoted-message) last-in-group? pinned) (when (or (and (seq response-to) quoted-message) last-in-group? pinned)
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from])) (let [[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity from])
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])] {:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
[quo/author [quo/author
{:profile-name display-name {:primary-name primary-name
:short-chat-key (utils/get-shortened-address (or compressed-key :secondary-name secondary-name
from)) :short-chat-key (address/get-shortened-key (or compressed-key from))
:time-str (datetime/timestamp->time timestamp) :time-str (datetime/timestamp->time timestamp)
:contact? added? :contact? added?
:verified? ens-verified}]))) :verified? ens-verified}])))

View File

@ -1,22 +1,124 @@
(ns status-im2.contexts.contacts.events (ns status-im2.contexts.contacts.events
(:require (:require
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im.contact.db :as contact.db] [taoensso.timbre :as log]
[status-im.data-store.contacts :as contacts-store])) [status-im.utils.types :as types]
[oops.core :as oops]
[status-im2.constants :as constants]))
(rf/defn load-contacts (defn <-rpc-js
{:events [:contacts/contacts-loaded]} [^js js-contact]
[{:keys [db] :as cofx} all-contacts] {:public-key (oops/oget js-contact "id")
(let [contacts-list (map #(vector (:public-key %) :compressed-key (oops/oget js-contact "compressedKey")
(if (empty? (:address %)) :primary-name (oops/oget js-contact "primaryName")
(dissoc % :address) :secondary-name (.-secondaryName js-contact)
%)) :ens-name (.-ensName js-contact)
all-contacts) :nickname (.-localNickname js-contact)
contacts (into {} contacts-list)] :identicon (oops/oget js-contact "identicon")
{:db (cond-> (-> db :images (types/js->clj (oops/oget js-contact "images"))
(update :contacts/contacts #(merge contacts %)) :ens-verified (oops/oget js-contact "ensVerified")
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts))))})) :contact-request-state (oops/oget js-contact "contactRequestState")
:last-updated (oops/oget js-contact "lastUpdated")
:active? (oops/oget js-contact "active")
:blocked? (oops/oget js-contact "blocked")
:added? (oops/oget js-contact "added")
:has-added-us? (oops/oget js-contact "hasAddedUs")
:mutual? (oops/oget js-contact "mutual")})
(defn prepare-events-for-contact
[db chats-js]
(fn [events {:keys [public-key has-added-us? blocked? contact-request-state] :as contact}]
(let [was-blocked? (get-in db [:contacts/contacts public-key :blocked?])]
(cond-> events
(and (not has-added-us?) (= constants/contact-request-state-none contact-request-state))
(conj [:activity-center/remove-pending-contact-request public-key])
(and blocked? (not was-blocked?))
(conj [:contacts/blocked contact chats-js])))))
(defn update-contacts
[contacts-cljs]
(fn [contacts]
(reduce (fn [contacts {:keys [public-key] :as contact}]
(update contacts public-key merge contact))
contacts
contacts-cljs)))
(rf/defn process-js-contacts
[{:keys [db]} response-js]
(let [contacts-js (oops/oget response-js "contacts")
contacts-cljs (map <-rpc-js contacts-js)
chats-js (.-chatsForContacts response-js)
events (reduce
(prepare-events-for-contact db chats-js)
[[:activity-center.notifications/fetch-unread-count]]
contacts-cljs)]
(js-delete response-js "contacts")
(js-delete response-js "chatsForContacts")
(merge
{:db (update db :contacts/contacts (update-contacts contacts-cljs))
:utils/dispatch-later [{:ms 20 :dispatch [:process-response response-js]}]}
(when (> (count events) 1)
{:dispatch-n events}))))
(rf/defn initialize-contacts (rf/defn initialize-contacts
[cofx] [_]
(contacts-store/fetch-contacts-rpc cofx #(rf/dispatch [:contacts/contacts-loaded %]))) {:json-rpc/call [{:method "wakuext_contacts"
:params []
:js-response true
:on-success #(rf/dispatch [:contacts/contacts-loaded (map <-rpc-js %)])
:on-error #(log/error "failed to fetch contacts" %)}]})
(rf/defn contacts-loaded
{:events [:contacts/contacts-loaded]}
[{:keys [db]} contacts]
{:db (assoc db :contacts/contacts (into {} (map #(vector (:public-key %) %) contacts)))})
(rf/defn add-contact
"Add a contact and set pending to false"
{:events [:contact.ui/add-contact-pressed]}
[{:keys [db]} public-key nickname ens-name]
(when (not= (get-in db [:multiaccount :public-key]) public-key)
{:json-rpc/call [{:method "wakuext_addContact"
:params [{:id public-key :nickname nickname :ensName ens-name}]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to add contact" public-key %)}]}))
(rf/defn remove-contact
"Remove a contact from current account's contact list"
{:events [:contact.ui/remove-contact-pressed]}
[{:keys [db]} {:keys [public-key]}]
{:db (-> db
(assoc-in [:contacts/contacts public-key :added?] false)
(assoc-in [:contacts/contacts public-key :contact-request-state]
constants/contact-request-state-none))
:json-rpc/call [{:method "wakuext_retractContactRequest"
:params [{:id public-key}]
:on-success #(log/debug "contact removed successfully")
:on-error #(log/error "failed to remove contact" public-key %)}]})
(rf/defn update-nickname
{:events [:contacts/update-nickname]}
[_ public-key nickname]
{:json-rpc/call [{:method "wakuext_setContactLocalNickname"
:params [{:id public-key :nickname nickname}]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to set contact nickname " public-key nickname %)}]})
(rf/defn block
[_ contact-id on-success]
{:json-rpc/call [{:method "wakuext_blockContact"
:params [contact-id]
:js-response true
:on-success on-success
:on-error #(log/error "failed to block contact" % contact-id)}]})
(rf/defn unblock
[_ contact-id on-success]
{:json-rpc/call [{:method "wakuext_unblockContact"
:params [contact-id]
:on-success on-success
:js-response true
:on-error #(log/error "failed to unblock contact" % contact-id)}]})

View File

@ -69,11 +69,12 @@
(defn preview-channel (defn preview-channel
[] []
[rn/view [rn/keyboard-avoiding-view {:style {:flex 1}}
{:background-color (colors/theme-colors colors/white colors/neutral-90) [rn/view
:flex 1} {:background-color (colors/theme-colors colors/white colors/neutral-90)
[rn/flat-list :flex 1}
{:flex 1 [rn/flat-list
:keyboardShouldPersistTaps :always {:flex 1
:header [cool-preview] :keyboardShouldPersistTaps :always
:key-fn str}]]) :header [cool-preview]
:key-fn str}]]])

View File

@ -0,0 +1,73 @@
(ns status-im2.contexts.quo-preview.list-items.user-list
(:require [react-native.core :as rn]
[reagent.core :as reagent]
[quo2.foundations.colors :as colors]
[status-im2.contexts.quo-preview.preview :as preview]
[quo2.components.list-items.user-list :as user-list]
[utils.address :as address]))
(def descriptor
[{:label "Primary name"
:key :primary-name
:type :text
:limit 24}
{:label "Secondary name"
:key :secondary-name
:type :text}
{:label "Chat key"
:key :chat-key
:type :text}
{:label "Is contact?"
:key :contact?
:type :boolean}
{:label "Is verified?"
:key :verified?
:type :boolean}
{:label "Is untrustworthy?"
:key :untrustworthy?
:type :boolean}
{:label "Online?"
:key :online?
:type :boolean}
{:label "Accessory:"
:key :accessory
:type :select
:options [{:key {:type :options}
:value "Options"}
{:key {:type :checkbox}
:value "Checkbox"}
{:key {:type :close}
:value "Close"}]}])
(defn cool-preview
[]
(let [state (reagent/atom {:primary-name "Alisher Yakupov"
:short-chat-key (address/get-shortened-key
"zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N")
:ens-verified true
:contact? false
:verified? false
:untrustworthy? false
:online? false})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[rn/view {:flex 1}
[preview/customizer state descriptor]]
[rn/view
{:padding-vertical 60
:padding--horizontal 15
:justify-content :center}
[user-list/user-list @state]]]])))
(defn preview-user-list
[]
[rn/keyboard-avoiding-view {:style {:flex 1}}
[rn/view
{:background-color (colors/theme-colors colors/white colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
:keyboardShouldPersistTaps :always
:header [cool-preview]
:key-fn str}]]])

View File

@ -7,7 +7,6 @@
[quo2.theme :as theme] [quo2.theme :as theme]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im2.contexts.quo-preview.animated-header-list.animated-header-list :as animated-header-list] [status-im2.contexts.quo-preview.animated-header-list.animated-header-list :as animated-header-list]
[status-im2.contexts.quo-preview.avatars.account-avatar :as account-avatar] [status-im2.contexts.quo-preview.avatars.account-avatar :as account-avatar]
[status-im2.contexts.quo-preview.avatars.channel-avatar :as channel-avatar] [status-im2.contexts.quo-preview.avatars.channel-avatar :as channel-avatar]
@ -74,7 +73,8 @@
[status-im2.contexts.quo-preview.wallet.lowest-price :as lowest-price] [status-im2.contexts.quo-preview.wallet.lowest-price :as lowest-price]
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount] [status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
[status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown] [status-im2.contexts.quo-preview.wallet.network-breakdown :as network-breakdown]
[status-im2.contexts.quo-preview.wallet.token-overview :as token-overview])) [status-im2.contexts.quo-preview.wallet.token-overview :as token-overview]
[status-im2.contexts.quo-preview.list-items.user-list :as user-list]))
(def screens-categories (def screens-categories
{:foundations [{:name :shadows {:foundations [{:name :shadows
@ -166,7 +166,10 @@
:component channel/preview-channel} :component channel/preview-channel}
{:name :preview-lists {:name :preview-lists
:insets {:top false} :insets {:top false}
:component preview-lists/preview-preview-lists}] :component preview-lists/preview-preview-lists}
{:name :user-list
:insets {:top false}
:component user-list/preview-user-list}]
:markdown [{:name :texts :markdown [{:name :texts
:insets {:top false} :insets {:top false}
:component text/preview-text}] :component text/preview-text}]
@ -289,32 +292,29 @@
(defn main-screen (defn main-screen
[] []
(fn [] (fn []
[safe-area/consumer [rn/scroll-view
(fn [insets] {:flex 1
[rn/scroll-view :padding-bottom 8
{:flex 1 :padding-horizontal 16
:padding-top (:top insets) :background-color (colors/theme-colors colors/white colors/neutral-90)}
:padding-bottom 8 [theme-switcher]
:padding-horizontal 16 [quo2-text/text {:size :heading-1} "Preview Quo2 Components"]
:background-color (colors/theme-colors colors/white colors/neutral-90)} [rn/view
[theme-switcher] (map (fn [category]
[quo2-text/text {:size :heading-1} "Preview Quo2 Components"] ^{:key (get category 0)}
[rn/view [rn/view {:style {:margin-vertical 8}}
(map (fn [category] [quo2-text/text
^{:key (get category 0)} {:weight :semi-bold
[rn/view {:style {:margin-vertical 8}} :size :heading-2}
[quo2-text/text (clojure.core/name (key category))]
{:weight :semi-bold (for [{:keys [name]} (val category)]
:size :heading-2} ^{:key name}
(clojure.core/name (key category))] [quo2-button/button
(for [{:keys [name]} (val category)] {:test-ID (str "quo2-" name)
^{:key name} :style {:margin-vertical 8}
[quo2-button/button :on-press #(re-frame/dispatch [:navigate-to name])}
{:test-ID (str "quo2-" name) (clojure.core/name name)])])
:style {:margin-vertical 8} (sort screens-categories))]]))
:on-press #(re-frame/dispatch [:navigate-to name])}
(clojure.core/name name)])])
(sort screens-categories))]])]))
(def main-screens (def main-screens
[{:name :quo2-preview [{:name :quo2-preview

View File

@ -5,23 +5,19 @@
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview] [status-im2.contexts.quo-preview.preview :as preview]
[status-im.utils.utils :as utils])) [utils.address :as address]))
(def descriptor (def descriptor
[{:label "Profile name" [{:label "Primary name"
:key :profile-name :key :primary-name
:type :text :type :text
:limit 24} :limit 24}
{:label "Nickname" {:label "Secondary name"
:key :nickname :key :secondary-name
:type :text} :type :text}
{:label "Chat key" {:label "Chat key"
:key :chat-key :key :chat-key
:type :text} :type :text}
{:label "ENS name"
:key :ens-name
:type :text
:suffix ".eth"}
{:label "Time" {:label "Time"
:key :time-str :key :time-str
:type :text :type :text
@ -38,15 +34,14 @@
(defn cool-preview (defn cool-preview
[] []
(let [state (reagent/atom {:profile-name "Alisher Yakupov" (let [state (reagent/atom {:primary-name "Alisher Yakupov"
:nickname "" :seconadary-name ""
:short-chat-key (utils/get-shortened-address :short-chat-key (address/get-shortened-key
"zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N") "zQ3ssgRy5TtB47MMiMKMKaGyaawkCgMqqbrnAUYrZJ1sgt5N")
:time-str "09:30" :time-str "09:30"
:ens-name "" :contact? false
:contact? false :verified? false
:verified? false :untrustworthy? false})]
:untrustworthy? false})]
(fn [] (fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150} [rn/view {:padding-bottom 150}
@ -58,19 +53,16 @@
:justify-content :center} :justify-content :center}
[rn/view [rn/view
[text/text "Author:"] [text/text "Author:"]
[quo2/author @state]] [quo2/author @state]]]]])))
[rn/view {:height 50}]
[rn/view
[text/text "Display Name:"]
[quo2/display-name @state]]]]])))
(defn preview-author (defn preview-author
[] []
[rn/view [rn/keyboard-avoiding-view {:style {:flex 1}}
{:background-color (colors/theme-colors colors/white colors/neutral-90) [rn/view
:flex 1} {:background-color (colors/theme-colors colors/white colors/neutral-90)
[rn/flat-list :flex 1}
{:flex 1 [rn/flat-list
:keyboardShouldPersistTaps :always {:flex 1
:header [cool-preview] :keyboardShouldPersistTaps :always
:key-fn str}]]) :header [cool-preview]
:key-fn str}]]])

View File

@ -53,18 +53,15 @@
:channel-name "Channel" :channel-name "Channel"
:type :group-avatar})] :type :group-avatar})]
(fn [] (fn []
(let [contacts {example-pk {:public-key example-pk (let [contacts {example-pk {:public-key example-pk
:names {:three-words-name :primary-name "Automatic incompatible Coati"
"Automatic incompatible Coati"} :photo example-photo}
:photo example-photo} example-pk2 {:public-key example-pk2
example-pk2 {:public-key example-pk2 :primary-name "Clearcut Flickering Rattlesnake"
:names {:three-words-name :photo example-photo2}}
"Clearcut Flickering Rattlesnake"}
:photo example-photo2}}
contacts-public-keys (map (fn [{:keys [public-key]}] contacts-public-keys (map (fn [{:keys [public-key]}]
{:key public-key {:key public-key
:value (multiaccounts/displayed-name :value (get-in contacts [public-key :primary-name])})
(get contacts public-key))})
(vals contacts)) (vals contacts))
current-username (if (seq (:contact @state)) current-username (if (seq (:contact @state))
(->> @state (->> @state

View File

@ -338,7 +338,7 @@
(defn filter-selected-contacts (defn filter-selected-contacts
[selected-contacts contacts] [selected-contacts contacts]
(filter #(:added (contacts %)) selected-contacts)) (filter #(:added? (contacts %)) selected-contacts))
(re-frame/reg-sub (re-frame/reg-sub
:selected-contacts-count :selected-contacts-count
@ -399,10 +399,14 @@
:<- [:contacts/blocked-set] :<- [:contacts/blocked-set]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:multiaccount] :<- [:multiaccount]
(fn [[{:keys [users community-id] :as chat} blocked all-contacts :<- [:communities/current-community-members]
{:keys [public-key] :as current-multiaccount}]] (fn
(let [community-members @(re-frame/subscribe [:communities/community-members community-id]) [[{:keys [users] :as chat}
mentionable-users (mentions/get-mentionable-users chat blocked
all-contacts
{:keys [public-key] :as current-multiaccount}
community-members]]
(let [mentionable-users (mentions/get-mentionable-users chat
all-contacts all-contacts
current-multiaccount current-multiaccount
community-members) community-members)

View File

@ -50,6 +50,13 @@
(fn [communities [_ id]] (fn [communities [_ id]]
(get-in communities [id :members]))) (get-in communities [id :members])))
(re-frame/reg-sub
:communities/current-community-members
:<- [:chats/current-chat]
:<- [:communities]
(fn [[{:keys [community-id]} communities]]
(get-in communities [community-id :members])))
(re-frame/reg-sub (re-frame/reg-sub
:communities/sorted-community-members :communities/sorted-community-members
(fn [[_ community-id]] (fn [[_ community-id]]

View File

@ -70,14 +70,16 @@
:contacts/active :contacts/active
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts] (fn [contacts]
(contact.db/get-active-contacts contacts))) (->> contacts
(filter (fn [[_ contact]] (:active? contact)))
contact.db/sort-contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-sections :contacts/active-sections
:<- [:contacts/active] :<- [:contacts/active]
(fn [contacts] (fn [contacts]
(->> contacts (->> contacts
(group-by #(string/upper-case (ffirst (:two-names %)))) (group-by #(string/upper-case (first (:primary-name %))))
sort sort
(mapv (fn [[title items]] {:title title :data items}))))) (mapv (fn [[title items]] {:title title :data items})))))
@ -117,7 +119,7 @@
:allow-new-users? :allow-new-users?
(< selected-contacts-count (< selected-contacts-count
(dec constants/max-group-chat-participants)))) (dec constants/max-group-chat-participants))))
(group-by (comp (fnil string/upper-case "") first :alias)) (group-by (comp (fnil string/upper-case "") first :primary-name))
(sort-by first) (sort-by first)
(map (fn [[title data]] (map (fn [[title data]]
{:title title {:title title
@ -135,8 +137,14 @@
(fn [contacts] (fn [contacts]
(->> contacts (->> contacts
(filter (fn [[_ contact]] (filter (fn [[_ contact]]
(:blocked contact))) (:blocked? contact)))
(contact.db/sort-contacts)))) contact.db/sort-contacts)))
(re-frame/reg-sub
:contacts/blocked-set
:<- [:contacts/blocked]
(fn [contacts]
(into #{} (map :public-key contacts))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/blocked-count :contacts/blocked-count
@ -145,14 +153,12 @@
(count blocked-contacts))) (count blocked-contacts)))
(defn filter-recipient-contacts (defn filter-recipient-contacts
[search-filter {:keys [names]}] [search-filter {:keys [primary-name secondary-name]}]
(let [{:keys [nickname three-words-name ens-name]} names] (or
(or (when primary-name
(when ens-name (string/includes? (string/lower-case (str primary-name)) search-filter))
(string/includes? (string/lower-case (str ens-name)) search-filter)) (when secondary-name
(string/includes? (string/lower-case three-words-name) search-filter) (string/includes? (string/lower-case (str secondary-name)) search-filter))))
(when nickname
(string/includes? (string/lower-case nickname) search-filter)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-with-ens-names :contacts/active-with-ens-names
@ -195,7 +201,7 @@
(fn [[_ identity] _] (fn [[_ identity] _]
[(re-frame/subscribe [:contacts/contact-by-identity identity])]) [(re-frame/subscribe [:contacts/contact-by-identity identity])])
(fn [[contact] _] (fn [[contact] _]
(:added contact))) (:added? contact)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-blocked? :contacts/contact-blocked?
@ -248,7 +254,7 @@
:contacts/all-contacts-not-in-current-chat :contacts/all-contacts-not-in-current-chat
:<- [::query-current-chat-contacts remove] :<- [::query-current-chat-contacts remove]
(fn [contacts] (fn [contacts]
(filter :added contacts))) (filter :added? contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/current-chat-contacts :contacts/current-chat-contacts

View File

@ -11,8 +11,9 @@
:mutual? true :mutual? true
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true :added? true
:name "slim.shady" :name "slim.shady"
:primary-name "rslim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Real Slim Shady" :alias "Real Slim Shady"
@ -21,18 +22,20 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false :blocked? false
:active? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:has-added-us true :has-added-us? true
:contact-request-state 1} :contact-request-state 1}
"0xtest2" {:last-updated 1672582629695 "0xtest2" {:last-updated 1672582629695
:mutual? true :mutual? true
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true :added? true
:name "slim.shady" :name "slim.shady"
:primary-name "fslim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Fake Slim Shady" :alias "Fake Slim Shady"
@ -41,18 +44,20 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false :blocked? false
:active? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:has-added-us true :has-added-us? true
:contact-request-state 1} :contact-request-state 1}
"0xtest3" {:last-updated 1672582629695 "0xtest3" {:last-updated 1672582629695
:mutual? true :mutual? true
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true :added? true
:name "slim.shady" :name "slim.shady"
:primary-name "islim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Instant noodles" :alias "Instant noodles"
@ -61,11 +66,12 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false :blocked? false
:active? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:has-added-us true :has-added-us? true
:contact-request-state 1}}}) :contact-request-state 1}}})
(def expected-sorted-contacts (def expected-sorted-contacts
@ -76,9 +82,9 @@
:blocked? false :blocked? false
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true
:name "slim.shady"
:added? true :added? true
:name "slim.shady"
:primary-name "fslim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Fake Slim Shady" :alias "Fake Slim Shady"
@ -87,17 +93,11 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false
:allow-new-users? true :allow-new-users? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:names {:nickname nil :has-added-us? true
:display-name ""
:three-words-name "Fake Slim Shady"
:ens-name "slim.shady"}
:two-names ["slim.shady" "Fake Slim Shady"]
:has-added-us true
:contact-request-state 1}]} :contact-request-state 1}]}
{:title "I" {:title "I"
:data [{:active? true :data [{:active? true
@ -106,9 +106,9 @@
:blocked? false :blocked? false
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true
:name "slim.shady"
:added? true :added? true
:name "slim.shady"
:primary-name "islim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Instant noodles" :alias "Instant noodles"
@ -117,17 +117,11 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false
:allow-new-users? true :allow-new-users? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:names {:nickname nil :has-added-us? true
:display-name ""
:three-words-name "Instant noodles"
:ens-name "slim.shady"}
:two-names ["slim.shady" "Instant noodles"]
:has-added-us true
:contact-request-state 1}]} :contact-request-state 1}]}
{:title "R" {:title "R"
:data [{:active? true :data [{:active? true
@ -136,9 +130,9 @@
:blocked? false :blocked? false
:contactRequestClock 0 :contactRequestClock 0
:images {} :images {}
:added true
:name "slim.shady"
:added? true :added? true
:name "slim.shady"
:primary-name "rslim.shady"
:Removed false :Removed false
:trustStatus 0 :trustStatus 0
:alias "Real Slim Shady" :alias "Real Slim Shady"
@ -147,17 +141,11 @@
:display-name "" :display-name ""
:ens-verified true :ens-verified true
:socialLinks nil :socialLinks nil
:blocked false
:allow-new-users? true :allow-new-users? true
:verificationStatus 0 :verificationStatus 0
:lastUpdatedLocally 1672582563204 :lastUpdatedLocally 1672582563204
:public-key "0xtest" :public-key "0xtest"
:names {:nickname nil :has-added-us? true
:display-name ""
:three-words-name "Real Slim Shady"
:ens-name "slim.shady"}
:two-names ["slim.shady" "Real Slim Shady"]
:has-added-us true
:contact-request-state 1}]}]) :contact-request-state 1}]}])
(h/deftest-sub :contacts/sorted-and-grouped-by-first-letter (h/deftest-sub :contacts/sorted-and-grouped-by-first-letter
@ -182,5 +170,4 @@
(dissoc contact :identicon)) (dissoc contact :identicon))
%))) %)))
(rf/sub [sub-name]))] (rf/sub [sub-name]))]
(is (= expected-sorted-contacts contact-list-without-identicons))))) (is (= expected-sorted-contacts contact-list-without-identicons)))))

View File

@ -1,11 +1,9 @@
(ns status-im2.subs.multiaccount (ns status-im2.subs.multiaccount
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
[clojure.set :as set]
[clojure.string :as string] [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.fleet.core :as fleet] [status-im.fleet.core :as fleet]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.db :as multiaccounts.db] [status-im.multiaccounts.db :as multiaccounts.db]
[status-im.utils.image-server :as image-server] [status-im.utils.image-server :as image-server]
[utils.security.core :as security])) [utils.security.core :as security]))
@ -20,11 +18,7 @@
:multiaccount/contact :multiaccount/contact
:<- [:multiaccount] :<- [:multiaccount]
(fn [current-account] (fn [current-account]
(some-> (select-keys current-account [:name :preferred-name :public-key :identicon :image :images])))
current-account
(select-keys [:name :preferred-name :public-key :identicon :image :images])
(set/rename-keys {:name :alias})
(multiaccounts/contact-with-names))))
(re-frame/reg-sub (re-frame/reg-sub
:multiaccount/preferred-name :multiaccount/preferred-name

View File

@ -153,7 +153,6 @@
(reg-root-key-sub :contacts/current-contact-ens-name :contacts/ens-name) (reg-root-key-sub :contacts/current-contact-ens-name :contacts/ens-name)
(reg-root-key-sub :contacts/new-identity :contacts/new-identity) (reg-root-key-sub :contacts/new-identity :contacts/new-identity)
(reg-root-key-sub :group/selected-contacts :group/selected-contacts) (reg-root-key-sub :group/selected-contacts :group/selected-contacts)
(reg-root-key-sub :contacts/blocked-set :contacts/blocked)
(reg-root-key-sub :contacts/search-query :contacts/search-query) (reg-root-key-sub :contacts/search-query :contacts/search-query)
;;wallet ;;wallet

View File

@ -3,14 +3,14 @@
(:require [status-im.ethereum.core :as ethereum] (:require [status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55])) [status-im.ethereum.eip55 :as eip55]))
(defn get-shortened-address (defn get-shortened-key
"Takes first and last 4 digits from address including leading 0x "Takes first and last 4 digits from address including leading 0x
and adds unicode ellipsis in between" and adds unicode ellipsis in between"
[address] [value]
(when address (when value
(str (subs address 0 6) "\u2026" (subs address (- (count address) 3) (count address))))) (str (subs value 0 6) "\u2026" (subs value (- (count value) 3) (count value)))))
(defn get-shortened-checksum-address (defn get-shortened-checksum-address
[address] [address]
(when address (when address
(get-shortened-address (eip55/address->checksum (ethereum/normalized-hex address))))) (get-shortened-key (eip55/address->checksum (ethereum/normalized-hex address)))))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>", "_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.132.3", "version": "feature/contacts-fields",
"commit-sha1": "999d8c0ee0f2274c58b5a2de3beddab7feaabd16", "commit-sha1": "dde6e6570e3e1035b2d56b2db3695ddbc72909c7",
"src-sha256": "0qcpbhkhy8l3cq1055gnxghi7292jnd7xznl6s6h92pcg37y1jzc" "src-sha256": "1h0wcmi41svyky5w3059nzbyyzzldir1bf01wgzhbykvnn26sjhp"
} }