[#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
: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
{:color colors/neutral-50
:margin-horizontal 4})
@ -27,12 +19,6 @@
{:color colors/neutral-50
: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
{:margin-left 4})

View File

@ -3,97 +3,64 @@
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[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 "·")
(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
[{: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>
(fn []
(let [ens? (-> ens-name string/blank? not)
nickname? (-> nickname string/blank? not)]
[rn/view {:style style/container}
(if ens?
[rn/view {:style style/container}
[:<>
[text/text
{: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
{:weight :semi-bold
{:size :paragraph-2
:style style/middle-dot-nickname}
middle-dot]
[text/text
{:weight :medium
:size :paragraph-2
:style (style/ens-text)}
ens-name]
[:<>
(when nickname?
[:<>
[text/text
{:weight :semi-bold
:size :paragraph-2
:style (style/nickname-text)}
nickname]
[text/text
{:size :paragraph-2
:style style/middle-dot-nickname}
middle-dot]])
[text/text
{:weight (if nickname? :medium :semi-bold)
:size :paragraph-2
:style (style/profile-name-text nickname?)}
profile-name]])
(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])
:style {:color (colors/theme-colors colors/neutral-60 colors/neutral-40)}}
secondary-name]])]
(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 verified?
[text/text
{:monospace true
:size :paragraph-2
:accessibility-label :message-timestamp
:style (style/time-text ens?)}
time-str]]))])
{:monospace true
:size :paragraph-2
:style style/chat-key-text}
short-chat-key])
(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.tag
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 button quo2.components.buttons.button/button)
@ -93,7 +94,6 @@
(def filter quo2.components.selectors.filter.view/view)
(def skeleton quo2.components.loaders.skeleton/skeleton)
(def author quo2.components.messages.author.view/author)
(def display-name quo2.components.messages.author.view/display-name)
;;;; 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 menu-item quo2.components.list-items.menu-item/menu-item)
(def preview-list quo2.components.list-items.preview-list/preview-list)
(def user-list quo2.components.list-items.user-list/user-list)
;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-log.view/view)

View File

