Implement blocked contacts setting inside profile messages settings #… (#19616)

This commit is contained in:
flexsurfer 2024-04-23 19:12:00 +02:00 committed by GitHub
parent 9b550e4b82
commit 380603ddce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 376 additions and 337 deletions

View File

@ -1,99 +0,0 @@
(ns legacy.status-im.contact.block
(:require
[legacy.status-im.contact.db :as contact.db]
[legacy.status-im.data-store.chats :as chats-store]
[legacy.status-im.utils.deprecated-types :as types]
[re-frame.core :as re-frame]
[status-im.contexts.chat.contacts.events :as contacts-store]
[status-im.contexts.chat.messenger.messages.list.events :as message-list]
[status-im.navigation.events :as navigation]
[utils.re-frame :as rf]))
(rf/defn clean-up-chat
[{:keys [db]}
public-key
{:keys [chat-id
unviewed-messages-count
unviewed-mentions-count
last-message]}]
(let [removed-messages-ids (keep
(fn [[message-id {:keys [from]}]]
(when (= from public-key)
message-id))
(get-in db [:messages chat-id]))
db (-> db
;; remove messages
(update-in [:messages chat-id]
#(apply dissoc % removed-messages-ids))
(update-in [:chats chat-id]
assoc
:unviewed-messages-count unviewed-messages-count
:unviewed-mentions-count unviewed-mentions-count
:last-message last-message))]
{:db (assoc-in db
[:message-lists chat-id]
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
(rf/defn contact-blocked
{: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-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))
:fx [[:activity-center.notifications/fetch-unread-count]
[:effects/push-notifications-clear-message-notifications [public-key]]
[:dispatch-later
[{:ms 500
:dispatch [:chat.ui/close-and-remove-chat public-key]}]]]}
fxs)))
(rf/defn block-contact
{:events [:contact.ui/block-contact-confirmed]}
[{:keys [db] :as cofx} public-key]
(let [contact (-> (contact.db/public-key->contact
(:contacts/contacts db)
public-key)
(assoc :blocked? true
:added? false
:active? false))
current-chat-id (:current-chat-id db)
from-one-to-one-chat? (not (get-in db [:chats current-chat-id :group-chat]))]
(rf/merge cofx
{:db (assoc-in db [:contacts/contacts public-key] contact)}
(contacts-store/block
public-key
(fn [^js 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
(when current-chat-id
(if from-one-to-one-chat?
(navigation/pop-to-root :shell-stack)
(navigation/navigate-back))))))
(rf/defn contact-unblocked
{:events [:contacts/unblocked]}
[{:keys [db]} contact-id]
(let [contact (-> (get-in db [:contacts/contacts contact-id])
(assoc :blocked? false))]
{:db (assoc-in db [:contacts/contacts contact-id] contact)}))
(rf/defn unblock-contact
{:events [:contact.ui/unblock-contact-pressed]}
[cofx contact-id]
(contacts-store/unblock
cofx
contact-id
#(re-frame/dispatch [:contacts/unblocked contact-id])))

View File

@ -1,87 +0,0 @@
(ns legacy.status-im.contact.db
(:require
[clojure.set :as set]
[clojure.string :as string]
[status-im.constants :as constants]
[utils.address :as address]))
(defn public-key-and-ens-name->new-contact
[public-key ens-name]
(let [contact {:public-key public-key}]
(if ens-name
(-> contact
(assoc :ens-name ens-name)
(assoc :ens-verified true)
(assoc :name ens-name))
contact)))
(defn public-key->contact
[contacts public-key]
(when public-key
(get contacts public-key {:public-key public-key})))
(defn- contact-by-address
[[addr contact] address]
(when (address/address= addr address)
contact))
(defn find-contact-by-address
[contacts address]
(some #(contact-by-address % address) contacts))
(defn sort-contacts
[contacts]
(sort (fn [c1 c2]
(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 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 preferred-name name display-name] :as current-account}]
(let [current-contact (some->
current-account
(select-keys [:name :preferred-name :public-key :images :compressed-key])
(set/rename-keys {:name :alias :preferred-name :name})
(assoc :primary-name (or display-name preferred-name name)))
all-contacts (cond-> contacts
current-contact
(assoc public-key current-contact))]
(->> members
(map #(or (get all-contacts %)
{:public-key %}))
(sort-by (comp string/lower-case
(fn [{:keys [primary-name name alias public-key]}]
(or primary-name
name
alias
public-key))))
(map #(if (get admins (:public-key %))
(assoc % :admin? true)
%)))))
(defn enrich-contact
([contact] (enrich-contact contact nil nil))
([{:keys [public-key] :as contact} setting own-public-key]
(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)))))
(dissoc :images))))
(defn enrich-contacts
[contacts profile-pictures-visibility own-public-key]
(reduce-kv
(fn [acc public-key contact]
(assoc acc public-key (enrich-contact contact profile-pictures-visibility own-public-key)))
{}
contacts))

View File

@ -1,49 +0,0 @@
(ns legacy.status-im.contact.db-test
(:require [cljs.test :refer-macros [deftest is testing]]
[legacy.status-im.contact.db :as contact.db]))
(deftest contacts-subs
(testing "get-all-contacts-in-group-chat"
(let
[chat-contact-ids
#{"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"
"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
admins
#{"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
contacts
{"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
{:last-updated 0
:name "User B"
:primary-name "User B"
:last-online 0
:public-key
"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"}}
current-multiaccount
{:last-updated 0
:signed-up? true
:sharing-usage-data? false
:primary-name "User A"
:name "User A"
:public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}]
(is
(=
(contact.db/get-all-contacts-in-group-chat chat-contact-ids
admins
contacts
current-multiaccount)
[{:admin? true
:public-key
"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
{:alias "User A"
:primary-name "User A"
:public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
{:last-updated 0
:name "User B"
:primary-name "User B"
:last-online 0
:public-key
"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"}])))))

View File

@ -5,7 +5,6 @@
legacy.status-im.browser.core legacy.status-im.browser.core
legacy.status-im.browser.permissions legacy.status-im.browser.permissions
legacy.status-im.chat.models.loading legacy.status-im.chat.models.loading
legacy.status-im.contact.block
legacy.status-im.currency.core legacy.status-im.currency.core
legacy.status-im.data-store.chats legacy.status-im.data-store.chats
legacy.status-im.data-store.switcher-cards legacy.status-im.data-store.switcher-cards

View File

@ -22,7 +22,7 @@
:loading @in-progress? :loading @in-progress?
:accessibility-label :block-contact-confirm :accessibility-label :block-contact-confirm
:on-press #(do (reset! in-progress? true) :on-press #(do (reset! in-progress? true)
(re-frame/dispatch [:contact.ui/block-contact-confirmed public-key]))} (re-frame/dispatch [:contact/block-contact public-key]))}
(i18n/label :t/block)] (i18n/label :t/block)]
[react/view {:height 8}] [react/view {:height 8}]
[quo/button [quo/button

View File

@ -56,7 +56,7 @@
:selected blocked? :selected blocked?
:icon :main-icons/cancel :icon :main-icons/cancel
:action (if blocked? :action (if blocked?
#(re-frame/dispatch [:contact.ui/unblock-contact-pressed public-key]) #(re-frame/dispatch [:contact/unblock-contact public-key])
#(re-frame/dispatch [:show-popover #(re-frame/dispatch [:show-popover
{:view sheets/block-contact {:view sheets/block-contact
:prevent-closing? true :prevent-closing? true

View File

@ -17,26 +17,28 @@
:flex-direction :row :flex-direction :row
:align-items :center}) :align-items :center})
(defn action-icon (defn accessory-item
[{:keys [type on-press on-check disabled? checked?]} customization-color theme] [{:keys [type on-press on-check disabled? checked? child]} customization-color theme]
[rn/touchable-opacity (if (= type :custom)
{:on-press on-press} child
(case type [rn/touchable-opacity
:options {:on-press on-press}
[icons/icon :i/options (case type
{:size 20 :options
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}] [icons/icon :i/options
:checkbox {:size 20
[selectors/view :color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}]
{:type :checkbox :checkbox
:checked? checked? [selectors/view
:customization-color customization-color {:type :checkbox
:accessibility-label :user-list-toggle-check :checked? checked?
:disabled? disabled? :customization-color customization-color
:on-change (when on-check on-check)}] :accessibility-label :user-list-toggle-check
:close :disabled? disabled?
[text/text "not implemented"] :on-change (when on-check on-check)}]
[rn/view])]) :close
[text/text "not implemented"]
[rn/view])]))
(defn user (defn user
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified? [{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
@ -72,4 +74,4 @@
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}} :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
short-chat-key])] short-chat-key])]
(when accessory (when accessory
[action-icon accessory customization-color disabled? theme])]]) [accessory-item accessory customization-color disabled? theme])]])

