Implement reviewal of contact requests from contact profile (#19119)

* chore: add english translation for contact-request-review

* feature: integrate contact-request-review button

* tweak: render the locked-input label when provided

* tweak: allow locked-input component to grow in height

* chore: add english translation for "ignore"

* feature: add subscription for retrieving a pending contact-request by contact-id

* feature: integrate initial contact request review flow

* tweak: display send-message button on contact profile when contact-request-state is mutual

* tidy: refactor button-wrapper view to be button container-styles

* feature: add toast for accepting contact request
This commit is contained in:
Sean Hagstrom 2024-03-11 09:43:18 +00:00 committed by GitHub
parent 7065f4abd2
commit ca9346a931
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 126 additions and 15 deletions

View File

@ -10,7 +10,7 @@
:background-color (colors/theme-colors colors/neutral-10 :background-color (colors/theme-colors colors/neutral-10
colors/neutral-80-opa-80 colors/neutral-80-opa-80
theme) theme)
:height 40 :min-height 40
:padding-horizontal 12 :padding-horizontal 12
:padding-vertical 9 :padding-vertical 9
:margin-top 4}) :margin-top 4})

View File

@ -22,11 +22,12 @@
(defn- locked-input-internal (defn- locked-input-internal
[{:keys [label icon container-style theme]} value] [{:keys [label icon container-style theme]} value]
[rn/view {:style container-style} [rn/view {:style container-style}
[text/text (when label
{:size :paragraph-2 [text/text
:weight :medium {:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}} :weight :medium
label] :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label])
[info-box [info-box
{:theme theme {:theme theme
:icon icon :icon icon

View File

@ -44,3 +44,4 @@
:button-one-props {:disabled? (string/blank? message) :button-one-props {:disabled? (string/blank? message)
:on-press on-message-submit} :on-press on-message-submit}
:button-one-label (i18n/label :t/send-contact-request)}]])) :button-one-label (i18n/label :t/send-contact-request)}]]))

View File

@ -0,0 +1,8 @@
(ns status-im.contexts.profile.contact.contact-review.style)
(def message-input-wrapper
{:padding-vertical 8
:padding-horizontal 20})
(def bottom-actions-wrapper
{:padding-vertical 4})

View File

@ -0,0 +1,52 @@
(ns status-im.contexts.profile.contact.contact-review.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.profile.contact.contact-review.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [public-key customization-color]
:as profile} (rf/sub [:contacts/current-contact])
{contact-request-id :id
:keys [message]} (rf/sub [:activity-center/pending-contact-request-from-contact-id
public-key])
;; TODO(@seanstrom): https://github.com/status-im/status-mobile/issues/18733
customization-color (or customization-color :blue)
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
on-contact-accept (rn/use-callback
(fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:activity-center.contact-requests/accept
contact-request-id])
(rf/dispatch [:toasts/upsert
{:id :accept-contact-request
:type :positive
:text (i18n/label
:t/contact-request-was-accepted)}]))
[contact-request-id])
on-contact-ignore (rn/use-callback (fn []
(rf/dispatch [:hide-bottom-sheet])))]
[:<>
[quo/drawer-top
{:type :context-tag
:context-tag-type :default
:title (i18n/label :t/contact-request-review)
:full-name full-name
:profile-picture profile-picture
:customization-color customization-color}]
[rn/view {:style style/message-input-wrapper}
[quo/locked-input {}
(-> message :content :text)]]
[rn/view {:style style/bottom-actions-wrapper}
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/accept)
:button-one-props {:type :positive
:on-press on-contact-accept}
:button-two-props {:type :danger
:on-press on-contact-ignore}
:button-two-label (i18n/label :t/ignore)}]]]))

View File