@ -19,8 +19,8 @@
(defn- wrap-key-fn
[f]
(fn [data index]
{:post [(some? %)]}
(f data index)))
(when f
(f data index))))
(defn base-list-props
[{: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]
[status-im.add-new.db :as db]
[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.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]

View File

@ -41,11 +41,11 @@
(rf/defn 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)
new-text (mentions/new-input-text-with-mention cofx user)
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
cofx
{:db (-> db
@ -63,15 +63,14 @@
;; NOTE(roman): on-text-input event is not dispatched when we change input
;; programmatically, so we have to call `on-text-input` manually
(mentions/on-text-input
(let [match-len (count match)
searched-text-len (count searched-text)
start (inc at-sign-idx)
end (+ start match-len)]
(let [match-len (count match)
start (inc at-sign-idx)
end (+ start match-len)]
{:new-text match
:previous-text searched-text
:start start
:end end}))
(mentions/recheck-at-idxs {alias user}))))
(mentions/recheck-at-idxs {primary-name user}))))
(rf/defn disable-chat-cooldown
"Turns off chat cooldown (protection against message spamming)"

View File

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

View File

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

View File

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

View File

@ -2,10 +2,8 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[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.transport.message.protocol :as protocol]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.platform :as platform]
[status-im.utils.types :as types]
[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
(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
[{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
(let [{:keys [replace from clock-value] :as message}
@ -118,7 +96,7 @@
(defn receive-many
[{:keys [db]} ^js response-js]
(let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10))
{:keys [db senders]}
{:keys [db]}
(reduce reduce-js-messages
{:db db :chats #{} :senders {} :transactions #{}}
messages-js)]
@ -128,9 +106,7 @@
:utils/dispatch-later
(concat [{:ms 20 :dispatch [:process-response response-js]}]
(when (and (:current-chat-id db) (= "active" (:app-state 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)]}]))}))
[{:ms 100 :dispatch [:chat/mark-all-as-read (:current-chat-id db)]}]))}))
(rf/defn update-db-message-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-im.contact.db :as contact.db]
[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]
[status-im.utils.types :as types]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.navigation.events :as navigation]))
(rf/defn clean-up-chat
[{:keys [db] :as cofx}
[{:keys [db]}
public-key
{:keys [chat-id
unviewed-messages-count
@ -35,18 +35,18 @@
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
(rf/defn contact-blocked
{:events [::contact-blocked]}
[{:keys [db] :as cofx} {:keys [public-key]} chats]
(let [fxs (when chats
{:events [:contacts/blocked]}
[{:keys [db] :as cofx} {:keys [public-key]} chats-js]
(let [fxs (when chats-js
(map #(->> (chats-store/<-rpc %)
(clean-up-chat public-key))
(types/js->clj chats)))]
(types/js->clj chats-js)))]
(apply rf/merge
cofx
{:db (-> db
(update :chats dissoc 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]
:clear-message-notifications
[[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
@ -59,19 +59,15 @@
(let [contact (-> (contact.db/public-key->contact
(:contacts/contacts db)
public-key)
(assoc :blocked true
:added false))
(assoc :blocked? true
:added? false))
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))]
(rf/merge cofx
{:db (-> db
;; 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))}
{:db (assoc-in db [:contacts/contacts public-key] contact)}
(contacts-store/block
public-key
(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 [:hide-popover])))
;; reset navigation to avoid going back to non existing one to one chat
@ -80,13 +76,11 @@
(navigation/navigate-back)))))
(rf/defn contact-unblocked
{:events [::contact-unblocked]}
{:events [:contacts/unblocked]}
[{:keys [db]} contact-id]
(let [contact (-> (get-in db [:contacts/contacts contact-id])
(assoc :blocked false))]
{:db (-> db
(update :contacts/blocked disj contact-id)
(assoc-in [:contacts/contacts contact-id] contact))}))
(assoc :blocked? false))]
{:db (assoc-in db [:contacts/contacts contact-id] contact)}))
(rf/defn unblock-contact
{:events [:contact.ui/unblock-contact-pressed]}
@ -94,4 +88,4 @@
(contacts-store/unblock
cofx
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
(: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]
[status-im2.navigation.events :as navigation]))

View File