View File

@ -2,19 +2,23 @@
(:require (:require
[quo.components.overlay.style :as style] [quo.components.overlay.style :as style]
[react-native.blur :as blur] [react-native.blur :as blur]
[react-native.core :as rn])) [react-native.core :as rn]
[react-native.safe-area :as safe-area]))
(defn view (defn view
[{:keys [type container-style]} & children] [{:keys [type container-style top-inset?]} & children]
[rn/view {:style (style/overlay-background type)} (let [top-style (when top-inset? {:padding-top (safe-area/get-top)})]
(if (= type :shell) [rn/view {:style (style/overlay-background type)}
[blur/view (if (= type :shell)
{:blur-amount 20 [blur/view
:blur-radius 25 {:blur-amount 20
:blur-type :transparent :blur-radius 25
:overlay-color :transparent :blur-type :transparent
:style style/container} :overlay-color :transparent
[rn/view {:style (merge style/blur-container container-style)} :style style/container}
children]] (into [rn/view
[rn/view {:style (merge style/container container-style)} {:style (merge style/blur-container top-style container-style)}]
children])]) children)]
(into [rn/view
{:style (merge style/container top-style container-style)}]
children))]))

View File

@ -113,7 +113,7 @@
(h/is-truthy (h/get-by-text "Title")) (h/is-truthy (h/get-by-text "Title"))
(h/is-truthy (h/get-by-label-text :address-text-input))) (h/is-truthy (h/get-by-label-text :address-text-input)))
(h/test "Address input" (h/test "Recovery phrase"
(h/render [page-top/view (h/render [page-top/view
{:title "Title" {:title "Title"
:input :recovery-phrase}]) :input :recovery-phrase}])

View File

@ -127,7 +127,7 @@
:context item :context item
:accessibility-label :block-user :accessibility-label :block-user
:button-text (i18n/label :t/block-user) :button-text (i18n/label :t/block-user)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed :on-press #(hide-sheet-and-dispatch [:contact/block-contact
public-key])}])}])) public-key])}])}]))
(defn mute-chat-entry (defn mute-chat-entry

View File

@ -19,7 +19,7 @@
(update :toasts dissoc :hide-toasts-timer-set))} (update :toasts dissoc :hide-toasts-timer-set))}
(and (not update?) (= (count ordered) 1)) (and (not update?) (= (count ordered) 1))
(assoc :show-toasts [(:view-id db) (:theme db)]) (assoc :show-toasts [(:view-id db) (or (:theme opts) (:theme db))])
(not (:id opts)) (not (:id opts))
(update-in [:db :toasts :next-toast-number] inc)))) (update-in [:db :toasts :next-toast-number] inc))))

