diff --git a/src/status_im/activity_center/core.cljs b/src/status_im/activity_center/core.cljs index 53b61d46b9..9878e17858 100644 --- a/src/status_im/activity_center/core.cljs +++ b/src/status_im/activity_center/core.cljs @@ -6,6 +6,14 @@ [status-im.utils.fx :as fx] [taoensso.timbre :as log])) +(def defaults + {:filter-status :unread + :filter-type types/no-type + ;; Choose the maximum number of notifications that *usually/safely* fit on + ;; most screens, so that the UI doesn't have to needlessly render + ;; notifications. + :notifications-per-page 8}) + ;;;; Navigation (fx/defn open-activity-center @@ -75,6 +83,35 @@ (map data-store.activities/<-rpc) (notifications-reconcile cofx))) +;;;; Mark notifications as read + +(defn- get-notification + [db notification-id] + (->> (get-in db [:activity-center + :notifications + (get-in db [:activity-center :filter :type]) + (get-in db [:activity-center :filter :status]) + :data]) + (filter #(= notification-id (:id %))) + first)) + +(fx/defn mark-as-read + {:events [:activity-center.notifications/mark-as-read]} + [{:keys [db]} notification-id] + (when-let [notification (get-notification db notification-id)] + {::json-rpc/call [{:method "wakuext_markActivityCenterNotificationsRead" + :params [[notification-id]] + :on-success #(rf/dispatch [:activity-center.notifications/mark-as-read-success notification]) + :on-error #(rf/dispatch [:activity-center/process-notification-failure + notification-id + :notification/mark-as-read + %])}]})) + +(fx/defn mark-as-read-success + {:events [:activity-center.notifications/mark-as-read-success]} + [cofx notification] + (notifications-reconcile cofx [(assoc notification :read true)])) + ;;;; Contact verification (fx/defn contact-verification-decline @@ -123,14 +160,6 @@ ;;;; Notifications fetching and pagination -(def defaults - {:filter-status :unread - :filter-type types/no-type - ;; Choose the maximum number of notifications that *usually/safely* fit on - ;; most screens, so that the UI doesn't have to needlessly render - ;; notifications. - :notifications-per-page 8}) - (def start-or-end-cursor "") diff --git a/src/status_im/activity_center/core_test.cljs b/src/status_im/activity_center/core_test.cljs index 79afa55d49..73d451fed2 100644 --- a/src/status_im/activity_center/core_test.cljs +++ b/src/status_im/activity_center/core_test.cljs @@ -9,13 +9,105 @@ [status-im.test-helpers :as h] [status-im2.setup.config :as config])) +(def notification-id "0x1") + (defn setup [] (h/register-helper-events) (rf/dispatch [:setup/app-started])) -;;;; Contact verification +(defn test-log-on-failure + [{:keys [before-test notification-id event action]}] + (rf-test/run-test-sync + (setup) + (h/using-log-test-appender + (fn [logs] + (when before-test + (before-test)) + (h/stub-fx-with-callbacks ::json-rpc/call :on-error (constantly :fake-error)) -(def notification-id 24) + (rf/dispatch event) + + (is (= {:args [(str "Failed to " action) + {:notification-id notification-id + :error :fake-error}] + :level :warn} + (last @logs))))))) + +;;;; Misc + +(deftest mark-as-read-test + (testing "does nothing if the notification ID cannot be found in the app db" + (rf-test/run-test-sync + (setup) + (let [spy-queue (atom [])] + (h/spy-fx spy-queue ::json-rpc/call) + (let [notifications {types/one-to-one-chat + {:all {:cursor "" :data [{:id notification-id + :read false + :type types/one-to-one-chat}]} + :unread {:cursor "" :data []}}}] + (rf/dispatch [:test/assoc-in [:activity-center] + {:notifications notifications + :filter {:type types/one-to-one-chat + :status :all}}]) + + (rf/dispatch [:activity-center.notifications/mark-as-read "0x666"]) + + (is (= [] @spy-queue)) + (is (= notifications (get-in (h/db) [:activity-center :notifications]))))))) + + (testing "marks notifications as read and updates app db" + (rf-test/run-test-sync + (setup) + (let [notif-1 {:id "0x1" :read true :type types/one-to-one-chat} + notif-2 {:id "0x2" :read false :type types/one-to-one-chat} + notif-3 {:id "0x3" :read false :type types/one-to-one-chat} + new-notif-3 (assoc notif-3 :read true) + new-notif-2 (assoc notif-2 :read true)] + (h/stub-fx-with-callbacks ::json-rpc/call :on-success (constantly nil)) + (rf/dispatch [:test/assoc-in [:activity-center] + {:notifications {types/one-to-one-chat + {:all {:cursor "" :data [notif-3 notif-2 notif-1]} + :unread {:cursor "" :data [notif-3 notif-2]}}} + :filter {:type types/one-to-one-chat + :status :unread}}]) + + (rf/dispatch [:activity-center.notifications/mark-as-read (:id notif-2)]) + (is (= {types/one-to-one-chat + {:all {:cursor "" :data [notif-3 new-notif-2 notif-1]} + :unread {:cursor "" :data [notif-3]}} + + types/no-type + {:all {:data [new-notif-2]} + :unread {:data []}}} + (get-in (h/db) [:activity-center :notifications]))) + + (rf/dispatch [:activity-center.notifications/mark-as-read (:id notif-3)]) + (is (= {types/one-to-one-chat + {:all {:cursor "" :data [new-notif-3 new-notif-2 notif-1]} + :unread {:cursor "" :data []}} + + types/no-type + {:all {:data [new-notif-3 new-notif-2]} + :unread {:data []}}} + (get-in (h/db) [:activity-center :notifications])))))) + + (testing "logs on failure" + (test-log-on-failure + {:notification-id notification-id + :event [:activity-center.notifications/mark-as-read notification-id] + :action :notification/mark-as-read + :before-test (fn [] + (rf/dispatch [:test/assoc-in [:activity-center] + {:notifications {types/one-to-one-chat + {:all {:cursor "" :data [{:id notification-id + :read false + :type types/one-to-one-chat}]} + :unread {:cursor "" :data []}}} + :filter {:type types/one-to-one-chat + :status :all}}]))}))) + +;;;; Contact verification (def contact-verification-rpc-response {:activityCenterNotifications @@ -59,22 +151,6 @@ :timestamp 1666647286000 :type types/contact-verification}) -(defn test-log-on-failure - [{:keys [notification-id event action]}] - (rf-test/run-test-sync - (setup) - (h/using-log-test-appender - (fn [logs] - (h/stub-fx-with-callbacks ::json-rpc/call :on-error (constantly :fake-error)) - - (rf/dispatch event) - - (is (= {:args [(str "Failed to " action) - {:notification-id notification-id - :error :fake-error}] - :level :warn} - (last @logs))))))) - (defn test-contact-verification-event [{:keys [event expected-rpc-call]}] (rf-test/run-test-sync diff --git a/src/status_im/ui/screens/activity_center/notification/contact_request/view.cljs b/src/status_im/ui/screens/activity_center/notification/contact_request/view.cljs index 9ef81f601d..d153335625 100644 --- a/src/status_im/ui/screens/activity_center/notification/contact_request/view.cljs +++ b/src/status_im/ui/screens/activity_center/notification/contact_request/view.cljs @@ -51,9 +51,13 @@ {:button-1 {:label (i18n/label :t/decline) :accessibility-label :decline-contact-request :type :danger - :on-press #(rf/dispatch [:contact-requests.ui/decline-request id])} + :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 #(rf/dispatch [:contact-requests.ui/accept-request id])}} + :on-press (fn [] + (rf/dispatch [:contact-requests.ui/accept-request id]) + (rf/dispatch [:activity-center.notifications/mark-as-read id]))}} nil))]))) diff --git a/src/status_im/ui/screens/activity_center/notification/contact_verification/view.cljs b/src/status_im/ui/screens/activity_center/notification/contact_verification/view.cljs index 0fde48f817..38df5a9e5d 100644 --- a/src/status_im/ui/screens/activity_center/notification/contact_verification/view.cljs +++ b/src/status_im/ui/screens/activity_center/notification/contact_verification/view.cljs @@ -85,21 +85,29 @@ {:button-1 {:label (i18n/label :t/untrustworthy) :accessibility-label :mark-contact-verification-as-untrustworthy :type :danger - :on-press #(rf/dispatch [:activity-center.contact-verification/mark-as-untrustworthy id])} + :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 #(rf/dispatch [:activity-center.contact-verification/mark-as-trusted id])}}) + :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 #(hide-bottom-sheet-and-dispatch [:activity-center.contact-verification/decline id])} + :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 #(hide-bottom-sheet-and-dispatch [:activity-center.contact-verification/reply id @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]))} {:label (i18n/label :t/message-reply) :accessibility-label :send-reply-to-contact-verification :type :primary diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 9a8f77cde1..01db525adc 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -256,11 +256,11 @@ :width 32 :style {:margin-left 12} :accessibility-label :notifications-button - :on-press #(do - (re-frame/dispatch [:mark-all-activity-center-notifications-as-read]) - (if config/new-activity-center-enabled? - (re-frame/dispatch [:activity-center/open]) - (re-frame/dispatch [:navigate-to :notifications-center])))} + :on-press #(do (if config/new-activity-center-enabled? + (re-frame/dispatch [:activity-center/open]) + (do + (re-frame/dispatch [:mark-all-activity-center-notifications-as-read]) + (re-frame/dispatch [:navigate-to :notifications-center]))))} [icons/icon :main-icons/notification2 {:color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)}]] (when (pos? notif-count) [react/view {:style (merge (styles/counter-public-container) {:top 5 :right 5}) diff --git a/src/status_im2/common/home/view.cljs b/src/status_im2/common/home/view.cljs index 8a7deaed9b..a203c3e9a1 100644 --- a/src/status_im2/common/home/view.cljs +++ b/src/status_im2/common/home/view.cljs @@ -9,10 +9,10 @@ [utils.re-frame :as rf])) (defn navigate-to-activity-center [] - (rf/dispatch [:mark-all-activity-center-notifications-as-read]) (if config/new-activity-center-enabled? (rf/dispatch [:activity-center/open]) - (rf/dispatch [:navigate-to :notifications-center]))) + (do (rf/dispatch [:mark-all-activity-center-notifications-as-read]) + (rf/dispatch [:navigate-to :notifications-center])))) (defn title-column [{:keys [label handler accessibility-label]}] [rn/view style/title-column diff --git a/src/status_im2/contexts/chat/home/contact_request/view.cljs b/src/status_im2/contexts/chat/home/contact_request/view.cljs index 33d4513458..8463421342 100644 --- a/src/status_im2/contexts/chat/home/contact_request/view.cljs +++ b/src/status_im2/contexts/chat/home/contact_request/view.cljs @@ -1,5 +1,6 @@ (ns status-im2.contexts.chat.home.contact-request.view (:require [react-native.core :as rn] + [status-im2.setup.config :as config] [quo2.core :as quo] [i18n.i18n :as i18n] [utils.re-frame :as rf] @@ -58,7 +59,8 @@ :on-press #(do (rf/dispatch [:bottom-sheet/show-sheet {:content (fn [] [contact-requests-sheet requests])}]) - (rf/dispatch [:mark-all-activity-center-notifications-as-read])) + (when-not config/new-activity-center-enabled? + (rf/dispatch [:mark-all-activity-center-notifications-as-read]))) :style style/contact-requests} [rn/view {:style (style/contact-requests-icon)} [quo/icon :i/pending-user {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]