@ -1,86 +1,6 @@
(ns status-im.contact.core
(:require [re-frame.core :as re-frame]
[status-im2.constants :as constants]
[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 %])))
(:require [utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]))
(rf/defn open-contact-toggle-list
{:events [:contact.ui/start-group-chat-pressed]}
@ -90,18 +10,3 @@
:group/selected-contacts #{}
:new-chat-name "")}
(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]
[status-im2.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]))
(defn public-key->new-contact
[public-key]
(let [alias (gfycat/generate-gfy public-key)]
{:alias alias
:name alias
:identicon (identicon/identicon public-key)
:public-key public-key}))
{:alias alias
:name alias
:primary-name alias
:identicon (identicon/identicon public-key)
:public-key public-key}))
(defn public-key-and-ens-name->new-contact
[public-key ens-name]
@ -43,84 +43,45 @@
(defn sort-contacts
[contacts]
(sort (fn [c1 c2]
(let [name1 (first (:two-names c1))
name2 (first (:two-names c2))]
(compare (string/lower-case name1)
(string/lower-case name2))))
(let [name1 (:primary-name c1)
name2 (:primary-name c2)]
(when (and name1 name2)
(compare (string/lower-case name1)
(string/lower-case name2)))))
(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
[{:keys [contacts]} all-contacts query-fn]
(let [participant-set (into #{} (filter identity) contacts)]
(query-fn (comp participant-set :public-key) (vals all-contacts))))
(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->
current-account
(select-keys [:name :preferred-name :public-key :identicon :images])
(set/rename-keys {:name :alias
:preferred-name :name}))
(set/rename-keys {:name :alias :preferred-name :name})
(assoc :primary-name (or preferred-name name)))
all-contacts (cond-> contacts
current-contact
(assoc public-key current-contact))]
(->> members
(map #(or (get all-contacts %)
(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 %))
(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
([contact] (enrich-contact contact nil nil))
([{:keys [public-key] :as contact} setting own-public-key]
(cond-> (-> contact
(dissoc :ens-verified-at :ens-verification-retries)
(assoc :blocked? (:blocked contact)
:active? (active? contact)
:added? (added? contact))
(multiaccounts/contact-with-names))
(cond-> contact
(and setting
(not= public-key own-public-key)
(or (= setting constants/profile-pictures-visibility-none)
(and (= setting constants/profile-pictures-visibility-contacts-only)
(not (added? contact)))))
(not (:added? contact)))))
(dissoc :images))))
(defn enrich-contacts
@ -134,15 +95,8 @@
(defn get-blocked-contacts
[contacts]
(reduce (fn [acc {:keys [public-key] :as contact}]
(if (:blocked contact)
(if (:blocked? contact)
(conj acc public-key)
acc))
#{}
contacts))
(defn get-active-contacts
[contacts]
(->> contacts
(filter (fn [[_ contact]]
(active? contact)))
sort-contacts))

View File

@ -20,6 +20,7 @@
{"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
{:last-updated 0
:name "User B"
:primary-name "User B"
:identicon "photo1"
:last-online 0
:public-key
@ -28,6 +29,7 @@
{:last-updated 0
:signed-up? true
:sharing-usage-data? false
:primary-name "User A"
:name "User A"
:identicon "photo2"
:public-key
@ -39,17 +41,20 @@
contacts
current-multiaccount)
[{:name "generated"
:primary-name "generated"
:identicon "generated"
:alias "generated"
:admin? true
:public-key
"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
{:alias "User A"
:primary-name "User A"
:identicon "photo2"
:public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
{:last-updated 0
:name "User B"
:primary-name "User B"
:identicon "photo1"
:last-online 0
: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
[{:keys [db now]}]
{:db (assoc db :app-in-background-since now)
{:db (assoc db :app-in-background-since now)})
;; event not implemented
;; :dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]]
})
(rf/defn app-state-change
{:events [:app-state-change]}

View File

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

View File

@ -3,7 +3,6 @@
[quo.platform :as platform]
[re-frame.core :as re-frame]
[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.native-module.core :as native-module]
[status-im.theme.core :as theme]
@ -12,11 +11,11 @@
[status-im2.constants :as constants]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
[status-im.utils.utils :as utils]
[status-im2.setup.hot-reload :as hot-reload]
[status-im2.common.theme.core :as utils.theme]
[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
(re-frame/reg-fx
@ -24,47 +23,6 @@
(fn [[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
"Use preferred name, display-name, name or alias in that order"
[{:keys [name display-name preferred-name alias public-key ens-verified]}]
@ -74,14 +32,13 @@
name)]
;; Preferred name is our own otherwise we make sure it's verified
(if (or preferred-name (and ens-verified name))
(let [username (stateofus/username ens-name)]
(or username ens-name))
ens-name
(or display-name alias (gfycat/generate-gfy public-key)))))
(defn contact-by-identity
[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
[contact current-multiaccount identity]
@ -89,7 +46,7 @@
(if me?
[(or (:preferred-name current-multiaccount)
(gfycat/generate-gfy identity))]
(contact-two-names contact false))))
[(:primary-name contact) (:secondary-name contact)])))
(def photo-quality-thumbnail :thumbnail)
(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"
:identicon
"data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX///+M2KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdPOdBAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5UBARL8TK8AAAAASUVORK5CYII="
:added true
:added? true
:last-online 0
:public-key
"0x04d6e56a475cd35f512d6ce0bf76c2c2af435c85ff48c2b9bdefd129f620e051a436f50961eae5717b2a750e59c3f5b60647d927da46d0b8b11621640b5678fc24"}
@ -16,7 +16,7 @@
:name "rv"
:identicon
"data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////VjNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwYzy6AAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6IYA4bRtf+EAAAAASUVORK5CYII="
:added true
:added? true
:last-online 0
:public-key
"0x043ae31038ff45a31b096a91d3f8290e079366fbbae76a00fbbd349cd0e5b8d7598965d206772ec4504f68908649a08383cdc51a52cdae5e9ccc744ace4d37020f"}])

View File

@ -2,7 +2,7 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[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.react :as react]
[utils.re-frame :as rf]
@ -101,8 +101,9 @@
{:db (-> db
(assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name))
:json-rpc/call [{:method "wakuext_buildContact"
:params [identity]
:on-success #(rf/dispatch [:contacts/contact-built
identity
(data-store.contacts/<-rpc %)])}]})))
:json-rpc/call [{:method "wakuext_buildContact"
:params [identity]
:js-response true
:on-success #(rf/dispatch [:contacts/contact-built
identity
(data-store.contacts/<-rpc-js %)])}]})))

