mirror of
https://github.com/status-im/status-react.git
synced 2025-01-11 11:34:45 +00:00
Display contact verification requests and allow users to decline them (#14223)
This commit is contained in:
parent
2ae57f7b21
commit
910bafc5f4
@ -1,6 +1,6 @@
|
||||
(ns status-im.activity-center.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.constants :as const]
|
||||
[status-im.data-store.activities :as data-store.activities]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
@ -18,21 +18,23 @@
|
||||
~excessively~ big, this implementation will probably need to be revisited."
|
||||
[db-notifications new-notifications]
|
||||
(reduce (fn [acc {:keys [id type read] :as notification}]
|
||||
(let [filter-status (if read :read :unread)]
|
||||
(cond-> (-> acc
|
||||
(update-in [type :read :data]
|
||||
(fn [data]
|
||||
(remove #(= id (:id %)) data)))
|
||||
(update-in [type :unread :data]
|
||||
(fn [data]
|
||||
(remove #(= id (:id %)) data))))
|
||||
(not (or (:dismissed notification) (:accepted notification)))
|
||||
(update-in [type filter-status :data]
|
||||
(fn [data]
|
||||
(->> notification
|
||||
(conj data)
|
||||
(sort-by (juxt :timestamp :id))
|
||||
reverse))))))
|
||||
(let [filter-status (if read :read :unread)
|
||||
remove-notification (fn [data]
|
||||
(remove #(= id (:id %)) data))
|
||||
insert-and-sort (fn [data]
|
||||
(->> notification
|
||||
(conj data)
|
||||
(sort-by (juxt :timestamp :id))
|
||||
reverse))]
|
||||
(as-> acc $
|
||||
(update-in $ [type :read :data] remove-notification)
|
||||
(update-in $ [type :unread :data] remove-notification)
|
||||
(update-in $ [const/activity-center-notification-type-no-type :read :data] remove-notification)
|
||||
(update-in $ [const/activity-center-notification-type-no-type :unread :data] remove-notification)
|
||||
(if (or (:dismissed notification) (:accepted notification))
|
||||
$
|
||||
(-> $ (update-in [type filter-status :data] insert-and-sort)
|
||||
(update-in [const/activity-center-notification-type-no-type filter-status :data] insert-and-sort))))))
|
||||
db-notifications
|
||||
new-notifications))
|
||||
|
||||
@ -43,11 +45,37 @@
|
||||
{:db (update-in db [:activity-center :notifications]
|
||||
update-notifications new-notifications)}))
|
||||
|
||||
;;;; Contact verification
|
||||
|
||||
(fx/defn contact-verification-decline
|
||||
{:events [:activity-center.contact-verification/decline]}
|
||||
[_ contact-verification-id]
|
||||
{::json-rpc/call [{:method "wakuext_declineContactVerificationRequest"
|
||||
:params [contact-verification-id]
|
||||
:on-success #(rf/dispatch [:activity-center.contact-verification/decline-success %])
|
||||
:on-error #(rf/dispatch [:activity-center.contact-verification/decline-error contact-verification-id %])}]})
|
||||
|
||||
(fx/defn contact-verification-decline-success
|
||||
{:events [:activity-center.contact-verification/decline-success]}
|
||||
[cofx response]
|
||||
(->> response
|
||||
:activityCenterNotifications
|
||||
(map data-store.activities/<-rpc)
|
||||
(notifications-reconcile cofx)))
|
||||
|
||||
(fx/defn contact-verification-decline-error
|
||||
{:events [:activity-center.contact-verification/decline-error]}
|
||||
[_ contact-verification-id error]
|
||||
(log/warn "Failed to decline contact verification"
|
||||
{:contact-verification-id contact-verification-id
|
||||
:error error})
|
||||
nil)
|
||||
|
||||
;;;; Notifications fetching and pagination
|
||||
|
||||
(def defaults
|
||||
{:filter-status :unread
|
||||
:filter-type constants/activity-center-notification-type-no-type
|
||||
:filter-type const/activity-center-notification-type-no-type
|
||||
:notifications-per-page 10})
|
||||
|
||||
(def start-or-end-cursor
|
||||
@ -70,8 +98,8 @@
|
||||
{:db (assoc-in db [:activity-center :notifications filter-type filter-status :loading?] true)
|
||||
::json-rpc/call [{:method (filter-status->rpc-method filter-status)
|
||||
:params [cursor (defaults :notifications-per-page) filter-type]
|
||||
:on-success #(re-frame/dispatch [:activity-center.notifications/fetch-success filter-type filter-status reset-data? %])
|
||||
:on-error #(re-frame/dispatch [:activity-center.notifications/fetch-error filter-type filter-status %])}]}))
|
||||
:on-success #(rf/dispatch [:activity-center.notifications/fetch-success filter-type filter-status reset-data? %])
|
||||
:on-error #(rf/dispatch [:activity-center.notifications/fetch-error filter-type filter-status %])}]}))
|
||||
|
||||
(fx/defn notifications-fetch-first-page
|
||||
{:events [:activity-center.notifications/fetch-first-page]}
|
||||
|
@ -2,7 +2,7 @@
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[day8.re-frame.test :as rf-test]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as c]
|
||||
[status-im.constants :as const]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
status-im.events
|
||||
[status-im.test-helpers :as h]))
|
||||
@ -12,8 +12,8 @@
|
||||
(rf/dispatch [:init/app-started]))
|
||||
|
||||
(defn remove-color-key
|
||||
"Remove `:color` key from notifications because they have random values that we
|
||||
can't assert against."
|
||||
"Remove `:color` key from notifications because they have random values that are
|
||||
inconvenient to assert against."
|
||||
[grouped-notifications {:keys [type status]}]
|
||||
(update-in grouped-notifications
|
||||
[type status :data]
|
||||
@ -21,27 +21,117 @@
|
||||
(map #(dissoc % :color) old))
|
||||
nil))
|
||||
|
||||
;;;; Contact verification
|
||||
|
||||
(deftest contact-verification-decline-test
|
||||
(testing "successfully declines and reconciles returned notification"
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(let [spy-queue (atom [])
|
||||
contact-verification-id 24
|
||||
expected-notification {:accepted false
|
||||
:author "0x04d03f"
|
||||
:chat-id "0x04d03f"
|
||||
:contact-verification-status 3
|
||||
:dismissed false
|
||||
:id 24
|
||||
:last-message nil
|
||||
:message {:command-parameters nil
|
||||
:content {:chat-id nil
|
||||
:ens-name nil
|
||||
:image nil
|
||||
:line-count nil
|
||||
:links nil
|
||||
:parsed-text nil
|
||||
:response-to nil
|
||||
:rtl? nil
|
||||
:sticker nil
|
||||
:text nil}
|
||||
:outgoing false
|
||||
:outgoing-status nil
|
||||
:quoted-message nil}
|
||||
:name "0x04d03f"
|
||||
:read true
|
||||
:reply-message nil
|
||||
:timestamp 1666647286000
|
||||
:type const/activity-center-notification-type-contact-verification}]
|
||||
(h/stub-fx-with-callbacks
|
||||
::json-rpc/call
|
||||
:on-success (constantly {:activityCenterNotifications
|
||||
[{:accepted false
|
||||
:author "0x04d03f"
|
||||
:chatId "0x04d03f"
|
||||
:contactVerificationStatus 3
|
||||
:dismissed false
|
||||
:id contact-verification-id
|
||||
:message {}
|
||||
:name "0x04d03f"
|
||||
:read true
|
||||
:timestamp 1666647286000
|
||||
:type const/activity-center-notification-type-contact-verification}]}))
|
||||
|
||||
(h/spy-fx spy-queue ::json-rpc/call)
|
||||
|
||||
(rf/dispatch [:activity-center.contact-verification/decline contact-verification-id])
|
||||
|
||||
(is (= {:method "wakuext_declineContactVerificationRequest"
|
||||
:params [contact-verification-id]}
|
||||
(-> @spy-queue
|
||||
(get-in [0 :args 0])
|
||||
(select-keys [:method :params]))))
|
||||
|
||||
(is (= {const/activity-center-notification-type-no-type
|
||||
{:read {:data [expected-notification]}
|
||||
:unread {:data []}}
|
||||
const/activity-center-notification-type-contact-verification
|
||||
{:read {:data [expected-notification]}
|
||||
:unread {:data []}}}
|
||||
(-> (h/db)
|
||||
(get-in [:activity-center :notifications])
|
||||
(remove-color-key {:type const/activity-center-notification-type-no-type
|
||||
:status :read})
|
||||
(remove-color-key {:type const/activity-center-notification-type-contact-verification
|
||||
:status :read})))))))
|
||||
|
||||
(testing "logs failure"
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(let [contact-verification-id 666]
|
||||
(h/using-log-test-appender
|
||||
(fn [logs]
|
||||
(h/stub-fx-with-callbacks ::json-rpc/call :on-error (constantly :fake-error))
|
||||
|
||||
(rf/dispatch [:activity-center.contact-verification/decline contact-verification-id])
|
||||
|
||||
(is (= {:args ["Failed to decline contact verification"
|
||||
{:contact-verification-id contact-verification-id
|
||||
:error :fake-error}]
|
||||
:level :warn}
|
||||
(last @logs)))))))))
|
||||
|
||||
;;;; Notification reconciliation
|
||||
|
||||
(deftest notifications-reconcile-test
|
||||
(testing "does nothing when there are no new notifications"
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(let [notifications {c/activity-center-notification-type-one-to-one-chat
|
||||
(let [notifications {const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat}
|
||||
:type const/activity-center-notification-type-one-to-one-chat}
|
||||
{:id "0x2"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x3"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}}
|
||||
c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}
|
||||
const/activity-center-notification-type-private-group-chat
|
||||
{:unread {:cursor ""
|
||||
:data [{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}]}}}]
|
||||
:type const/activity-center-notification-type-private-group-chat}]}}}]
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications] notifications])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/reconcile nil])
|
||||
@ -52,96 +142,127 @@
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
|
||||
{c/activity-center-notification-type-one-to-one-chat
|
||||
{const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1" :read true :type c/activity-center-notification-type-one-to-one-chat}
|
||||
{:id "0x2" :read true :type c/activity-center-notification-type-one-to-one-chat}]}
|
||||
:data [{:id "0x1" :read true :type const/activity-center-notification-type-one-to-one-chat}
|
||||
{:id "0x2" :read true :type const/activity-center-notification-type-one-to-one-chat}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x3" :read false :type c/activity-center-notification-type-one-to-one-chat}]}}
|
||||
2 {:unread {:cursor ""
|
||||
:data [{:id "0x4" :read false :type 2}
|
||||
{:id "0x6" :read false :type 2}]}}}])
|
||||
:data [{:id "0x3" :read false :type const/activity-center-notification-type-one-to-one-chat}]}}
|
||||
const/activity-center-notification-type-private-group-chat
|
||||
{:unread {:cursor ""
|
||||
:data [{:id "0x4" :read false :type const/activity-center-notification-type-private-group-chat}
|
||||
{:id "0x6" :read false :type const/activity-center-notification-type-private-group-chat}]}}}])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/reconcile
|
||||
[{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:dismissed true}
|
||||
{:id "0x3"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:accepted true}
|
||||
{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-private-group-chat
|
||||
:dismissed true}
|
||||
{:id "0x5"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-private-group-chat
|
||||
:accepted true}]])
|
||||
|
||||
(is (= {c/activity-center-notification-type-one-to-one-chat
|
||||
(is (= {const/activity-center-notification-type-no-type
|
||||
{:read {:data []}
|
||||
:unread {:data []}}
|
||||
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x2"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}
|
||||
:unread {:cursor ""
|
||||
:data []}}
|
||||
c/activity-center-notification-type-private-group-chat
|
||||
const/activity-center-notification-type-private-group-chat
|
||||
{:read {:data []}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x6"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}]}}}
|
||||
:type const/activity-center-notification-type-private-group-chat}]}}}
|
||||
(get-in (h/db) [:activity-center :notifications])))))
|
||||
|
||||
(testing "replaces old notifications with newly arrived ones"
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
|
||||
{c/activity-center-notification-type-one-to-one-chat
|
||||
{const/activity-center-notification-type-no-type
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x4"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-private-group-chat}
|
||||
{:id "0x6"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-private-group-chat}]}}
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}}
|
||||
c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}
|
||||
const/activity-center-notification-type-private-group-chat
|
||||
{:unread {:cursor ""
|
||||
:data [{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}
|
||||
:type const/activity-center-notification-type-private-group-chat}
|
||||
{:id "0x6"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}]}}}])
|
||||
:type const/activity-center-notification-type-private-group-chat}]}}}])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/reconcile
|
||||
[{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:last-message {}}
|
||||
{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-private-group-chat
|
||||
:author "0xabc"}
|
||||
{:id "0x6"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}]])
|
||||
:type const/activity-center-notification-type-private-group-chat}]])
|
||||
|
||||
(is (= {c/activity-center-notification-type-one-to-one-chat
|
||||
(is (= {const/activity-center-notification-type-no-type
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:last-message {}}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x6"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-private-group-chat}
|
||||
{:id "0x4"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-private-group-chat
|
||||
:author "0xabc"}]}}
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:last-message {}}]}
|
||||
:unread {:data []}}
|
||||
c/activity-center-notification-type-private-group-chat
|
||||
const/activity-center-notification-type-private-group-chat
|
||||
{:read {:data []}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x6"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat}
|
||||
:type const/activity-center-notification-type-private-group-chat}
|
||||
{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-private-group-chat
|
||||
:type const/activity-center-notification-type-private-group-chat
|
||||
:author "0xabc"}]}}}
|
||||
(get-in (h/db) [:activity-center :notifications])))))
|
||||
|
||||
@ -149,23 +270,29 @@
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
|
||||
{c/activity-center-notification-type-one-to-one-chat
|
||||
{const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}}}])
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}}])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/reconcile
|
||||
[{:id "0x1"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]])
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]])
|
||||
|
||||
(is (= {c/activity-center-notification-type-one-to-one-chat
|
||||
(is (= {const/activity-center-notification-type-no-type
|
||||
{:read {:data []}
|
||||
:unread {:data [{:id "0x1"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}
|
||||
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data []}
|
||||
:unread {:data [{:id "0x1"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}}}
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}}
|
||||
(get-in (h/db) [:activity-center :notifications])))))
|
||||
|
||||
;; Sorting by timestamp and ID is compatible with what the backend does when
|
||||
@ -174,46 +301,59 @@
|
||||
(rf-test/run-test-sync
|
||||
(setup)
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
|
||||
{c/activity-center-notification-type-one-to-one-chat
|
||||
{const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x1" :read true :type c/activity-center-notification-type-one-to-one-chat :timestamp 1}
|
||||
{:id "0x2" :read true :type c/activity-center-notification-type-one-to-one-chat :timestamp 1}]}
|
||||
:data [{:id "0x1" :read true :type const/activity-center-notification-type-one-to-one-chat :timestamp 1}
|
||||
{:id "0x2" :read true :type const/activity-center-notification-type-one-to-one-chat :timestamp 1}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x3" :read false :type c/activity-center-notification-type-one-to-one-chat :timestamp 50}
|
||||
{:id "0x4" :read false :type c/activity-center-notification-type-one-to-one-chat :timestamp 100}
|
||||
{:id "0x5" :read false :type c/activity-center-notification-type-one-to-one-chat :timestamp 100}]}}}])
|
||||
:data [{:id "0x3" :read false :type const/activity-center-notification-type-one-to-one-chat :timestamp 50}
|
||||
{:id "0x4" :read false :type const/activity-center-notification-type-one-to-one-chat :timestamp 100}
|
||||
{:id "0x5" :read false :type const/activity-center-notification-type-one-to-one-chat :timestamp 100}]}}}])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/reconcile
|
||||
[{:id "0x1" :read true :type c/activity-center-notification-type-one-to-one-chat :timestamp 1 :last-message {}}
|
||||
{:id "0x4" :read false :type c/activity-center-notification-type-one-to-one-chat :timestamp 100 :last-message {}}]])
|
||||
[{:id "0x1" :read true :type const/activity-center-notification-type-one-to-one-chat :timestamp 1 :last-message {}}
|
||||
{:id "0x4" :read false :type const/activity-center-notification-type-one-to-one-chat :timestamp 100 :last-message {}}]])
|
||||
|
||||
(is (= {c/activity-center-notification-type-one-to-one-chat
|
||||
(is (= {const/activity-center-notification-type-no-type
|
||||
{:read {:data [{:id "0x1"
|
||||
:read true
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 1
|
||||
:last-message {}}]}
|
||||
:unread {:data [{:id "0x4"
|
||||
:read false
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 100
|
||||
:last-message {}}]}}
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
{:read {:cursor ""
|
||||
:data [{:id "0x2"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 1}
|
||||
{:id "0x1"
|
||||
:read true
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 1
|
||||
:last-message {}}]}
|
||||
:unread {:cursor ""
|
||||
:data [{:id "0x5"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 100}
|
||||
{:id "0x4"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 100
|
||||
:last-message {}}
|
||||
{:id "0x3"
|
||||
:read false
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:timestamp 50}]}}}
|
||||
(get-in (h/db) [:activity-center :notifications]))))))
|
||||
|
||||
;;;; Notifications fetching and pagination
|
||||
|
||||
(deftest notifications-fetch-test
|
||||
(testing "fetches first page"
|
||||
(rf-test/run-test-sync
|
||||
@ -223,22 +363,22 @@
|
||||
::json-rpc/call
|
||||
:on-success (constantly {:cursor "10"
|
||||
:notifications [{:id "0x1"
|
||||
:type c/activity-center-notification-type-one-to-one-chat
|
||||
:type const/activity-center-notification-type-one-to-one-chat
|
||||
:read false
|
||||
:chatId "0x9"}]}))
|
||||
(h/spy-fx spy-queue ::json-rpc/call)
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-first-page
|
||||
{:filter-type c/activity-center-notification-type-one-to-one-chat}])
|
||||
{:filter-type const/activity-center-notification-type-one-to-one-chat}])
|
||||
|
||||
(is (= :unread (get-in (h/db) [:activity-center :filter :status])))
|
||||
(is (= "" (get-in @spy-queue [0 :args 0 :params 0]))
|
||||
"Should be called with empty cursor when fetching first page")
|
||||
(is (= {c/activity-center-notification-type-one-to-one-chat
|
||||
(is (= {const/activity-center-notification-type-one-to-one-chat
|
||||
{:unread {:cursor "10"
|
||||
:data [{:chat-id "0x9"
|
||||
:chat-name nil
|
||||
:chat-type c/activity-center-notification-type-one-to-one-chat
|
||||
:chat-type const/activity-center-notification-type-one-to-one-chat
|
||||
:group-chat false
|
||||
:id "0x1"
|
||||
:public? false
|
||||
@ -246,10 +386,10 @@
|
||||
:message nil
|
||||
:read false
|
||||
:reply-message nil
|
||||
:type c/activity-center-notification-type-one-to-one-chat}]}}}
|
||||
:type const/activity-center-notification-type-one-to-one-chat}]}}}
|
||||
(remove-color-key (get-in (h/db) [:activity-center :notifications])
|
||||
{:status :unread
|
||||
:type c/activity-center-notification-type-one-to-one-chat}))))))
|
||||
:type const/activity-center-notification-type-one-to-one-chat}))))))
|
||||
|
||||
(testing "does not fetch next page when pagination cursor reached the end"
|
||||
(rf-test/run-test-sync
|
||||
@ -259,8 +399,8 @@
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
|
||||
:unread])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
|
||||
c/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
const/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
""])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-next-page])
|
||||
@ -278,8 +418,8 @@
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
|
||||
:unread])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
|
||||
c/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
const/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
nil])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-next-page])
|
||||
@ -294,15 +434,15 @@
|
||||
::json-rpc/call
|
||||
:on-success (constantly {:cursor ""
|
||||
:notifications [{:id "0x1"
|
||||
:type c/activity-center-notification-type-mention
|
||||
:type const/activity-center-notification-type-mention
|
||||
:read false
|
||||
:chatId "0x9"}]}))
|
||||
(h/spy-fx spy-queue ::json-rpc/call)
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
|
||||
:unread])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
|
||||
c/activity-center-notification-type-mention])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-mention :unread :cursor]
|
||||
const/activity-center-notification-type-mention])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-mention :unread :cursor]
|
||||
"10"])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-next-page])
|
||||
@ -310,7 +450,7 @@
|
||||
(is (= "wakuext_unreadActivityCenterNotifications" (get-in @spy-queue [0 :args 0 :method])))
|
||||
(is (= "10" (get-in @spy-queue [0 :args 0 :params 0]))
|
||||
"Should be called with current cursor")
|
||||
(is (= {c/activity-center-notification-type-mention
|
||||
(is (= {const/activity-center-notification-type-mention
|
||||
{:unread {:cursor ""
|
||||
:data [{:chat-id "0x9"
|
||||
:chat-name nil
|
||||
@ -320,10 +460,10 @@
|
||||
:message nil
|
||||
:read false
|
||||
:reply-message nil
|
||||
:type c/activity-center-notification-type-mention}]}}}
|
||||
:type const/activity-center-notification-type-mention}]}}}
|
||||
(remove-color-key (get-in (h/db) [:activity-center :notifications])
|
||||
{:status :unread
|
||||
:type c/activity-center-notification-type-mention}))))))
|
||||
:type const/activity-center-notification-type-mention}))))))
|
||||
|
||||
(testing "does not fetch next page while it is still loading"
|
||||
(rf-test/run-test-sync
|
||||
@ -333,10 +473,10 @@
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
|
||||
:read])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
|
||||
c/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :read :cursor]
|
||||
const/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :read :cursor]
|
||||
"10"])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :read :loading?]
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :read :loading?]
|
||||
true])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-next-page])
|
||||
@ -353,15 +493,15 @@
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
|
||||
:unread])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
|
||||
c/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
const/activity-center-notification-type-one-to-one-chat])
|
||||
(rf/dispatch [:test/assoc-in [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :unread :cursor]
|
||||
""])
|
||||
|
||||
(rf/dispatch [:activity-center.notifications/fetch-first-page])
|
||||
|
||||
(is (nil? (get-in (h/db) [:activity-center :notifications c/activity-center-notification-type-one-to-one-chat :unread :loading?])))
|
||||
(is (nil? (get-in (h/db) [:activity-center :notifications const/activity-center-notification-type-one-to-one-chat :unread :loading?])))
|
||||
(is (= [:activity-center.notifications/fetch-error
|
||||
c/activity-center-notification-type-one-to-one-chat
|
||||
const/activity-center-notification-type-one-to-one-chat
|
||||
:unread
|
||||
:fake-error]
|
||||
(:args (last @spy-queue))))))))
|
||||
|
@ -22,6 +22,13 @@
|
||||
(def ^:const contact-request-state-received 3)
|
||||
(def ^:const contact-request-state-dismissed 4)
|
||||
|
||||
(def ^:const contact-verification-state-unknown 0)
|
||||
(def ^:const contact-verification-state-pending 1)
|
||||
(def ^:const contact-verification-state-accepted 2)
|
||||
(def ^:const contact-verification-state-declined 3)
|
||||
(def ^:const contact-verification-state-cancelled 4)
|
||||
(def ^:const contact-verification-state-trusted 5)
|
||||
|
||||
(def ^:const emoji-reaction-love 1)
|
||||
(def ^:const emoji-reaction-thumbs-up 2)
|
||||
(def ^:const emoji-reaction-thumbs-down 3)
|
||||
@ -183,11 +190,15 @@
|
||||
(def ^:const activity-center-notification-type-mention 3)
|
||||
(def ^:const activity-center-notification-type-reply 4)
|
||||
(def ^:const activity-center-notification-type-contact-request 5)
|
||||
(def ^:const activity-center-notification-type-contact-verification 6)
|
||||
|
||||
;; TODO: Remove this constant once the old Notification Center code is removed.
|
||||
;; Its value clashes with the new constant `activity-center-notification-type-contact-verification`
|
||||
;; used in status-go.
|
||||
(def ^:const activity-center-notification-type-contact-request-retracted 6)
|
||||
|
||||
;; TODO: Replace with correct enum values once status-go implements them.
|
||||
(def ^:const activity-center-notification-type-admin 66610)
|
||||
(def ^:const activity-center-notification-type-identity-verification 66611)
|
||||
(def ^:const activity-center-notification-type-tx 66612)
|
||||
(def ^:const activity-center-notification-type-membership 66613)
|
||||
(def ^:const activity-center-notification-type-system 66614)
|
||||
|
@ -1,44 +1,44 @@
|
||||
(ns status-im.data-store.activities
|
||||
(:require [status-im.data-store.messages :as messages]
|
||||
[status-im.constants :as constants]
|
||||
(:require [clojure.set :as set]
|
||||
[quo.design-system.colors :as colors]
|
||||
clojure.set))
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.messages :as messages]))
|
||||
|
||||
(defn rpc->type [{:keys [type name] :as chat}]
|
||||
(cond
|
||||
(= constants/activity-center-notification-type-reply type)
|
||||
(defn- rpc->type [{:keys [type name] :as chat}]
|
||||
(case type
|
||||
constants/activity-center-notification-type-reply
|
||||
(assoc chat
|
||||
:chat-name name
|
||||
:chat-type constants/private-group-chat-type)
|
||||
|
||||
(= constants/activity-center-notification-type-mention type)
|
||||
constants/activity-center-notification-type-mention
|
||||
(assoc chat
|
||||
:chat-type constants/private-group-chat-type
|
||||
:chat-name name)
|
||||
|
||||
(= constants/activity-center-notification-type-private-group-chat type)
|
||||
constants/activity-center-notification-type-private-group-chat
|
||||
(assoc chat
|
||||
:chat-type constants/private-group-chat-type
|
||||
:chat-name name
|
||||
:public? false
|
||||
:group-chat true)
|
||||
|
||||
(= constants/activity-center-notification-type-one-to-one-chat type)
|
||||
constants/activity-center-notification-type-one-to-one-chat
|
||||
(assoc chat
|
||||
:chat-type constants/one-to-one-chat-type
|
||||
:chat-name name
|
||||
:public? false
|
||||
:group-chat false)
|
||||
|
||||
:else
|
||||
chat))
|
||||
|
||||
(defn <-rpc [item]
|
||||
(-> item
|
||||
rpc->type
|
||||
(clojure.set/rename-keys {:lastMessage :last-message
|
||||
:replyMessage :reply-message
|
||||
:chatId :chat-id})
|
||||
(set/rename-keys {:lastMessage :last-message
|
||||
:replyMessage :reply-message
|
||||
:chatId :chat-id
|
||||
:contactVerificationStatus :contact-verification-status})
|
||||
(assoc :color (rand-nth colors/chat-colors))
|
||||
(update :last-message #(when % (messages/<-rpc %)))
|
||||
(update :message #(when % (messages/<-rpc %)))
|
||||
|
101
src/status_im/data_store/activities_test.cljs
Normal file
101
src/status_im/data_store/activities_test.cljs
Normal file
@ -0,0 +1,101 @@
|
||||
(ns status-im.data-store.activities-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.activities :as store]))
|
||||
|
||||
(def chat-id
|
||||
"0x04c66155")
|
||||
|
||||
(def chat-name
|
||||
"0x04c661")
|
||||
|
||||
(def raw-notification
|
||||
{:chatId chat-id
|
||||
:contactVerificationStatus constants/contact-verification-state-pending
|
||||
:lastMessage {}
|
||||
:name chat-name
|
||||
:replyMessage {}})
|
||||
|
||||
(deftest <-rpc-test
|
||||
(testing "assocs random chat color"
|
||||
(is (contains? (set colors/chat-colors) (:color (store/<-rpc raw-notification)))))
|
||||
|
||||
(testing "renames keys"
|
||||
(is (= {:name chat-name
|
||||
:chat-id chat-id
|
||||
:contact-verification-status constants/contact-verification-state-pending}
|
||||
(-> raw-notification
|
||||
store/<-rpc
|
||||
(dissoc :color :last-message :message :reply-message)))))
|
||||
|
||||
(testing "transforms messages from RPC response"
|
||||
(is (= {:last-message {:quoted-message nil
|
||||
:outgoing-status nil
|
||||
:command-parameters nil
|
||||
:content {:sticker nil
|
||||
:rtl? nil
|
||||
:ens-name nil
|
||||
:parsed-text nil
|
||||
:response-to nil
|
||||
:chat-id nil
|
||||
:image nil
|
||||
:line-count nil
|
||||
:links nil
|
||||
:text nil}
|
||||
:outgoing false}
|
||||
:message nil
|
||||
:reply-message {:quoted-message nil
|
||||
:outgoing-status nil
|
||||
:command-parameters nil
|
||||
:content {:sticker nil
|
||||
:rtl? nil
|
||||
:ens-name nil
|
||||
:parsed-text nil
|
||||
:response-to nil
|
||||
:chat-id nil
|
||||
:image nil
|
||||
:line-count nil
|
||||
:links nil
|
||||
:text nil}
|
||||
:outgoing false}}
|
||||
(-> raw-notification
|
||||
store/<-rpc
|
||||
(select-keys [:last-message :message :reply-message])))))
|
||||
|
||||
(testing "augments notification based on its type"
|
||||
(is (= {:chat-name chat-name
|
||||
:chat-type constants/private-group-chat-type
|
||||
:name chat-name}
|
||||
(-> raw-notification
|
||||
(assoc :type constants/activity-center-notification-type-reply)
|
||||
store/<-rpc
|
||||
(select-keys [:name :chat-type :chat-name :public? :group-chat]))))
|
||||
|
||||
(is (= {:chat-name chat-name
|
||||
:chat-type constants/private-group-chat-type
|
||||
:name chat-name}
|
||||
(-> raw-notification
|
||||
(assoc :type constants/activity-center-notification-type-mention)
|
||||
store/<-rpc
|
||||
(select-keys [:name :chat-type :chat-name :public? :group-chat]))))
|
||||
|
||||
(is (= {:chat-name chat-name
|
||||
:chat-type constants/private-group-chat-type
|
||||
:group-chat true
|
||||
:name chat-name
|
||||
:public? false}
|
||||
(-> raw-notification
|
||||
(assoc :type constants/activity-center-notification-type-private-group-chat)
|
||||
store/<-rpc
|
||||
(select-keys [:name :chat-type :chat-name :public? :group-chat]))))
|
||||
|
||||
(is (= {:chat-name chat-name
|
||||
:chat-type constants/one-to-one-chat-type
|
||||
:group-chat false
|
||||
:name chat-name
|
||||
:public? false}
|
||||
(-> raw-notification
|
||||
(assoc :type constants/activity-center-notification-type-one-to-one-chat)
|
||||
store/<-rpc
|
||||
(select-keys [:name :chat-type :chat-name :public? :group-chat]))))))
|
@ -20,6 +20,7 @@
|
||||
(clojure.set/rename-keys {:id :message-id
|
||||
:whisperTimestamp :whisper-timestamp
|
||||
:editedAt :edited-at
|
||||
:contactVerificationState :contact-verification-state
|
||||
:contactRequestState :contact-request-state
|
||||
:commandParameters :command-parameters
|
||||
:gapParameters :gap-parameters
|
||||
|
@ -20,6 +20,8 @@
|
||||
:response-to "a"
|
||||
:links nil}
|
||||
:whisper-timestamp 1
|
||||
:contact-verification-state 1
|
||||
:contact-request-state 2
|
||||
:outgoing-status :sending
|
||||
:command-parameters nil
|
||||
:outgoing true
|
||||
@ -35,6 +37,8 @@
|
||||
:whisperTimestamp 1
|
||||
:parsedText "parsed-text"
|
||||
:ensName "ens-name"
|
||||
:contactVerificationState 1
|
||||
:contactRequestState 2
|
||||
:localChatId chat-id
|
||||
:from from
|
||||
:text "hta"
|
||||
|
@ -6,9 +6,10 @@
|
||||
prefer to use it for more general purpose concepts, such as the re-frame event
|
||||
layer."
|
||||
(:require [re-frame.core :as rf]
|
||||
[re-frame.registrar :as rf-registrar]
|
||||
[re-frame.db :as rf-db]
|
||||
[re-frame.events :as rf-events]
|
||||
[re-frame.db :as rf-db]))
|
||||
[re-frame.registrar :as rf-registrar]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn db
|
||||
"A simple wrapper to get the latest value from the app db."
|
||||
@ -85,3 +86,17 @@
|
||||
(original-on-error (on-error fx-map))
|
||||
(and original-on-success on-success)
|
||||
(original-on-success (on-success fx-map)))))))
|
||||
|
||||
(defn using-log-test-appender
|
||||
"Rebinds `taoensso.timbre/*config*` to use a custom test appender that persists
|
||||
all `taoensso.timbre/log` call arguments. `f` is called with the atom
|
||||
reference so that tests can de-reference it and verify log messages and their
|
||||
respective levels."
|
||||
[f]
|
||||
(let [logs (atom [])]
|
||||
(binding [log/*config* (assoc-in log/*config*
|
||||
[:appenders :test]
|
||||
{:enabled? true
|
||||
:fn (fn [{:keys [vargs level]}]
|
||||
(swap! logs conj {:args vargs :level level}))})]
|
||||
(f logs))))
|
||||
|
@ -15,98 +15,114 @@
|
||||
[status-im.utils.handlers :refer [<sub >evt]]
|
||||
[quo.components.safe-area :as safe-area]))
|
||||
|
||||
(defn activity-title
|
||||
[{:keys [type]}]
|
||||
(case type
|
||||
constants/activity-center-notification-type-contact-request
|
||||
(i18n/label :t/contact-request)
|
||||
;;;; Misc
|
||||
|
||||
constants/activity-center-notification-type-one-to-one-chat
|
||||
"Dummy 1:1 chat title"
|
||||
(defn sender-name
|
||||
[contact]
|
||||
(or (get-in contact [:names :nickname])
|
||||
(get-in contact [:names :three-words-name])))
|
||||
|
||||
"Dummy default title"))
|
||||
(defmulti notification-component :type)
|
||||
|
||||
(defn activity-icon
|
||||
[{:keys [type]}]
|
||||
(case type
|
||||
constants/activity-center-notification-type-contact-request
|
||||
:main-icons2/add-user
|
||||
:main-icons2/placeholder))
|
||||
;;;; Contact request notifications
|
||||
|
||||
(defn activity-context
|
||||
[{:keys [message last-message type]}]
|
||||
(case type
|
||||
constants/activity-center-notification-type-contact-request
|
||||
(let [message (or message last-message)
|
||||
contact (<sub [:contacts/contact-by-identity (:from message)])
|
||||
sender-name (or (get-in contact [:names :nickname])
|
||||
(get-in contact [:names :three-words-name]))]
|
||||
[[context-tags/user-avatar-tag
|
||||
{:color :purple
|
||||
:override-theme :dark
|
||||
:size :small
|
||||
:style {:background-color colors/white-opa-10}
|
||||
:text-style {:color colors/white}}
|
||||
sender-name
|
||||
(multiaccounts/displayed-photo contact)]
|
||||
[rn/text {:style {:color colors/white}}
|
||||
(i18n/label :t/contact-request-sent)]])
|
||||
nil))
|
||||
(defmethod notification-component constants/activity-center-notification-type-contact-request
|
||||
[{:keys [id] :as notification}]
|
||||
(let [message (or (:message notification) (:last-message notification))
|
||||
contact (<sub [:contacts/contact-by-identity (:author notification)])
|
||||
pressable (case (:contact-request-state message)
|
||||
constants/contact-request-message-state-accepted
|
||||
;; NOTE [2022-09-21]: We need to dispatch to
|
||||
;; `:contact.ui/send-message-pressed` instead of
|
||||
;; `:chat.ui/navigate-to-chat`, otherwise the chat screen looks completely
|
||||
;; broken if it has never been opened before for the accepted contact.
|
||||
[animation/pressable {:on-press (fn []
|
||||
(>evt [:hide-popover])
|
||||
(>evt [:contact.ui/send-message-pressed {:public-key (:author notification)}]))}]
|
||||
[:<>])]
|
||||
(conj pressable
|
||||
[activity-logs/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 [[context-tags/user-avatar-tag
|
||||
{:color :purple
|
||||
:override-theme :dark
|
||||
:size :small
|
||||
:style {:background-color colors/white-opa-10}
|
||||
:text-style {:color colors/white}}
|
||||
(sender-name contact)
|
||||
(multiaccounts/displayed-photo contact)]
|
||||
[rn/text {:style {:color colors/white}}
|
||||
(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-state-mutual
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:type :danger
|
||||
:on-press #(>evt [:contact-requests.ui/decline-request id])}
|
||||
:button-2 {:label (i18n/label :t/message-reply)
|
||||
:type :success
|
||||
:override-background-color colors/success-60
|
||||
:on-press #(>evt [:contact-requests.ui/accept-request id])}}
|
||||
nil))])))
|
||||
|
||||
(defn activity-message
|
||||
[{:keys [message last-message]}]
|
||||
{:body (get-in (or message last-message) [:content :text])})
|
||||
;;;; Contact verification notifications
|
||||
|
||||
(defn activity-status
|
||||
[notification]
|
||||
(case (get-in notification [:message :contact-request-state])
|
||||
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))
|
||||
(defmethod notification-component constants/activity-center-notification-type-contact-verification
|
||||
[{:keys [id contact-verification-status] :as notification}]
|
||||
(let [message (or (:message notification) (:last-notification notification))
|
||||
contact (<sub [:contacts/contact-by-identity (:author notification)])]
|
||||
[activity-logs/activity-log
|
||||
(merge {:title (i18n/label :t/identity-verification-request)
|
||||
:icon :main-icons2/friend
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:unread? (not (:read notification))
|
||||
:context [[context-tags/user-avatar-tag
|
||||
{:color :purple
|
||||
:override-theme :dark
|
||||
:size :small
|
||||
:style {:background-color colors/white-opa-10}
|
||||
:text-style {:color colors/white}}
|
||||
(sender-name contact)
|
||||
(multiaccounts/displayed-photo contact)]
|
||||
[rn/text {:style {:color colors/white}}
|
||||
(str (i18n/label :t/identity-verification-request-sent)
|
||||
":")]]
|
||||
:message (case contact-verification-status
|
||||
(constants/contact-verification-state-pending
|
||||
constants/contact-verification-state-declined)
|
||||
{:body (get-in message [:content :text])}
|
||||
nil)
|
||||
:status (case contact-verification-status
|
||||
constants/contact-verification-state-declined
|
||||
{:type :negative :label (i18n/label :t/declined)}
|
||||
nil)}
|
||||
(case contact-verification-status
|
||||
constants/contact-verification-state-pending
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:type :danger
|
||||
:on-press #(>evt [:activity-center.contact-verification/decline id])}
|
||||
:button-2 {:label (i18n/label :t/accept)
|
||||
:type :primary
|
||||
;; TODO: The acceptance flow will be implemented in follow-up PRs.
|
||||
:on-press identity}}
|
||||
nil))]))
|
||||
|
||||
(defn activity-buttons
|
||||
[{:keys [id type]}]
|
||||
(case type
|
||||
constants/activity-center-notification-type-contact-request
|
||||
{:button-1 {:label (i18n/label :t/decline)
|
||||
:type :danger
|
||||
:on-press #(>evt [:contact-requests.ui/decline-request id])}
|
||||
:button-2 {:label (i18n/label :t/accept)
|
||||
:type :success
|
||||
:override-background-color colors/success-60
|
||||
:on-press #(>evt [:contact-requests.ui/accept-request id])}}
|
||||
nil))
|
||||
|
||||
(defn activity-pressable
|
||||
[notification activity]
|
||||
(case (get-in notification [:message :contact-request-state])
|
||||
constants/contact-request-message-state-accepted
|
||||
;; NOTE [2022-09-21]: We need to dispatch to
|
||||
;; `:contact.ui/send-message-pressed` instead of
|
||||
;; `:chat.ui/navigate-to-chat`, otherwise the chat screen looks completely
|
||||
;; broken if it has never been opened before for the accepted contact.
|
||||
[animation/pressable {:on-press (fn []
|
||||
(>evt [:hide-popover])
|
||||
(>evt [:contact.ui/send-message-pressed {:public-key (:author notification)}]))}
|
||||
activity]
|
||||
activity))
|
||||
;;;; Type-independent components
|
||||
|
||||
(defn render-notification
|
||||
[notification index]
|
||||
[rn/view {:margin-top (if (= 0 index) 0 4)
|
||||
:padding-horizontal 20}
|
||||
[activity-pressable notification
|
||||
[activity-logs/activity-log
|
||||
(merge {:context (activity-context notification)
|
||||
:icon (activity-icon notification)
|
||||
:message (activity-message notification)
|
||||
:status (activity-status notification)
|
||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||
:title (activity-title notification)
|
||||
:unread? (not (:read notification))}
|
||||
(activity-buttons notification))]]])
|
||||
[notification-component notification]])
|
||||
|
||||
(defn filter-selector-read-toggle
|
||||
[]
|
||||
@ -164,7 +180,7 @@
|
||||
:label (i18n/label :t/replies)}
|
||||
{:id constants/activity-center-notification-type-contact-request
|
||||
:label (i18n/label :t/contact-requests)}
|
||||
{:id constants/activity-center-notification-type-identity-verification
|
||||
{:id constants/activity-center-notification-type-contact-verification
|
||||
:label (i18n/label :t/identity-verification)}
|
||||
{:id constants/activity-center-notification-type-tx
|
||||
:label (i18n/label :t/transactions)}
|
||||
|
@ -1819,6 +1819,8 @@
|
||||
"admin": "Admin",
|
||||
"replies": "Replies",
|
||||
"identity-verification": "Identity verification",
|
||||
"identity-verification-request": "Identity verification request",
|
||||
"identity-verification-request-sent": "asked you",
|
||||
"membership": "Membership",
|
||||
"jump-to": "Jump to",
|
||||
"blank-messages-text": "Your messages will be here",
|
||||
|
Loading…
x
Reference in New Issue
Block a user