@ -8,8 +8,8 @@
:align-items :flex-start}) :align-items :flex-start})
(def button-wrapper (def button-wrapper
{:padding-top 8 {:margin-top 8
:padding-bottom 16 :margin-bottom 16
:padding-horizontal 20}) :padding-horizontal 20})
(defn header-container (defn header-container

View File

@ -7,6 +7,7 @@
[status-im.common.scalable-avatar.view :as avatar] [status-im.common.scalable-avatar.view :as avatar]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.profile.contact.contact-request.view :as contact-request] [status-im.contexts.profile.contact.contact-request.view :as contact-request]
[status-im.contexts.profile.contact.contact-review.view :as contact-review]
[status-im.contexts.profile.contact.header.style :as style] [status-im.contexts.profile.contact.header.style :as style]
[status-im.contexts.profile.utils :as profile.utils] [status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
@ -14,7 +15,7 @@
(defn view (defn view
[{:keys [scroll-y]}] [{:keys [scroll-y]}]
(let [{:keys [public-key customization-color (let [{:keys [public-key customization-color ens-name
emoji-hash bio contact-request-state] emoji-hash bio contact-request-state]
:as profile} (rf/sub [:contacts/current-contact]) :as profile} (rf/sub [:contacts/current-contact])
customization-color (or customization-color :blue) customization-color (or customization-color :blue)
@ -23,7 +24,13 @@
online? (rf/sub [:visibility-status-updates/online? public-key]) online? (rf/sub [:visibility-status-updates/online? public-key])
theme (quo.theme/use-theme-value) theme (quo.theme/use-theme-value)
on-contact-request (rn/use-callback #(rf/dispatch [:show-bottom-sheet on-contact-request (rn/use-callback #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [contact-request/view])}]))] {:content (fn [] [contact-request/view])}]))
on-contact-review (rn/use-callback #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [contact-review/view])}]))
on-start-chat (rn/use-callback #(rf/dispatch [:chat.ui/start-chat
public-key
ens-name])
[ens-name public-key])]
[rn/view {:style style/header-container} [rn/view {:style style/header-container}
[rn/view {:style style/header-top-wrapper} [rn/view {:style style/header-top-wrapper}
[rn/view {:style style/avatar-wrapper} [rn/view {:style style/avatar-wrapper}
@ -49,10 +56,24 @@
(cond (cond
(or (not contact-request-state) (or (not contact-request-state)
(= contact-request-state constants/contact-request-state-none)) (= contact-request-state constants/contact-request-state-none))
[rn/view {:style style/button-wrapper} [quo/button
[quo/button {:container-style style/button-wrapper
{:on-press on-contact-request :on-press on-contact-request
:icon-left :i/add-user} :icon-left :i/add-user}
(i18n/label :t/send-contact-request)]] (i18n/label :t/send-contact-request)]
(= contact-request-state constants/contact-request-state-received)
[quo/button
{:container-style style/button-wrapper
:on-press on-contact-review
:icon-left :i/add-user}
(i18n/label :t/contact-request-review)]
(= contact-request-state constants/contact-request-state-mutual)
[quo/button
{:container-style style/button-wrapper
:on-press on-start-chat
:icon-left :i/messages}
(i18n/label :t/send-message)]
:else nil)])) :else nil)]))

View File

@ -80,3 +80,11 @@
:<- [:activity-center] :<- [:activity-center]
(fn [activity-center] (fn [activity-center]
(:contact-requests activity-center))) (:contact-requests activity-center)))
(re-frame/reg-sub
:activity-center/pending-contact-request-from-contact-id
:<- [:activity-center/pending-contact-requests]
(fn [pending-contact-requests [_ contact-id]]
(->> pending-contact-requests
(filter #(= contact-id (:author %)))
(first))))

View File

@ -86,3 +86,21 @@
(swap! rf-db/app-db assoc-in [:activity-center :unread-counts-by-type] {types/one-to-one-chat 1}) (swap! rf-db/app-db assoc-in [:activity-center :unread-counts-by-type] {types/one-to-one-chat 1})
(swap! rf-db/app-db assoc-in [:activity-center :seen?] true) (swap! rf-db/app-db assoc-in [:activity-center :seen?] true)
(is (= :unread-indicator/seen (rf/sub [sub-name]))))) (is (= :unread-indicator/seen (rf/sub [sub-name])))))
(h/deftest-sub :activity-center/pending-contact-request-from-contact-id
[sub-name]
(testing "returns contact request data if it finds a matching contact-id"
(let [contact-id "0x01"
contact-request {:author contact-id
:message {:content {:text "Hey there"}}}]
(swap! rf-db/app-db assoc-in [:activity-center :contact-requests] [contact-request])
(is (match? contact-request
(rf/sub [sub-name contact-id])))))
(testing "returns nil if it does not find a matching contact-id"
(let [contact-id "0x01"
contact-request {:author "0x02"
:message {:content {:text "Hey there"}}}]
(swap! rf-db/app-db assoc-in [:activity-center :contact-requests] [contact-request])
(is (match? nil
(rf/sub [sub-name contact-id]))))))

View File

@ -1666,6 +1666,7 @@
"remove-nickname-toast": "You have removed {{secondary-name}}'s nickname", "remove-nickname-toast": "You have removed {{secondary-name}}'s nickname",
"nickname-description": "Nicknames help you identify others in Status.\nOnly you can see the nicknames youve added", "nickname-description": "Nicknames help you identify others in Status.\nOnly you can see the nicknames youve added",
"accept": "Accept", "accept": "Accept",
"ignore": "Ignore",
"group-invite": "Group invite", "group-invite": "Group invite",
"group-invite-link": "Group invite link", "group-invite-link": "Group invite link",
"pending-invitations": "Pending membership requests", "pending-invitations": "Pending membership requests",
@ -1986,6 +1987,7 @@
"accepted": "Accepted", "accepted": "Accepted",
"declined": "Declined", "declined": "Declined",
"contact-request-sent": "sent contact request", "contact-request-sent": "sent contact request",
"contact-request-review": "Review contact request",
"contact-request-sent-toast": "{{name}} sent you a contact request", "contact-request-sent-toast": "{{name}} sent you a contact request",
"contact-request-accepted-toast": "{{name}} accepted your contact request", "contact-request-accepted-toast": "{{name}} accepted your contact request",
"contact-request-outgoing": "Youre trying to connect with", "contact-request-outgoing": "Youre trying to connect with",