View File

@ -7,10 +7,9 @@
[status-im.chat.models.reactions :as models.reactions]
[status-im.communities.core :as models.communities]
[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.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.messages :as data-store.messages]
[status-im.data-store.reactions :as data-store.reactions]
@ -84,15 +83,7 @@
(models.pairing/handle-installations installations-clj)))
(seq contacts)
(let [contacts-clj (types/js->clj contacts)
^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)))
(models.contact/process-js-contacts cofx response-js)
(seq communities)
(let [communities-clj (types/js->clj communities)]

View File

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

View File

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

View File

@ -30,10 +30,10 @@
(defn contacts-list-item
[{: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
{:title first-name
:subtitle second-name
{:title primary-name
:subtitle secondary-name
:icon [chat-icon.screen/contact-icon-contacts-tab
(multiaccounts/displayed-photo contact)]
:accessory :checkbox

View File

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

View File

@ -12,10 +12,10 @@
(defn contacts-list-item
[{: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
{:title first-name
:subtitle second-name
{:title primary-name
:subtitle secondary-name
:icon [chat-icon.screen/profile-photo-plus-dot-view
{:public-key public-key
:photo-path (multiaccounts/displayed-photo contact)}]

View File

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

View File

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

View File

@ -20,45 +20,44 @@
(defn member-sheet
[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
{:theme :accent
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)]
:title first-name
:subtitle (i18n/label :t/view-profile)
:accessibility-label :view-chat-details-button
:chevron true
: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
[:chat.ui/show-profile
(: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)])}])]))
[:group-chats.ui/remove-member-pressed chat-id
(:public-key member)])}])])
(defn render-member
[{: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
(merge
{:title first-name
:subtitle second-name
{:title primary-name
:subtitle secondary-name
:accessibility-label :member-item
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)]

View File

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

View File

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

View File

@ -3,33 +3,22 @@
[quo2.core :as quo2]
[quo2.foundations.colors :as quo2.colors]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[react-native.core :as rn]
[utils.re-frame :as rf]
[clojure.string :as string]
[status-im2.common.contact-list.view :as contact-list]
[quo2.components.markdown.text :as text]
[status-im.ui.components.invite.events :as invite.events]
[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
[event]
(rf/dispatch [:bottom-sheet/hide])
(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
[]
[rn/view
@ -59,28 +48,34 @@
:on-press #(hide-sheet-and-dispatch [:open-modal :new-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
[]
[:f>
(fn []
(let [contacts (rf/sub
[:contacts/sorted-and-grouped-by-first-letter])
selected-contacts-count (rf/sub [:selected-contacts-count])
selected-contacts (rf/sub [:group/selected-contacts])
window-height (rf/sub [:dimensions/window-height])
one-contact-selected? (= selected-contacts-count 1)
contacts-selected? (pos? selected-contacts-count)
{:keys [names public-key]} (when one-contact-selected?
(rf/sub [:contacts/contact-by-identity
(first selected-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)]
(let [contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter])
selected-contacts-count (rf/sub [:selected-contacts-count])
selected-contacts (rf/sub [:group/selected-contacts])
window-height (rf/sub [:dimensions/window-height])
one-contact-selected? (= selected-contacts-count 1)
contacts-selected? (pos? selected-contacts-count)
{:keys [primary-name public-key]} (when one-contact-selected?
(rf/sub [:contacts/contact-by-identity
(first selected-contacts)]))
no-contacts? (empty? contacts)]
[rn/view {:style {:height (* window-height 0.9)}}
[quo2/button
{:type :grey
@ -102,20 +97,19 @@
:weight :regular
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-40 quo2.colors/neutral-50)}}
(i18n/label :t/selected-count-from-max
{:selected (inc selected-contacts-count)
{:selected selected-contacts-count
:max constants/max-group-chat-participants})])]
[rn/view
{:style {:flex 1}}
(if no-contacts?
[no-contacts-view]
[contact-list/contact-list
{:icon :check
:group nil
:added? added?
:search? false
:start-a-new-chat? true
:on-toggle on-toggle}
70])]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections (rf/sub [:contacts/filtered-active-sections])
:render-section-header-fn contact-list/contacts-section-header
:content-container-style {:padding-bottom 70}
:render-fn contact-item-render}])]
(when contacts-selected?
[button/button
{:type :primary
@ -128,5 +122,5 @@
(hide-sheet-and-dispatch [:navigate-to
:new-group])))}
(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))])]))])