View File

@ -131,20 +131,3 @@
:js-response true :js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %]) :on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to set contact nickname " public-key nickname %)}]}) :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

@ -0,0 +1,85 @@
(ns status-im.contexts.contact.blocking.events
(:require
[legacy.status-im.data-store.chats :as chats-store]
[re-frame.core :as re-frame]
[status-im.contexts.chat.messenger.messages.list.events :as message-list]
[taoensso.timbre :as log]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/defn clean-up-chat
[{:keys [db]} public-key
{:keys [chat-id unviewed-messages-count unviewed-mentions-count last-message]}]
(let [ids (keep (fn [[message-id {:keys [from]}]]
(when (= from public-key) message-id))
(get-in db [:messages chat-id]))
db (-> db
;; remove messages
(update-in [:messages chat-id] #(apply dissoc % ids))
(update-in [:chats chat-id]
assoc
:unviewed-messages-count unviewed-messages-count
:unviewed-mentions-count unviewed-mentions-count
:last-message last-message))]
{:db (assoc-in db
[:message-lists chat-id]
(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-js]
(let [fxs (when chats-js
(map #(->> (chats-store/<-rpc %)
(clean-up-chat public-key))
(transforms/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))
:fx [[:activity-center.notifications/fetch-unread-count]
[:effects/push-notifications-clear-message-notifications [public-key]]
[:dispatch-later
[{:ms 500
:dispatch [:chat.ui/close-and-remove-chat public-key]}]]]}
fxs)))
(rf/reg-event-fx :contact/block-contact
(fn [{:keys [db]} [public-key]]
(let [contact (-> (get (:contacts/contacts db) public-key {:public-key public-key})
(assoc :blocked? true
:added? false
:active? false))
current-chat-id (:current-chat-id db)
from-one-to-one-chat? (not (get-in db [:chats current-chat-id :group-chat]))]
{:db (assoc-in db [:contacts/contacts public-key] contact)
:fx [[:json-rpc/call
[{:method "wakuext_blockContact"
:params [public-key]
:js-response true
:on-success (fn [^js response]
(re-frame/dispatch [:contact/blocked contact (.-chats response)])
(re-frame/dispatch [:sanitize-messages-and-process-response response]))
:on-error #(log/error "failed to block contact" % public-key)}]]
[:dispatch [:hide-popover]]
;; reset navigation to avoid going back to non existing one to one chat
(when current-chat-id
(if from-one-to-one-chat?
[:dispatch [:pop-to-root :shell-stack]]
[:dispatch [:navigate-back]]))]})))
(rf/reg-event-fx :contact/unblocked
(fn [{:keys [db]} [contact-id]]
{:db (update-in db
[:contacts/contacts contact-id]
#(assoc % :blocked? false :added true :active? true))}))
(rf/reg-event-fx :contact/unblock-contact
(fn [_ [contact-id]]
{:json-rpc/call
[{:method "wakuext_unblockContact"
:params [contact-id]
:on-success #(re-frame/dispatch [:contact/unblocked contact-id])
:on-error #(log/error "failed to unblock contact" % contact-id)}]}))

View File

@ -24,7 +24,7 @@
:text (i18n/label :t/user-blocked :text (i18n/label :t/user-blocked
{:username {:username
full-name})}]) full-name})}])
(rf/dispatch [:contact.ui/block-contact-confirmed (rf/dispatch [:contact/block-contact
public-key]) public-key])
(rf/dispatch [:contact.ui/remove-contact-pressed (rf/dispatch [:contact.ui/remove-contact-pressed
{:public-key public-key}]) {:public-key public-key}])

View File

@ -46,7 +46,7 @@
ens-name]) ens-name])
[ens-name public-key]) [ens-name public-key])
on-unblock-press (rn/use-callback (fn [] on-unblock-press (rn/use-callback (fn []
(rf/dispatch [:contact.ui/unblock-contact-pressed (rf/dispatch [:contact/unblock-contact
public-key]) public-key])
(rf/dispatch [:toasts/upsert (rf/dispatch [:toasts/upsert
{:id :user-unblocked {:id :user-unblocked

View File

@ -0,0 +1,52 @@
(ns status-im.contexts.profile.contact.unblock-contact.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.profile.contact.block-contact.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn on-close [] (rf/dispatch [:hide-bottom-sheet]))
(defn view
[contact]
(let [{:keys [customization-color
public-key]} contact
full-name (profile.utils/displayed-name contact)
profile-picture (profile.utils/photo contact)
on-unblock-press (rn/use-callback
(fn []
(rf/dispatch [:toasts/upsert
{:id :user-unblocked
:type :positive
:theme :dark
:text (i18n/label :t/user-unblocked
{:username
full-name})}])
(rf/dispatch [:contact/unblock-contact
public-key])
(on-close))
[public-key full-name])]
[:<>
[quo/drawer-top
{:type :context-tag
:context-tag-type :default
:title (i18n/label :t/unblock)
:full-name full-name
:profile-picture profile-picture
:customization-color customization-color}]
[rn/view {:style style/content-wrapper}
[quo/text
{:weight :medium
:size :paragraph-1}
(i18n/label :t/unblocking-a-user-message {:username full-name})]]
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/unblock)
:button-one-props {:type :danger
:accessibility-label :block-contact
:on-press on-unblock-press}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:accessibility-label :cancel
:on-press on-close}}]]))

View File

@ -17,13 +17,12 @@
:image :icon :image :icon
:blur? true :blur? true
:action :arrow}] :action :arrow}]
[(when config/show-not-implemented-features? [{:title (i18n/label :t/messages)
{:title (i18n/label :t/messages) :on-press #(rf/dispatch [:open-modal :screen/settings-messages])
:on-press not-implemented/alert :image-props :i/messages
:image-props :i/messages :image :icon
:image :icon :blur? true
:blur? true :action :arrow}
:action :arrow})
(when config/show-not-implemented-features? (when config/show-not-implemented-features?
{:title (i18n/label :t/wallet) {:title (i18n/label :t/wallet)
:on-press not-implemented/alert :on-press not-implemented/alert

View File

@ -0,0 +1,43 @@
(ns status-im.contexts.profile.settings.screens.messages.blocked-users.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.contact-list-item.view :as contact-list-item]
[status-im.contexts.profile.contact.unblock-contact.view :as unblock-contact]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn list-item
[user _ _ _]
[contact-list-item/contact-list-item
{:accessory {:type :custom
:child [quo/button
{:on-press #(rf/dispatch [:show-bottom-sheet
{:theme :dark
:content
(fn [] [unblock-contact/view user])}])
:type :outline
:size 24
:background :blur
:customization-color :blue}
(i18n/label :t/unblock)]}}
user])
(defn- navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn view
[]
(let [contacts (rf/sub [:contacts/blocked])]
[quo/overlay {:type :shell :top-inset? true}
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back}]
[quo/page-top {:title (i18n/label :t/blocked-users)}]
[rn/flat-list
{:data contacts
:key-fn :key
:render-fn list-item
:accessibility-label :contacts-list}]]))

View File

@ -0,0 +1,29 @@
(ns status-im.contexts.profile.settings.screens.messages.view
(:require [quo.core :as quo]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn- open-blocked-users
[]
(rf/dispatch [:open-modal :screen/settings-blocked-users]))
(defn view
[]
[quo/overlay {:type :shell :top-inset? true}
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press navigate-back}]
[quo/page-top {:title (i18n/label :t/messages)}]
[quo/category
{:label (i18n/label :t/contacts)
:data [{:title (i18n/label :t/blocked-users)
:on-press open-blocked-users
:blur? true
:action :arrow}]
:blur? true
:list-type :settings}]])

View File

@ -1,12 +1,9 @@
(ns status-im.contexts.profile.settings.screens.password.view (ns status-im.contexts.profile.settings.screens.password.view
(:require [quo.core :as quo] (:require [quo.core :as quo]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.biometric.utils :as biometric] [status-im.common.biometric.utils :as biometric]
[status-im.common.not-implemented :as not-implemented] [status-im.common.not-implemented :as not-implemented]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.profile.settings.screens.password.style :as style]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -56,27 +53,19 @@
:image-props :i/password :image-props :i/password
:action :arrow}) :action :arrow})
(defn- navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn view (defn view
[] []
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)]
insets (safe-area/get-insets)] [quo/overlay {:type :shell :top-inset? true}
[quo/overlay {:type :shell} [quo/page-nav
[rn/view {:background :blur
{:key :navigation :icon-name :i/arrow-left
:style (style/navigation (:top insets))} :on-press navigate-back}]
[quo/page-nav [quo/page-top {:title (i18n/label :t/password)}]
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])}]]
[rn/view
{:key :header
:style style/header}
[quo/text
{:accessibility-label :password-settings-label
:weight :semi-bold
:number-of-lines 1
:size :heading-1}
(i18n/label :t/password)]]
[quo/category [quo/category
{:key :category {:key :category
:data [(get-biometric-item theme) :data [(get-biometric-item theme)

View File

@ -23,6 +23,7 @@
status-im.contexts.communities.events status-im.contexts.communities.events
status-im.contexts.communities.overview.events status-im.contexts.communities.overview.events
status-im.contexts.communities.sharing.events status-im.contexts.communities.sharing.events
status-im.contexts.contact.blocking.events
status-im.contexts.onboarding.common.overlay.events status-im.contexts.onboarding.common.overlay.events
status-im.contexts.onboarding.events status-im.contexts.onboarding.events
status-im.contexts.profile.events status-im.contexts.profile.events

View File

@ -48,6 +48,9 @@
[status-im.contexts.profile.edit.name.view :as edit-name] [status-im.contexts.profile.edit.name.view :as edit-name]
[status-im.contexts.profile.edit.view :as edit-profile] [status-im.contexts.profile.edit.view :as edit-profile]
[status-im.contexts.profile.profiles.view :as profiles] [status-im.contexts.profile.profiles.view :as profiles]
[status-im.contexts.profile.settings.screens.messages.blocked-users.view :as
settings.blocked-users]
[status-im.contexts.profile.settings.screens.messages.view :as settings.messages]
[status-im.contexts.profile.settings.screens.password.view :as settings-password] [status-im.contexts.profile.settings.screens.password.view :as settings-password]
[status-im.contexts.profile.settings.view :as settings] [status-im.contexts.profile.settings.view :as settings]
[status-im.contexts.shell.activity-center.view :as activity-center] [status-im.contexts.shell.activity-center.view :as activity-center]
@ -471,7 +474,15 @@
{:name :settings-password {:name :settings-password
:options options/transparent-modal-screen-options :options options/transparent-modal-screen-options
:component settings-password/view}] :component settings-password/view}
{:name :screen/settings-messages
:options options/transparent-modal-screen-options
:component settings.messages/view}
{:name :screen/settings-blocked-users
:options options/transparent-modal-screen-options
:component settings.blocked-users/view}]
[{:name :shell [{:name :shell
:options {:theme :dark}}] :options {:theme :dark}}]

View File

@ -1,7 +1,7 @@
(ns status-im.subs.contact (ns status-im.subs.contact
(:require (:require
[clojure.set :as set]
[clojure.string :as string] [clojure.string :as string]
[legacy.status-im.contact.db :as contact.db]
[legacy.status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils] [legacy.status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[quo.theme] [quo.theme]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
@ -13,12 +13,17 @@
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.image-server :as image-server])) [utils.image-server :as image-server]))
(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))))
(re-frame/reg-sub (re-frame/reg-sub
::query-current-chat-contacts ::query-current-chat-contacts
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [[chat contacts] [_ query-fn]] (fn [[chat contacts] [_ query-fn]]
(contact.db/query-chat-contacts chat contacts query-fn))) (query-chat-contacts chat contacts query-fn)))
(re-frame/reg-sub (re-frame/reg-sub
:multiaccount/profile-pictures-show-to :multiaccount/profile-pictures-show-to
@ -73,6 +78,25 @@
(assoc contact :images images))) (assoc contact :images images)))
(defn- enrich-contact
([contact] (enrich-contact contact nil nil))
([{:keys [public-key] :as contact} setting own-public-key]
(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)))))
(dissoc :images))))
(defn- enrich-contacts
[contacts profile-pictures-visibility own-public-key]
(reduce-kv
(fn [acc public-key contact]
(assoc acc public-key (enrich-contact contact profile-pictures-visibility own-public-key)))
{}
contacts))
(defn- reduce-contacts-image-uri (defn- reduce-contacts-image-uri
[contacts port font-file theme] [contacts port font-file theme]
(reduce-kv (fn [acc public-key contact] (reduce-kv (fn [acc public-key contact]
@ -90,16 +114,26 @@
:<- [:initials-avatar-font-file] :<- [:initials-avatar-font-file]
:<- [:theme] :<- [:theme]
(fn [[contacts profile-pictures-visibility public-key port font-file theme]] (fn [[contacts profile-pictures-visibility public-key port font-file theme]]
(let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)] (let [contacts (enrich-contacts contacts profile-pictures-visibility public-key)]
(reduce-contacts-image-uri contacts port font-file theme)))) (reduce-contacts-image-uri contacts port font-file theme))))
(defn sort-contacts
[contacts]
(sort (fn [c1 c2]
(let [name1 (:primary-name c1)
name2 (:primary-name c2)]
(when (and name1 name2)
(compare (string/lower-case name1)
(string/lower-case name2)))))
(vals contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active :contacts/active
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts] (fn [contacts]
(->> contacts (->> contacts
(filter (fn [[_ contact]] (:active? contact))) (filter (fn [[_ contact]] (:active? contact)))
contact.db/sort-contacts))) sort-contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-sections :contacts/active-sections
@ -165,7 +199,7 @@
(->> contacts (->> contacts
(filter (fn [[_ contact]] (filter (fn [[_ contact]]
(:blocked? contact))) (:blocked? contact)))
contact.db/sort-contacts))) sort-contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/blocked-set :contacts/blocked-set
@ -179,10 +213,20 @@
(fn [blocked-contacts] (fn [blocked-contacts]
(count blocked-contacts))) (count blocked-contacts)))
(defn- enrich-contact (defn public-key-and-ens-name->new-contact
[public-key ens-name]
(let [contact {:public-key public-key}]
(if ens-name
(-> contact
(assoc :ens-name ens-name)
(assoc :ens-verified true)
(assoc :name ens-name))
contact)))
(defn- prepare-contact
[_ contact-identity ens-name port font-file theme] [_ contact-identity ens-name port font-file theme]
(let [contact (contact.db/enrich-contact (let [contact (enrich-contact
(contact.db/public-key-and-ens-name->new-contact contact-identity ens-name))] (public-key-and-ens-name->new-contact contact-identity ens-name))]
(replace-contact-image-uri contact port contact-identity font-file theme))) (replace-contact-image-uri contact port contact-identity font-file theme)))
(re-frame/reg-sub (re-frame/reg-sub
@ -197,7 +241,7 @@
(let [contact (get contacts contact-identity)] (let [contact (get contacts contact-identity)]
(cond-> contact (cond-> contact
(nil? contact) (nil? contact)
(enrich-contact contact-identity ens-name port font-file theme))))) (prepare-contact contact-identity ens-name port font-file theme)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-by-identity :contacts/contact-by-identity
@ -228,13 +272,36 @@
(fn [contacts] (fn [contacts]
(filter :added? contacts))) (filter :added? contacts)))
(defn get-all-contacts-in-group-chat
[members admins contacts {:keys [public-key preferred-name name display-name] :as current-account}]
(let [current-contact (some->
current-account
(select-keys [:name :preferred-name :public-key :images :compressed-key])
(set/rename-keys {:name :alias :preferred-name :name})
(assoc :primary-name (or display-name preferred-name name)))
all-contacts (cond-> contacts
current-contact
(assoc public-key current-contact))]
(->> members
(map #(or (get all-contacts %)
{:public-key %}))
(sort-by (comp string/lower-case
(fn [{:keys [primary-name name alias public-key]}]
(or primary-name
name
alias
public-key))))
(map #(if (get admins (:public-key %))
(assoc % :admin? true)
%)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/current-chat-contacts :contacts/current-chat-contacts
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:profile/profile] :<- [:profile/profile]
(fn [[{:keys [contacts admins]} all-contacts current-multiaccount]] (fn [[{:keys [contacts admins]} all-contacts current-multiaccount]]
(contact.db/get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount))) (get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contacts-by-chat :contacts/contacts-by-chat
@ -243,7 +310,16 @@
(re-frame/subscribe [:contacts/contacts]) (re-frame/subscribe [:contacts/contacts])
(re-frame/subscribe [:profile/profile])]) (re-frame/subscribe [:profile/profile])])
(fn [[{:keys [contacts admins]} all-contacts current-multiaccount]] (fn [[{:keys [contacts admins]} all-contacts current-multiaccount]]
(contact.db/get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount))) (get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount)))
(defn- contact-by-address
[[addr contact] address]
(when (address/address= addr address)
contact))
(defn find-contact-by-address
[contacts address]
(some #(contact-by-address % address) contacts))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-by-address :contacts/contact-by-address
@ -252,7 +328,7 @@
(fn [[contacts multiaccount] [_ address]] (fn [[contacts multiaccount] [_ address]]
(if (address/address= address (:public-key multiaccount)) (if (address/address= address (:public-key multiaccount))
multiaccount multiaccount
(contact.db/find-contact-by-address contacts address)))) (find-contact-by-address contacts address))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-customization-color-by-address :contacts/contact-customization-color-by-address

View File

@ -2076,6 +2076,7 @@
"block-user": "Block user", "block-user": "Block user",
"block-user-title-message": "You will not see {{username}}'s messages, but {{username}} still can see your messages in mutual group chats and communities. {{username}} will be unable to message you.", "block-user-title-message": "You will not see {{username}}'s messages, but {{username}} still can see your messages in mutual group chats and communities. {{username}} will be unable to message you.",
"blocking-a-user-message": "Blocking a user purges the database of all messages that youve previously received from {{username}} in all contexts.", "blocking-a-user-message": "Blocking a user purges the database of all messages that youve previously received from {{username}} in all contexts.",
"unblocking-a-user-message": "After unblocking {{username}}, you will be able to connect with them as a contact and see their messages in group chats and communities.",
"group-details": "Group details", "group-details": "Group details",
"edit-name-and-image": "Edit name and image", "edit-name-and-image": "Edit name and image",
"change-group-privacy": "Change group privacy", "change-group-privacy": "Change group privacy",