Outgoing contact requests (#14853)
* First thoughts/ideas
* Showing "Cancel contact request" button
* Fixes
* Restructuring, `retractContactRequest`
* Pending label
* Proper buttons for activity notifications
* New updates
* Returning back `activity-log` `items`
* Last changes in code
* Lint fix
* Lint fix (2)
* Style fixes
* Style fixes
* Code fixes
* Style fixes
* Fixes
1d9d7343...0082f7e9
* Footer update
* Toasts done
* Formatting fix
* Go version update
* Fixes for deletion
* status-go-version.json
* Lint fix
* Fixes
* Lint fix
* status-go version
* status-go version
This commit is contained in:
parent
888bf12856
commit
1b33aa4988
|
@ -33,25 +33,16 @@
|
|||
:padding-vertical 8
|
||||
:background-color colors/white-opa-5})
|
||||
|
||||
(def buttons-container
|
||||
(def footer-container
|
||||
{:margin-top 12
|
||||
:flex-direction :row
|
||||
:align-items :flex-start})
|
||||
|
||||
(def status
|
||||
{:margin-top 12
|
||||
:align-items :flex-start
|
||||
:flex 1})
|
||||
:flex-direction :row})
|
||||
|
||||
(defn title
|
||||
[replying?]
|
||||
{:color colors/white
|
||||
:flex-shrink 1
|
||||
:max-width (when-not replying? "60%")})
|
||||
[]
|
||||
{:color colors/white})
|
||||
|
||||
(def timestamp
|
||||
{:text-transform :none
|
||||
:flex-grow 1
|
||||
:margin-left 8
|
||||
:color colors/neutral-40})
|
||||
|
||||
|
@ -75,3 +66,8 @@
|
|||
(def top-section-container
|
||||
{:align-items :center
|
||||
:flex-direction :row})
|
||||
|
||||
(def title-container
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
|
|
@ -11,15 +11,8 @@
|
|||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ^:private max-reply-length
|
||||
280)
|
||||
|
||||
(defn- valid-reply?
|
||||
[reply]
|
||||
(<= (count reply) max-reply-length))
|
||||
|
||||
(defn- activity-reply-text-input
|
||||
[reply-input on-update-reply]
|
||||
[{:keys [on-update-reply max-reply-length valid-reply?]} reply-input]
|
||||
[rn/view
|
||||
[rn/view
|
||||
{:style {:margin-top 16
|
||||
|
@ -99,44 +92,12 @@
|
|||
body]
|
||||
body)])
|
||||
|
||||
(defn- activity-buttons
|
||||
[button-1 button-2 replying? reply-input]
|
||||
(let [size (if replying? 40 24)
|
||||
common-style (when replying?
|
||||
{:padding-vertical 9
|
||||
:flex-grow 1
|
||||
:flex-basis 0})]
|
||||
[rn/view style/buttons-container
|
||||
(when button-1
|
||||
[button/button
|
||||
(-> button-1
|
||||
(assoc :size size)
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
(:label button-1)])
|
||||
(when button-2
|
||||
[button/button
|
||||
(-> button-2
|
||||
(assoc :size size)
|
||||
(assoc :disabled (and replying? (not (valid-reply? @reply-input))))
|
||||
(update :style merge common-style))
|
||||
(:label button-2)])]))
|
||||
|
||||
(defn- activity-status
|
||||
[status]
|
||||
[rn/view
|
||||
{:style style/status
|
||||
:accessibility-label :activity-status}
|
||||
[status-tags/status-tag
|
||||
{:size :small
|
||||
:label (:label status)
|
||||
:status status}]])
|
||||
|
||||
(defn- activity-title
|
||||
[title replying?]
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:accessibility-label :activity-title
|
||||
:style (style/title replying?)
|
||||
:style (style/title)
|
||||
:size (if replying? :heading-2 :paragraph-1)}
|
||||
title])
|
||||
|
||||
|
@ -155,18 +116,42 @@
|
|||
:style style/unread-dot-container}
|
||||
[rn/view {:style style/unread-dot}]])
|
||||
|
||||
(defmulti footer-item-view (fn [item _ _] (:type item)))
|
||||
|
||||
(defmethod footer-item-view :button
|
||||
[{:keys [label subtype disable-when] :as button} replying? reply-input]
|
||||
(let [size (if replying? 40 24)
|
||||
common-style (when replying?
|
||||
{:padding-vertical 9
|
||||
:flex-grow 1
|
||||
:flex-basis 0})]
|
||||
[button/button
|
||||
(-> button
|
||||
(assoc :size size)
|
||||
(assoc :type subtype)
|
||||
(assoc :disabled (and replying? (disable-when @reply-input)))
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
label]))
|
||||
|
||||
(defmethod footer-item-view :status
|
||||
[{:keys [label subtype]} _ _]
|
||||
[status-tags/status-tag
|
||||
{:size :small
|
||||
:label label
|
||||
:status {:type subtype}}])
|
||||
|
||||
(defn- footer
|
||||
[_]
|
||||
[_ _]
|
||||
(let [reply-input (reagent/atom "")]
|
||||
(fn [{:keys [replying? on-update-reply status button-1 button-2]}]
|
||||
(fn [{:keys [replying? items] :as props}]
|
||||
[:<>
|
||||
(when replying?
|
||||
[activity-reply-text-input reply-input on-update-reply])
|
||||
(cond (some? status)
|
||||
[activity-status status]
|
||||
|
||||
(or button-1 button-2)
|
||||
[activity-buttons button-1 button-2 replying? reply-input])])))
|
||||
[activity-reply-text-input props reply-input])
|
||||
(when items
|
||||
[rn/view style/footer-container
|
||||
(for [{:keys [key] :as item} items]
|
||||
^{:key key}
|
||||
[footer-item-view item replying? reply-input])])])))
|
||||
|
||||
(defn view
|
||||
[{:keys [icon
|
||||
|
@ -187,9 +172,10 @@
|
|||
:flex 1}}
|
||||
[rn/view
|
||||
[rn/view {:style style/top-section-container}
|
||||
[activity-title title replying?]
|
||||
(when-not replying?
|
||||
[activity-timestamp timestamp])
|
||||
[rn/view {:style style/title-container}
|
||||
[activity-title title replying?]
|
||||
(when-not replying?
|
||||
[activity-timestamp timestamp])]
|
||||
(when (and unread? (not replying?))
|
||||
[activity-unread-dot])]
|
||||
(when context
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
(def ^:private themes
|
||||
{:container {:dark {:background-color colors/white-opa-70}
|
||||
:light {:background-color colors/neutral-80-opa-90}}
|
||||
:title {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:text {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:icon {:dark {:color colors/neutral-100}
|
||||
|
@ -51,7 +53,7 @@
|
|||
[i18n/label :t/undo]]])
|
||||
|
||||
(defn- toast-container
|
||||
[{:keys [left middle right container-style override-theme]}]
|
||||
[{:keys [left title text right container-style override-theme]}]
|
||||
[rn/view {:style (merge {:padding-left 12 :padding-right 12} container-style)}
|
||||
[rn/view
|
||||
{:style (merge-theme-style :container
|
||||
|
@ -66,16 +68,25 @@
|
|||
override-theme)}
|
||||
[rn/view {:style {:padding 2}} left]
|
||||
[rn/view {:style {:padding 4 :flex 1}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (merge-theme-style :text {} override-theme)
|
||||
:accessibility-label :toast-content}
|
||||
middle]]
|
||||
(when title
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style (merge-theme-style :title {} override-theme)
|
||||
:accessibility-label :toast-title}
|
||||
title])
|
||||
(when text
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (merge-theme-style :text {} override-theme)
|
||||
:accessibility-label :toast-content}
|
||||
text])]
|
||||
(when right right)]])
|
||||
|
||||
(defn toast
|
||||
[{:keys [icon icon-color text action undo-duration undo-on-press container-style override-theme]}]
|
||||
[{:keys [icon icon-color title text action undo-duration undo-on-press container-style
|
||||
override-theme]}]
|
||||
[toast-container
|
||||
{:left (when icon
|
||||
[icon/icon icon
|
||||
|
@ -84,7 +95,8 @@
|
|||
(get-in themes
|
||||
[:icon (or override-theme (theme/get-theme))
|
||||
:color]))}])
|
||||
:middle text
|
||||
:title title
|
||||
:text text
|
||||
:right (if undo-duration
|
||||
[toast-undo-action undo-duration undo-on-press override-theme]
|
||||
action)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
(def small-container-style
|
||||
(merge default-container-style
|
||||
{:padding-horizontal 8
|
||||
:padding-vertical 3}))
|
||||
:padding-vertical 1}))
|
||||
|
||||
(def large-container-style
|
||||
(merge default-container-style
|
||||
|
@ -56,8 +56,8 @@
|
|||
[size theme label]
|
||||
[base-tag
|
||||
{:size size
|
||||
:background-color colors/success-50-opa-10
|
||||
:icon :verified
|
||||
:background-color colors/success-50-opa-10
|
||||
:border-color colors/success-50-opa-20
|
||||
:label label
|
||||
:text-color (if (= theme :light)
|
||||
|
@ -77,18 +77,14 @@
|
|||
colors/danger-60)}])
|
||||
|
||||
(defn- pending
|
||||
[size theme label]
|
||||
[size _ label]
|
||||
[base-tag
|
||||
{:size size
|
||||
:icon :pending
|
||||
:label label
|
||||
:background-color (if (= theme :light)
|
||||
colors/neutral-10
|
||||
colors/neutral-80)
|
||||
:border-color (if (= theme :light)
|
||||
colors/neutral-20
|
||||
colors/neutral-70)
|
||||
:text-color colors/neutral-50}])
|
||||
:background-color colors/white-opa-5
|
||||
:border-color colors/white-opa-5
|
||||
:text-color colors/white-opa-70}])
|
||||
|
||||
(defn status-tag
|
||||
[{:keys [status size override-theme label]}]
|
||||
|
|
|
@ -8,19 +8,6 @@
|
|||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(rf/defn load-contacts
|
||||
{:events [::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 build-contact
|
||||
[{{:keys [multiaccount]
|
||||
:contacts/keys [contacts]}
|
||||
|
@ -66,7 +53,7 @@
|
|||
|
||||
(rf/defn add-contact
|
||||
"Add a contact and set pending to false"
|
||||
{:events [:contact.ui/add-to-contact-pressed]}
|
||||
{: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
|
||||
|
@ -87,26 +74,10 @@
|
|||
(assoc-in [:contacts/contacts public-key :contact-request-state]
|
||||
constants/contact-request-state-none))
|
||||
:json-rpc/call [{:method "wakuext_retractContactRequest"
|
||||
:params [{:contactId public-key}]
|
||||
:params [{:id public-key}]
|
||||
:on-success #(log/debug "contact removed successfully")}]
|
||||
:dispatch [:chat/offload-messages constants/timeline-chat-id]})
|
||||
|
||||
(rf/defn accept-contact-request
|
||||
{:events [:contact-requests.ui/accept-request]}
|
||||
[{:keys [db]} id]
|
||||
{:json-rpc/call [{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(rf/defn decline-contact-request
|
||||
{:events [:contact-requests.ui/decline-request]}
|
||||
[{:keys [db]} id]
|
||||
{:json-rpc/call [{:method "wakuext_dismissContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(rf/defn initialize-contacts
|
||||
[cofx]
|
||||
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.communities.core :as communities]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.invitations :as data-store.invitations]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
|
@ -41,6 +40,7 @@
|
|||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[status-im2.contexts.contacts.events :as contacts]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im2.common.log :as logging]
|
||||
[taoensso.timbre :as log]
|
||||
|
@ -468,7 +468,7 @@
|
|||
(transport/start-messenger)
|
||||
(initialize-transactions-management-enabled)
|
||||
(check-network-version network-id)
|
||||
(contact/initialize-contacts)
|
||||
(contacts/initialize-contacts)
|
||||
(initialize-browser)
|
||||
(mobile-network/on-network-status-change)
|
||||
(get-group-chat-invitations)
|
||||
|
|
|
@ -67,13 +67,13 @@
|
|||
(models.message/receive-many cofx response-js)
|
||||
|
||||
(seq activity-notifications)
|
||||
(do
|
||||
(let [notifications (->> activity-notifications
|
||||
types/js->clj
|
||||
(map data-store.activities/<-rpc))]
|
||||
(js-delete response-js "activityCenterNotifications")
|
||||
(rf/merge cofx
|
||||
(->> activity-notifications
|
||||
types/js->clj
|
||||
(map data-store.activities/<-rpc)
|
||||
activity-center/notifications-reconcile)
|
||||
(activity-center/notifications-reconcile notifications)
|
||||
(activity-center/show-toasts notifications)
|
||||
(process-next response-js sync-handler)))
|
||||
|
||||
(seq installations)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
:disabled blocked?
|
||||
:accessibility-label :add-to-contacts-button
|
||||
:action (when-not blocked?
|
||||
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key
|
||||
#(re-frame/dispatch [:contact.ui/add-contact-pressed public-key
|
||||
nil ens-name]))}])
|
||||
[{:label (i18n/label (if (or muted? blocked?) :t/unmute :t/mute))
|
||||
:icon :main-icons/notification
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im2.contexts.activity-center.notification-types :as types]
|
||||
[status-im2.contexts.chat.events :as chat.events]
|
||||
[status-im2.common.toasts.events :as toasts]
|
||||
status-im2.contexts.activity-center.notification.contact-requests.events
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im2.constants :as constants]))
|
||||
|
||||
(def defaults
|
||||
|
@ -93,6 +97,38 @@
|
|||
new-notifications)
|
||||
:dispatch [:activity-center.notifications/fetch-unread-count]}))
|
||||
|
||||
(rf/defn show-toasts
|
||||
{:events [:activity-center.notifications/show-toasts]}
|
||||
[{:keys [db]} new-notifications]
|
||||
(let [my-public-key (get-in db [:multiaccount :public-key])]
|
||||
(reduce (fn [cofx {:keys [author type accepted dismissed message name] :as x}]
|
||||
(cond
|
||||
(and (not= author my-public-key)
|
||||
(= type types/contact-request)
|
||||
(not accepted)
|
||||
(not dismissed))
|
||||
(toasts/upsert cofx
|
||||
{:icon :placeholder
|
||||
:icon-color colors/primary-50-opa-40
|
||||
:title (i18n/label :t/contact-request-sent-toast
|
||||
{:name name})
|
||||
:text (get-in message [:content :text])})
|
||||
|
||||
(and (= author my-public-key) ;; we show it for user who sent the request
|
||||
(= type types/contact-request)
|
||||
accepted
|
||||
(not dismissed))
|
||||
(toasts/upsert cofx
|
||||
{:icon :placeholder
|
||||
:icon-color colors/primary-50-opa-40
|
||||
:title (i18n/label :t/contact-request-accepted-toast
|
||||
{:name (:alias message)})})
|
||||
|
||||
:else
|
||||
cofx))
|
||||
{:db db}
|
||||
new-notifications)))
|
||||
|
||||
(rf/defn notifications-reconcile-from-response
|
||||
{:events [:activity-center/reconcile-notifications-from-response]}
|
||||
[cofx response]
|
||||
|
|
|
@ -14,38 +14,48 @@
|
|||
community-name (:name community)
|
||||
community-image (get-in community [:images :thumbnail :uri])]
|
||||
[quo/activity-log
|
||||
(merge
|
||||
{:title (i18n/label :t/join-request)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative timestamp)
|
||||
:unread? (not read)
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/wants-to-join)
|
||||
[quo/context-tag
|
||||
{:size :small
|
||||
:override-theme :dark
|
||||
:color colors/primary-50
|
||||
:style style/user-avatar-tag
|
||||
:text-style style/user-avatar-tag-text}
|
||||
{:uri community-image} community-name]]
|
||||
:status (case membership-status
|
||||
constants/activity-center-membership-status-accepted
|
||||
{:type :positive :label (i18n/label :t/accepted)}
|
||||
constants/activity-center-membership-status-declined
|
||||
{:type :negative :label (i18n/label :t/declined)}
|
||||
nil)}
|
||||
(case membership-status
|
||||
constants/activity-center-membership-status-pending
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-join-request
|
||||
:type :danger
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities.ui/decline-request-to-join-pressed
|
||||
community-id id]))}
|
||||
:button-2 {:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-join-request
|
||||
:type :positive
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities.ui/accept-request-to-join-pressed
|
||||
community-id id]))}}
|
||||
nil))]))
|
||||
{:title (i18n/label :t/join-request)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative timestamp)
|
||||
:unread? (not read)
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/wants-to-join)
|
||||
[quo/context-tag
|
||||
{:size :small
|
||||
:override-theme :dark
|
||||
:color colors/primary-50
|
||||
:style style/user-avatar-tag
|
||||
:text-style style/user-avatar-tag-text}
|
||||
{:uri community-image} community-name]]
|
||||
:items (case membership-status
|
||||
constants/activity-center-membership-status-accepted
|
||||
[{:type :status
|
||||
:subtype :positive
|
||||
:key :status-accepted
|
||||
:label (i18n/label :t/accepted)}]
|
||||
|
||||
constants/activity-center-membership-status-declined
|
||||
[{:type :status
|
||||
:subtype :negative
|
||||
:key :status-declined
|
||||
:label (i18n/label :t/declined)}]
|
||||
|
||||
constants/activity-center-membership-status-pending
|
||||
[{:type :button
|
||||
:subtype :danger
|
||||
:key :button-decline
|
||||
:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-join-request
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities.ui/decline-request-to-join-pressed
|
||||
community-id id]))}
|
||||
{:type :button
|
||||
:subtype :positive
|
||||
:key :button-accept
|
||||
:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-join-request
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities.ui/accept-request-to-join-pressed
|
||||
community-id id]))}]
|
||||
|
||||
nil)}]))
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn user-avatar-tag
|
||||
[user]
|
||||
(let [contact (rf/sub [:contacts/contact-by-identity user])]
|
||||
[user-id]
|
||||
(let [contact (rf/sub [:contacts/contact-by-identity user-id])]
|
||||
[quo/user-avatar-tag
|
||||
{:color :purple
|
||||
:override-theme :dark
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
(ns status-im2.contexts.activity-center.notification.contact-request.view
|
||||
(:require [quo2.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.activity-center.notification.common.view :as common]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [id author message last-message] :as notification}]
|
||||
(let [message (or message last-message)
|
||||
pressable (case (:contact-request-state message)
|
||||
constants/contact-request-message-state-accepted
|
||||
;; NOTE(2022-09-21): We need to dispatch to
|
||||
;; `:chat.ui/start-chat` instead of
|
||||
;; `:chat/navigate-to-chat`, otherwise the chat screen
|
||||
;; looks completely broken if it has never been opened
|
||||
;; before for the accepted contact.
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn []
|
||||
(rf/dispatch [:hide-popover])
|
||||
(rf/dispatch [:chat.ui/start-chat author]))}]
|
||||
[:<>])]
|
||||
(conj
|
||||
pressable
|
||||
[rn/view
|
||||
[quo/activity-log
|
||||
(merge
|
||||
{:title (i18n/label :t/contact-request)
|
||||
:icon :main-icons2/add-user
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/contact-request-sent)]
|
||||
:message {:body (get-in message [:content :text])}
|
||||
:status (case (:contact-request-state message)
|
||||
constants/contact-request-message-state-accepted
|
||||
{:type :positive :label (i18n/label :t/accepted)}
|
||||
constants/contact-request-message-state-declined
|
||||
{:type :negative :label (i18n/label :t/declined)}
|
||||
nil)}
|
||||
(case (:contact-request-state message)
|
||||
constants/contact-request-message-state-pending
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-contact-request
|
||||
:type :danger
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:contact-requests.ui/decline-request id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}
|
||||
:button-2 {:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-contact-request
|
||||
:type :positive
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:contact-requests.ui/accept-request id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}}
|
||||
nil))]])))
|
|
@ -0,0 +1,26 @@
|
|||
(ns status-im2.contexts.activity-center.notification.contact-requests.events
|
||||
(:require [utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn accept-contact-request
|
||||
{:events [:activity-center.contact-requests/accept-request]}
|
||||
[{:keys [db]} id]
|
||||
{:json-rpc/call [{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(rf/defn decline-contact-request
|
||||
{:events [:activity-center.contact-requests/decline-request]}
|
||||
[{:keys [db]} id]
|
||||
{:json-rpc/call [{:method "wakuext_declineContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(rf/defn cancel-outgoing-contact-request
|
||||
{:events [:activity-center.contact-requests/cancel-outgoing-request]}
|
||||
[{:keys [db]} id]
|
||||
{:json-rpc/call [{:method "wakuext_cancelOutgoingContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]})
|
|
@ -0,0 +1,119 @@
|
|||
(ns status-im2.contexts.activity-center.notification.contact-requests.view
|
||||
(:require [quo2.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.activity-center.notification.common.view :as common]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn outgoing-contact-request-view
|
||||
[{:keys [id chat-id message last-message] :as notification}]
|
||||
(let [{:keys [contact-request-state] :as message} (or message last-message)]
|
||||
(if (= contact-request-state constants/contact-request-message-state-accepted)
|
||||
[quo/activity-log
|
||||
{:title (i18n/label :t/contact-request-was-accepted)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:context [[common/user-avatar-tag chat-id]
|
||||
(i18n/label :t/contact-request-is-now-a-contact)]}
|
||||
:message {:body (get-in message [:content :text])}
|
||||
:items []]
|
||||
[quo/activity-log
|
||||
{:title (i18n/label :t/contact-request)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:context [(i18n/label :t/contact-request-outgoing)
|
||||
[common/user-avatar-tag chat-id]]
|
||||
:message {:body (get-in message [:content :text])}
|
||||
:items (case contact-request-state
|
||||
constants/contact-request-state-mutual
|
||||
[{:type :button
|
||||
:subtype :danger
|
||||
:key :button-cancel
|
||||
:label (i18n/label :t/cancel)
|
||||
:accessibility-label :cancel-contact-request
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:activity-center.contact-requests/cancel-outgoing-request
|
||||
(:from message)])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}
|
||||
{:type :status
|
||||
:subtype :pending
|
||||
:key :status-pending
|
||||
:label (i18n/label :t/pending)}]
|
||||
|
||||
constants/contact-request-message-state-declined
|
||||
[{:type :status
|
||||
:subtype :pending
|
||||
:key :status-pending
|
||||
:label (i18n/label :t/pending)}]
|
||||
|
||||
nil)}])))
|
||||
|
||||
(defn incoming-contact-request-view
|
||||
[{:keys [id author message last-message] :as notification}]
|
||||
(let [message (or message last-message)]
|
||||
[quo/activity-log
|
||||
{:title (i18n/label :t/contact-request)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/contact-request-sent)]
|
||||
:message {:body (get-in message [:content :text])}
|
||||
:items
|
||||
(case (:contact-request-state message)
|
||||
constants/contact-request-message-state-accepted
|
||||
[{:type :status
|
||||
:subtype :positive
|
||||
:key :status-accepted
|
||||
:label (i18n/label :t/accepted)}]
|
||||
|
||||
constants/contact-request-message-state-declined
|
||||
[{:type :status
|
||||
:subtype :negative
|
||||
:key :status-declined
|
||||
:label (i18n/label :t/declined)}]
|
||||
|
||||
constants/contact-request-state-mutual
|
||||
[{:type :button
|
||||
:subtype :danger
|
||||
:key :button-decline
|
||||
:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-contact-request
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:activity-center.contact-requests/decline-request id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}
|
||||
{:type :button
|
||||
:subtype :positive
|
||||
:key :button-accept
|
||||
:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-contact-request
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:activity-center.contact-requests/accept-request id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}]
|
||||
nil)}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [author message last-message] :as notification}]
|
||||
(let [{:keys [public-key]} (rf/sub [:multiaccount/contact])
|
||||
{:keys [contact-request-state]} (or message last-message)]
|
||||
(cond
|
||||
(= public-key author)
|
||||
[outgoing-contact-request-view notification]
|
||||
|
||||
(= contact-request-state constants/contact-request-message-state-accepted)
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn []
|
||||
(rf/dispatch [:hide-popover])
|
||||
(rf/dispatch [:chat.ui/start-chat {:public-key author}]))}
|
||||
[incoming-contact-request-view notification]]
|
||||
|
||||
:else
|
||||
[incoming-contact-request-view notification])))
|
|
@ -50,6 +50,13 @@
|
|||
(= contact-verification-status constants/contact-verification-status-declined)
|
||||
{:type :negative :label (i18n/label :t/declined)})))
|
||||
|
||||
(def ^:private max-reply-length
|
||||
280)
|
||||
|
||||
(defn- valid-reply?
|
||||
[reply]
|
||||
(<= (count reply) max-reply-length))
|
||||
|
||||
(defn view
|
||||
[_ _]
|
||||
(let [reply (atom "")]
|
||||
|
@ -62,57 +69,72 @@
|
|||
(= contact-verification-status constants/contact-verification-status-declined))
|
||||
[quo/activity-log
|
||||
(merge
|
||||
{:title (i18n/label :t/identity-verification-request)
|
||||
:icon :i/friend
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
{:title (i18n/label :t/identity-verification-request)
|
||||
:icon :i/friend
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:on-update-reply #(reset! reply %)
|
||||
:replying? replying?
|
||||
:context (context-tags challenger? notification)
|
||||
:message (activity-message challenger? notification)
|
||||
:status (activity-status challenger? contact-verification-status)}
|
||||
(if challenger?
|
||||
(when (= contact-verification-status constants/contact-verification-status-accepted)
|
||||
{:button-1 {:label (i18n/label :t/untrustworthy)
|
||||
:accessibility-label :mark-contact-verification-as-untrustworthy
|
||||
:type :danger
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:activity-center.contact-verification/mark-as-untrustworthy
|
||||
id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read id]))}
|
||||
:button-2 {:label (i18n/label :t/accept)
|
||||
:accessibility-label :mark-contact-verification-as-trusted
|
||||
:type :positive
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:activity-center.contact-verification/mark-as-trusted id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}})
|
||||
(when (= contact-verification-status constants/contact-verification-status-pending)
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-contact-verification
|
||||
:type :danger
|
||||
:on-press (fn []
|
||||
(hide-bottom-sheet-and-dispatch
|
||||
[:activity-center.contact-verification/decline id])
|
||||
(rf/dispatch
|
||||
[:activity-center.notifications/mark-as-read id]))}
|
||||
:button-2 (if replying?
|
||||
{:label (i18n/label :t/send-reply)
|
||||
:accessibility-label :reply-to-contact-verification
|
||||
:type :primary
|
||||
:on-press (fn []
|
||||
(hide-bottom-sheet-and-dispatch
|
||||
[:activity-center.contact-verification/reply id
|
||||
@reply])
|
||||
(rf/dispatch
|
||||
[:activity-center.notifications/mark-as-read id]))}
|
||||
{:label (i18n/label :t/message-reply)
|
||||
:accessibility-label :send-reply-to-contact-verification
|
||||
:type :primary
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:content view}
|
||||
{:notification notification
|
||||
:replying? true}]))})})))])))))
|
||||
:replying? replying?
|
||||
:max-reply-length max-reply-length
|
||||
:valid-reply? valid-reply?
|
||||
:context (context-tags challenger? notification)
|
||||
:message (activity-message challenger? notification)
|
||||
:status (activity-status challenger? contact-verification-status)
|
||||
:items
|
||||
(if challenger?
|
||||
(when (= contact-verification-status constants/contact-verification-status-accepted)
|
||||
[{:type :button
|
||||
:subtype :danger
|
||||
:key :button-mark-as-untrustworthy
|
||||
:label (i18n/label :t/untrustworthy)
|
||||
:accessibility-label :mark-contact-verification-as-untrustworthy
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:activity-center.contact-verification/mark-as-untrustworthy
|
||||
id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}
|
||||
{:type :button
|
||||
:subtype :positive
|
||||
:key :button-accept
|
||||
:label (i18n/label :t/accept)
|
||||
:accessibility-label :mark-contact-verification-as-trusted
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:activity-center.contact-verification/mark-as-trusted id])
|
||||
(rf/dispatch [:activity-center.notifications/mark-as-read
|
||||
id]))}])
|
||||
(when (= contact-verification-status constants/contact-verification-status-pending)
|
||||
[{:type :button
|
||||
:subtype :danger
|
||||
:key :button-decline
|
||||
:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-contact-verification
|
||||
:on-press (fn []
|
||||
(hide-bottom-sheet-and-dispatch
|
||||
[:activity-center.contact-verification/decline id])
|
||||
(rf/dispatch
|
||||
[:activity-center.notifications/mark-as-read id]))}
|
||||
(if replying?
|
||||
{:type :button
|
||||
:subtype :primary
|
||||
:key :button-reply
|
||||
:label (i18n/label :t/send-reply)
|
||||
:accessibility-label :reply-to-contact-verification
|
||||
:disable-when #(not (valid-reply? %))
|
||||
:on-press (fn []
|
||||
(hide-bottom-sheet-and-dispatch
|
||||
[:activity-center.contact-verification/reply id
|
||||
@reply])
|
||||
(rf/dispatch
|
||||
[:activity-center.notifications/mark-as-read id]))}
|
||||
{:type :button
|
||||
:subtype :primary
|
||||
:key :button-send-reply
|
||||
:label (i18n/label :t/message-reply)
|
||||
:accessibility-label :send-reply-to-contact-verification
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:content view}
|
||||
{:notification notification
|
||||
:replying? true}]))})]))})])))))
|
||||
|
|
|
@ -20,22 +20,26 @@
|
|||
[{:keys [id accepted author read timestamp chat-name chat-id]}]
|
||||
[pressable {:accepted accepted :chat-id chat-id}
|
||||
[quo/activity-log
|
||||
(merge
|
||||
{:title (i18n/label :t/added-to-group-chat)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative timestamp)
|
||||
:unread? (not read)
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/added-you-to)
|
||||
[quo/group-avatar-tag chat-name
|
||||
{:size :small
|
||||
:color :purple}]]}
|
||||
(when-not accepted
|
||||
{:button-2 {:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-group-chat-invitation
|
||||
:type :positive
|
||||
:on-press #(rf/dispatch [:activity-center.notifications/accept id])}
|
||||
:button-1 {:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-group-chat-invitation
|
||||
:type :danger
|
||||
:on-press #(rf/dispatch [:activity-center.notifications/dismiss id])}}))]])
|
||||
{:title (i18n/label :t/added-to-group-chat)
|
||||
:icon :i/add-user
|
||||
:timestamp (datetime/timestamp->relative timestamp)
|
||||
:unread? (not read)
|
||||
:context [[common/user-avatar-tag author]
|
||||
(i18n/label :t/added-you-to)
|
||||
[quo/group-avatar-tag chat-name
|
||||
{:size :small
|
||||
:color :purple}]]
|
||||
:items (when-not accepted
|
||||
[{:type :button
|
||||
:subtype :positive
|
||||
:key :button-accept
|
||||
:label (i18n/label :t/accept)
|
||||
:accessibility-label :accept-group-chat-invitation
|
||||
:on-press #(rf/dispatch [:activity-center.notifications/accept id])}
|
||||
{:type :button
|
||||
:subtype :danger
|
||||
:key :button-decline
|
||||
:label (i18n/label :t/decline)
|
||||
:accessibility-label :decline-group-chat-invitation
|
||||
:on-press #(rf/dispatch [:activity-center.notifications/dismiss
|
||||
id])}])}]])
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.contexts.activity-center.notification-types :as types]
|
||||
[status-im2.contexts.activity-center.notification.admin.view :as admin]
|
||||
[status-im2.contexts.activity-center.notification.contact-request.view :as contact-request]
|
||||
[status-im2.contexts.activity-center.notification.contact-requests.view :as contact-requests]
|
||||
[status-im2.contexts.activity-center.notification.contact-verification.view :as
|
||||
contact-verification]
|
||||
[status-im2.contexts.activity-center.notification.membership.view :as membership]
|
||||
|
@ -173,15 +173,15 @@
|
|||
(= type types/contact-verification)
|
||||
[contact-verification/view notification {}]
|
||||
|
||||
(= type types/contact-request)
|
||||
[contact-request/view notification]
|
||||
|
||||
(= type types/mention)
|
||||
[mentions/view notification]
|
||||
|
||||
(= type types/reply)
|
||||
[reply/view notification]
|
||||
|
||||
(= type types/contact-request)
|
||||
[contact-requests/view notification]
|
||||
|
||||
(= type types/admin)
|
||||
[admin/view notification]
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
(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]))
|
||||
|
||||
(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))))}))
|
||||
|
||||
(rf/defn initialize-contacts
|
||||
[cofx]
|
||||
(contacts-store/fetch-contacts-rpc cofx #(rf/dispatch [:contacts/contacts-loaded %])))
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"_comment": "THIS SHOULD NOT BE EDITED BY HAND.",
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.131.10",
|
||||
"commit-sha1": "8ff91ba0024f5ecf05d29904288537b236329f51",
|
||||
"src-sha256": "1m3an4fhzhh0vq8bb24xfjwdysfdd9qrz08a3gfz3ddahkh41jad"
|
||||
"_comment": "THIS SHOULD NOT BE EDITED BY HAND.",
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.131.11",
|
||||
"commit-sha1": "27730057d0914b0c53c3e87e1442def7edc76998",
|
||||
"src-sha256": "1c3q6nbki2fcs23jarkk673kr65frdfqbb3hsxp05mh8ybv1wgjw"
|
||||
}
|
||||
|
|
|
@ -1825,12 +1825,17 @@
|
|||
"new-ui": "New UI",
|
||||
"send-contact-request-message": "To start a chat you need to become contacts",
|
||||
"contact-request": "Contact request",
|
||||
"contact-request-was-accepted": "Contact request accepted",
|
||||
"contact-request-is-now-a-contact": "is now a contact",
|
||||
"contact-requests": "Contact requests",
|
||||
"say-hi": "Say hi",
|
||||
"opened": "Opened",
|
||||
"accepted": "Accepted",
|
||||
"declined": "Declined",
|
||||
"contact-request-sent": "sent contact request",
|
||||
"contact-request-sent-toast": "{{name}} sent you a contact request",
|
||||
"contact-request-accepted-toast": "{{name}} accepted your contact request",
|
||||
"contact-request-outgoing": "You’re trying to connect with",
|
||||
"contact-request-header": "👋 Contact requests",
|
||||
"contact-request-declined": "Declined ⓧ",
|
||||
"contact-request-accepted": "Accepted ✓",
|
||||
|
|
Loading…
Reference in New Issue