View File

@ -76,7 +76,6 @@
(defn on-text-change
[val chat-id]
(println "on=text-change" val)
(swap! input-texts assoc chat-id val)
;;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]))

View File

@ -1,51 +1,2 @@
(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]))
(ns status-im.ui2.screens.chat.composer.mentions)
(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
[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
(defview message-author-name
[from opts max-length]
(letsubs [contact-with-names [:contacts/contact-by-identity from]]
(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
[display-name contact timestamp show-key?]
[rn/view {:style {:flex-direction :row}}

View File

@ -1,23 +1,6 @@
(ns status-im2.common.contact-list.view
(: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]))
(:require [quo2.core :as quo]))
(defn contacts-section-header
[{:keys [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
(: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]
[reagent.core :as reagent]))
(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}])])]))
[utils.address :as address]))
(defn contact-list-item
[item _ _ {:keys [start-a-new-chat? on-toggle group] :as extra-data}]
(let [{:keys [public-key compressed-key ens-verified
added? images]} item
display-name (first
(rf/sub
[:contacts/contact-two-names-by-identity
public-key]))
photo-path (when (seq images)
(rf/sub [:chats/photo-path public-key]))
online? (rf/sub [:visibility-status-updates/online?
public-key])
user-selected? (rf/sub [:is-contact-selected? public-key])
{:keys [contacts admins]} group
member? (contains? contacts public-key)
current-pk (rf/sub [:multiaccount/public-key])
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?])]))
[{:keys [on-press on-long-press accessory]}
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}]
(let [photo-path (rf/sub [:chats/photo-path public-key])
online? (rf/sub [:visibility-status-updates/online? public-key])]
[quo/user-list
{:short-chat-key (address/get-shortened-key (or compressed-key public-key))
:primary-name primary-name
:secondary-name secondary-name
:photo-path photo-path
:online? online?
:verified? ens-verified
:contact? added?
:on-press on-press
:on-long-press on-long-press
:accessory accessory}]))

View File

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

View File

@ -5,7 +5,6 @@
[quo2.foundations.colors :as colors]
[status-im.multiaccounts.core :as multiaccounts]
[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.re-frame :as rf]))
@ -18,7 +17,7 @@
:size :small
:style style/user-avatar-tag
:text-style style/user-avatar-tag-text}
(activity-center.utils/contact-name contact)
(:primary-name contact)
(multiaccounts/displayed-photo contact)]))
(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-im.chat.models.loading :as loading]
[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.utils.clocks :as utils.clocks]))
[status-im.utils.clocks :as utils.clocks]
[status-im.utils.types :as types]))
(defn- get-chat
[cofx chat-id]
@ -221,10 +222,10 @@
(rf/defn handle-one-to-one-chat-created
{:events [:chat/one-to-one-chat-created]}
[{:keys [db]} chat-id response]
(let [chat (chats-store/<-rpc (first (:chats response)))
contact-rpc (first (:contacts response))
contact (when contact-rpc (contacts-store/<-rpc contact-rpc))]
[{:keys [db]} chat-id response-js]
(let [chat (chats-store/<-rpc (first (types/js->clj (.-chats ^js response-js))))
contact-js (first (.-contacts ^js response-js))
contact (when contact-js (contacts-store/<-rpc-js contact-js))]
{:db (cond-> db
contact
(assoc-in [:contacts/contacts chat-id] contact)
@ -253,10 +254,11 @@
{:events [:chat.ui/start-chat]}
[cofx chat-id ens-name]
(when (not= (multiaccounts.model/current-public-key cofx) chat-id)
{:json-rpc/call [{:method "wakuext_createOneToOneChat"
:params [{:id chat-id :ensName ens-name}]
: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 %)}]}))
{:json-rpc/call [{:method "wakuext_createOneToOneChat"
:params [{:id chat-id :ensName ens-name}]
:js-response true
: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
"Clears history of the particular chat"

View File

@ -1,30 +1,31 @@
(ns status-im2.contexts.chat.group-details.view
(:require [utils.i18n :as i18n]
[quo.components.safe-area :as safe-area]
[quo2.core :as quo2]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[status-im2.contexts.chat.group-details.style :as style]
[status-im2.common.contact-list.view :as contact-list]
[status-im2.common.contact-list-item.view :as contact-list-item]
[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
[]
[quo2/button
[quo/button
{:type :grey
:size 32
:width 32
:style {:margin-left 20}
:accessibility-label :back-button
: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
[]
(let [group (rf/sub [:chats/current-chat])]
[quo2/button
[quo/button
{:type :grey
:size 32
:width 32
@ -32,7 +33,7 @@
:accessibility-label :options-button
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{: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
[]
@ -47,7 +48,7 @@
[rn/view
{:style (style/count-container)
:accessibility-label accessibility-label}
[quo2/text
[quo/text
{:size :label
:weight :medium
:style {:text-align :center}} count]])
@ -60,11 +61,37 @@
:border-top-color colors/neutral-20
:padding-vertical 8
:margin-top 8}}
[quo2/text
[quo/text
{:size :paragraph-2
:weight :medium
: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
[group admin?]
[:f>
@ -78,18 +105,22 @@
{:on-press #(rf/dispatch [:bottom-sheet/hide])
:accessibility-label :close-manage-members
:style (style/close-icon)}
[quo2/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[quo2/text
[quo/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[quo/text
{:size :heading-1
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label (if admin? :t/manage-members :t/add-members))]
[contact-list/contact-list
{:icon :check
:group group
:search? true}]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
: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)}
[quo2/button
[quo/button
{:style {:flex 1}
:accessibility-label :save
:on-press (fn []
@ -103,6 +134,20 @@
(zero? (count deselected-members)))}
(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
[]
(let [{:keys [admins chat-id chat-name color public?
@ -116,7 +161,7 @@
[rn/view
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header
[quo/header
{:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
@ -124,15 +169,15 @@
{:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo2/group-avatar
[quo/group-avatar
{:color color
:size :medium}]
[quo2/text
[quo/text
{:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[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)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
@ -144,17 +189,17 @@
[rn/view
{:style {:flex-direction :row
: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]]
[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)]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
: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)}]
[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))]]
[rn/touchable-opacity
{:style (style/action-container color)
@ -168,16 +213,15 @@
[rn/view
{:style {:flex-direction :row
: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]]
[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))]]]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header
:render-fn contact-list-item/contact-list-item
:render-data {:chat-id chat-id
:admin? admin?
:icon :options}}]]))
:admin? admin?}
:render-fn contact-item-render}]]))

View File

@ -127,7 +127,7 @@
(merge {:style (style/container)
:on-press (open-chat chat-id)
: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]
[rn/view {:style {:margin-left 8}}
[name-view display-name contact timestamp]

View File

@ -8,7 +8,9 @@
[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.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
[_ index]
@ -50,6 +52,29 @@
[quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)]
[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
[pending-contact-requests]
(let [items (rf/sub [:contacts/active-sections])]
@ -59,7 +84,7 @@
(when (seq pending-contact-requests)
[contact-request/contact-requests pending-contact-requests])
(when (seq items)
[contact-list/contact-list {:icon :options}])])))
[contacts-section-list items])])))
(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]
[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.mentions.view :as mentions]
[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.mentions :as mentions]
[status-im.ui2.screens.chat.composer.reply :as reply]))
(def initial-content-height (atom nil))
@ -98,25 +98,6 @@
(update-y params))
(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!
[{:keys [keyboard-shown reply edit suggestions images] :as params}]
(rn/use-effect
@ -241,7 +222,7 @@
:sending-image (seq images)
:refs refs}]]]]
(if suggestions?
[mentions params insets]
[mentions/mentions params insets]
[controls/view send-ref params insets chat-id images #(clean-and-minimize params)])
;;;;black background
[reanimated/view

View File

@ -7,7 +7,7 @@
(defn user-xxx-deleted-this-message
[{: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}}
[quo/user-avatar
{:full-name display-name
@ -15,9 +15,7 @@
:status-indicator? false
:ring? false
:size :xxxs}]]
[quo/display-name
{:profile-name display-name
:text-style {}}]
[quo/author {:primary-name display-name}]
[quo/text {:style {:margin-left 4} :size :paragraph-2}
(i18n/label :t/deleted-this-message)]])

View File

@ -1,7 +1,6 @@
(ns status-im2.contexts.chat.messages.content.view
(:require [react-native.core :as rn]
[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.pin.view :as pin]
[status-im2.constants :as constants]
@ -18,7 +17,8 @@
[status-im.ui2.screens.chat.messages.message :as old-message]
[status-im2.common.not-implemented :as not-implemented]
[utils.datetime :as datetime]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[utils.address :as address]))
(def delivery-state-showing-time-ms 3000)
@ -52,12 +52,12 @@
from
timestamp]}]
(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])]
[quo/author
{:profile-name display-name
:short-chat-key (utils/get-shortened-address (or compressed-key
from))
{:primary-name primary-name
:secondary-name secondary-name
:short-chat-key (address/get-shortened-key (or compressed-key from))
:time-str (datetime/timestamp->time timestamp)
:contact? added?
:verified? ens-verified}])))

View File

@ -1,22 +1,124 @@
(ns status-im2.contexts.contacts.events
(:require
[utils.re-frame :as rf]
[status-im.contact.db :as contact.db]
[status-im.data-store.contacts :as contacts-store]))
[taoensso.timbre :as log]
[status-im.utils.types :as types]
[oops.core :as oops]
[status-im2.constants :as constants]))
(rf/defn load-contacts
{:events [:contacts/contacts-loaded]}
[{:keys [db] :as cofx} all-contacts]
(let [contacts-list (map #(vector (:public-key %)
(if (empty? (:address %))
(dissoc % :address)
%))
all-contacts)
contacts (into {} contacts-list)]
{:db (cond-> (-> db
(update :contacts/contacts #(merge contacts %))
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts))))}))
(defn <-rpc-js
[^js js-contact]
{:public-key (oops/oget js-contact "id")
:compressed-key (oops/oget js-contact "compressedKey")
:primary-name (oops/oget js-contact "primaryName")
:secondary-name (.-secondaryName js-contact)
:ens-name (.-ensName js-contact)
:nickname (.-localNickname js-contact)
:identicon (oops/oget js-contact "identicon")
:images (types/js->clj (oops/oget js-contact "images"))
:ens-verified (oops/oget js-contact "ensVerified")
: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
[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
[]
[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}]])
[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

@ -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]
[re-frame.core :as re-frame]
[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.avatars.account-avatar :as account-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.network-amount :as network-amount]
[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
{:foundations [{:name :shadows
@ -166,7 +166,10 @@
:component channel/preview-channel}
{:name :preview-lists
: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
:insets {:top false}
:component text/preview-text}]
@ -289,32 +292,29 @@
(defn main-screen
[]
(fn []
[safe-area/consumer
(fn [insets]
[rn/scroll-view
{:flex 1
:padding-top (:top insets)
:padding-bottom 8
:padding-horizontal 16
:background-color (colors/theme-colors colors/white colors/neutral-90)}
[theme-switcher]
[quo2-text/text {:size :heading-1} "Preview Quo2 Components"]
[rn/view
(map (fn [category]
^{:key (get category 0)}
[rn/view {:style {:margin-vertical 8}}
[quo2-text/text
{:weight :semi-bold
:size :heading-2}
(clojure.core/name (key category))]
(for [{:keys [name]} (val category)]
^{:key name}
[quo2-button/button
{:test-ID (str "quo2-" name)
:style {:margin-vertical 8}
:on-press #(re-frame/dispatch [:navigate-to name])}
(clojure.core/name name)])])
(sort screens-categories))]])]))
[rn/scroll-view
{:flex 1
:padding-bottom 8
:padding-horizontal 16
:background-color (colors/theme-colors colors/white colors/neutral-90)}
[theme-switcher]
[quo2-text/text {:size :heading-1} "Preview Quo2 Components"]
[rn/view
(map (fn [category]
^{:key (get category 0)}
[rn/view {:style {:margin-vertical 8}}
[quo2-text/text
{:weight :semi-bold
:size :heading-2}
(clojure.core/name (key category))]
(for [{:keys [name]} (val category)]
^{:key name}
[quo2-button/button
{:test-ID (str "quo2-" name)
:style {:margin-vertical 8}
:on-press #(re-frame/dispatch [:navigate-to name])}
(clojure.core/name name)])])
(sort screens-categories))]]))
(def main-screens
[{:name :quo2-preview

View File

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

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

View File

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

View File

@ -50,6 +50,13 @@
(fn [communities [_ id]]
(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
:communities/sorted-community-members
(fn [[_ community-id]]

View File

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

View File

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

View File

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

View File

@ -3,14 +3,14 @@
(:require [status-im.ethereum.core :as ethereum]
[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
and adds unicode ellipsis in between"
[address]
(when address
(str (subs address 0 6) "\u2026" (subs address (- (count address) 3) (count address)))))
[value]
(when value
(str (subs value 0 6) "\u2026" (subs value (- (count value) 3) (count value)))))
(defn get-shortened-checksum-address
[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>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.132.3",
"commit-sha1": "999d8c0ee0f2274c58b5a2de3beddab7feaabd16",
"src-sha256": "0qcpbhkhy8l3cq1055gnxghi7292jnd7xznl6s6h92pcg37y1jzc"
"version": "feature/contacts-fields",
"commit-sha1": "dde6e6570e3e1035b2d56b2db3695ddbc72909c7",
"src-sha256": "1h0wcmi41svyky5w3059nzbyyzzldir1bf01wgzhbykvnn26sjhp"
}