Introduce marking all notifications as read in Activity Center (#14952)

* [Feature][#14902][#14917] Added marking all notifications as read

* [Fix] Lint Fix
This commit is contained in:
Mohamed Javid 2023-02-20 23:54:17 +05:30 committed by GitHub
parent 3fbb7cb0a7
commit 8ed64f810f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 185 additions and 58 deletions

View File

@ -6,10 +6,10 @@
[quo2.components.drawers.action-drawers.style :as style]))
(defn- get-icon-color
[danger?]
[danger? override-theme]
(if danger?
colors/danger-50
(colors/theme-colors colors/neutral-50 colors/neutral-40)))
(colors/theme-colors colors/neutral-50 colors/neutral-40 override-theme)))
(def divider
[rn/view
@ -25,6 +25,7 @@
danger?
on-press
add-divider?
override-theme
accessibility-label]
:as action-props}]
(when action-props
@ -33,7 +34,7 @@
[rn/touchable-highlight
{:accessibility-label accessibility-label
:style (style/container sub-label)
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90)
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90 override-theme)
:on-press on-press}
[rn/view
{:style (style/row-container sub-label)}
@ -42,7 +43,7 @@
:accessible true
:style style/left-icon}
[icon/icon icon
{:color (get-icon-color danger?)
{:color (get-icon-color danger? override-theme)
:size 20}]]
[rn/view
{:style style/text-container}
@ -50,14 +51,15 @@
{:size :paragraph-1
:weight :medium
:style {:color
(when danger?
(colors/theme-colors colors/danger-50 colors/danger-60))}}
(cond
danger? (colors/theme-colors colors/danger-50 colors/danger-60 override-theme)
:else (colors/theme-colors colors/neutral-100 colors/white override-theme))}}
label]
(when sub-label
[text/text
{:size :paragraph-2
:style {:color
(colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(colors/theme-colors colors/neutral-50 colors/neutral-40 override-theme)}}
sub-label])]
(when right-icon
[rn/view
@ -65,7 +67,7 @@
:accessible true
:accessibility-label :right-icon-for-action}
[icon/icon right-icon
{:color (get-icon-color danger?)
{:color (get-icon-color danger? override-theme)
:size 20}]])]]]))
(defn action-drawer

View File

@ -18,8 +18,8 @@
:light {:background-color :colors/white-opa-5}}})
(defn- merge-theme-style
[component-key styles]
(merge (get-in themes [component-key (theme/get-theme)]) styles))
[component-key styles override-theme]
(merge (get-in themes [component-key (or override-theme (theme/get-theme))]) styles))
(defn toast-action-container
[{:keys [on-press style]} & children]
@ -41,17 +41,17 @@
children]])
(defn toast-undo-action
[duration on-press]
[duration on-press override-theme]
[toast-action-container
{:on-press on-press :accessibility-label :toast-undo-action}
[rn/view {:style {:margin-right 5}}
[count-down-circle/circle-timer {:duration duration}]]
[text/text
{:size :paragraph-2 :weight :medium :style (merge-theme-style :text {})}
{:size :paragraph-2 :weight :medium :style (merge-theme-style :text {} override-theme)}
[i18n/label :t/undo]]])
(defn- toast-container
[{:keys [left middle right container-style]}]
[{:keys [left middle right container-style override-theme]}]
[rn/view {:style (merge {:padding-left 12 :padding-right 12} container-style)}
[rn/view
{:style (merge-theme-style :container
@ -62,27 +62,31 @@
:padding-vertical 8
:padding-left 10
:padding-right 8
:border-radius 12})}
:border-radius 12}
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 {})
:style (merge-theme-style :text {} override-theme)
:accessibility-label :toast-content}
middle]]
(when right right)]])
(defn toast
[{:keys [icon icon-color text action undo-duration undo-on-press container-style]}]
[{:keys [icon icon-color text action undo-duration undo-on-press container-style override-theme]}]
[toast-container
{:left (when icon
[icon/icon icon
{:container-style {:width 20 :height 20}
:color (or icon-color
(get-in themes [:icon (theme/get-theme) :color]))}])
(get-in themes
[:icon (or override-theme (theme/get-theme))
:color]))}])
:middle text
:right (if undo-duration
[toast-undo-action undo-duration undo-on-press]
[toast-undo-action undo-duration undo-on-press override-theme]
action)
:container-style container-style}])
:container-style container-style
:override-theme override-theme}])

View File

@ -4,6 +4,10 @@
[status-im.data-store.messages :as messages]
[status-im2.contexts.activity-center.notification-types :as notification-types]))
(defn mark-notifications-as-read
[notifications]
(map #(assoc % :read true) notifications))
(defn- rpc->type
[{:keys [type name] :as chat}]
(case type

View File

@ -4,12 +4,12 @@
(def border-radius 20)
(defn handle
[]
[override-theme]
{:position :absolute
:top 8
:width 32
:height 4
:background-color (colors/theme-colors colors/neutral-100 colors/white)
:background-color (colors/theme-colors colors/neutral-100 colors/white override-theme)
:opacity 0.1
:border-radius 100
:align-self :center})
@ -40,17 +40,17 @@
:padding-bottom (if bottom-safe-area-spacing? (:bottom insets) 0)})
(defn selected-background
[]
[override-theme]
{:border-radius 12
:padding-left 12
:margin-horizontal 8
:margin-bottom 10
:height 48
:background-color (colors/theme-colors colors/white colors/neutral-90)})
:background-color (colors/theme-colors colors/white colors/neutral-90 override-theme)})
(defn background
[]
{:background-color (colors/theme-colors colors/white colors/neutral-95)
[override-theme]
{:background-color (colors/theme-colors colors/white colors/neutral-95 override-theme)
:flex 1
:border-top-left-radius border-radius
:border-top-right-radius border-radius})

View File

@ -70,14 +70,14 @@
(reset! expanded? false))))))))
(defn handle-comp
[window-width]
[window-width override-theme]
[rn/view
{:style {:width window-width
:position :absolute
:background-color :transparent
:top 0
:height 20}}
[rn/view {:style (styles/handle)}]])
[rn/view {:style (styles/handle override-theme)}]])
(defn bottom-sheet
[props children]
@ -90,6 +90,7 @@
bottom-safe-area-spacing? :bottom-safe-area-spacing?
selected-item :selected-item
is-initially-expanded? :expanded?
override-theme :override-theme
:or {show-handle? true
backdrop-dismiss? true
expandable? false
@ -125,7 +126,7 @@
window-height (if selected-item (- height 72) height)
{:keys [keyboard-shown]} (hooks/use-keyboard)
bg-height-expanded (- window-height (:top insets))
bg-height (max (min @content-height bg-height-expanded) 200)
bg-height (max (min @content-height bg-height-expanded) 109)
bottom-sheet-dy (reanimated/use-shared-value 0)
pan-y (reanimated/use-shared-value 0)
translate-y (.useTranslateY ^js bottom-sheet-js window-height bottom-sheet-dy pan-y)
@ -154,7 +155,7 @@
close-bottom-sheet
gesture-running?)
handle-comp [gesture/gesture-detector {:gesture bottom-sheet-gesture}
[handle-comp window-width]]]
[handle-comp window-width override-theme]]]
(react/effect! #(do
(cond
@ -221,9 +222,9 @@
:height window-height})}
[rn/view {:style styles/container}
(when selected-item
[rn/view {:style (styles/selected-background)}
[rn/view {:style (styles/selected-background override-theme)}
[selected-item]])
[rn/view {:style (styles/background)}
[rn/view {:style (styles/background override-theme)}
[rn/keyboard-avoiding-view
{:behaviour (if platform/ios? :padding :height)
:style {:flex 1}}

View File

@ -36,6 +36,8 @@
(def ^:const activity-center-membership-status-accepted 2)
(def ^:const activity-center-membership-status-declined 3)
(def ^:const activity-center-mark-all-as-read-undo-time-limit-ms 4000)
(def ^:const emoji-reaction-love 1)
(def ^:const emoji-reaction-thumbs-up 2)
(def ^:const emoji-reaction-thumbs-down 3)

View File

@ -4,7 +4,8 @@
[status-im2.contexts.activity-center.notification-types :as types]
[status-im2.contexts.chat.events :as chat.events]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[status-im2.constants :as constants]))
(def defaults
{:filter-status :unread
@ -153,6 +154,66 @@
[cofx notification]
(notifications-reconcile cofx [(assoc notification :read true)]))
(rf/defn mark-all-as-read
{:events [:activity-center.notifications/mark-all-as-read]}
[{:keys [db now]}]
(when-let [undoable-till (get-in db [:activity-center :mark-all-as-read-undoable-till])]
(when (>= now undoable-till)
{:json-rpc/call [{:method "wakuext_markAllActivityCenterNotificationsRead"
:params []
:on-success #(rf/dispatch
[:activity-center.notifications/mark-all-as-read-success])
:on-error #(rf/dispatch [:activity-center/process-notification-failure
nil
:notification/mark-all-as-read
%])}]})))
(rf/defn mark-all-as-read-success
{:events [:activity-center.notifications/mark-all-as-read-success]}
[{:keys [db]}]
{:db (-> (reduce (fn [acc notification-type]
(assoc-in acc [:activity-center :unread-counts-by-type notification-type] 0))
db
types/all-supported)
(update :activity-center dissoc :mark-all-as-read-undoable-till))})
(rf/defn undo-mark-all-as-read
{:events [:activity-center.notifications/undo-mark-all-as-read-locally]}
[{:keys [db]} {:keys [notifications]}]
{:db (-> db
(update-in [:activity-center :notifications]
update-notifications
notifications)
(update :activity-center dissoc :mark-all-as-read-undoable-till))})
(rf/defn mark-all-as-read-locally
{:events [:activity-center.notifications/mark-all-as-read-locally]}
[{:keys [db now]} get-toast-ui-props]
(let [unread-notifications (get-in db [:activity-center :notifications types/no-type :unread :data])
undo-time-limit-ms constants/activity-center-mark-all-as-read-undo-time-limit-ms
undoable-till (+ now undo-time-limit-ms)]
{:db (-> db
(update-in [:activity-center :notifications]
update-notifications
(data-store.activities/mark-notifications-as-read
unread-notifications))
(assoc-in [:activity-center :mark-all-as-read-undoable-till]
undoable-till))
:dispatch [:toasts/upsert
(merge
{:id :activity-center-mark-all-as-read
:duration undo-time-limit-ms
:undo-duration (/ undo-time-limit-ms 1000)
:undo-on-press
(fn []
(rf/dispatch
[:activity-center.notifications/undo-mark-all-as-read-locally
{:notifications unread-notifications}])
(rf/dispatch [:toasts/close :activity-center-mark-all-as-read]))}
(get-toast-ui-props))]
:utils/dispatch-later [{:dispatch [:activity-center.notifications/mark-all-as-read]
:ms undo-time-limit-ms}]}))
;;;; Acceptance/dismissal
(rf/defn accept-notification

View File

@ -3,9 +3,11 @@
(def screen-padding 20)
(def header-button
{:margin-bottom 12
:margin-left screen-padding})
(def header-container
{:flex-direction :row
:justify-content :space-between
:padding-horizontal screen-padding
:margin-bottom 12})
(def header-heading
{:padding-horizontal screen-padding

View File

@ -1,7 +1,7 @@
(ns status-im2.contexts.activity-center.view
(:require [utils.i18n :as i18n]
[quo.react :as react]
(:require [quo.react :as react]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im2.contexts.activity-center.notification-types :as types]
@ -13,6 +13,7 @@
[status-im2.contexts.activity-center.notification.mentions.view :as mentions]
[status-im2.contexts.activity-center.notification.reply.view :as reply]
[status-im2.contexts.activity-center.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn filter-selector-read-toggle
@ -27,6 +28,28 @@
:all
:unread)}])}]))
(defn options-bottom-sheet-content
[]
(let [unread-count (rf/sub [:activity-center/unread-count])]
[quo/action-drawer
[[{:icon :i/check
:override-theme :dark
:label (i18n/label :t/mark-all-notifications-as-read)
:on-press (fn []
(if (pos? unread-count)
(rf/dispatch [:activity-center.notifications/mark-all-as-read-locally
(fn []
{:icon :up-to-date
:icon-color colors/success-50
:text (i18n/label :t/notifications-marked-as-read
{:count unread-count})
:override-theme :dark})])
;; Need design improvements if there is NO unread
;; notifications to mark as read
;; https://github.com/status-im/status-mobile/issues/14983
(js/alert "No unread notifications to mark as read"))
(rf/dispatch [:bottom-sheet/hide]))}]]]))
(defn empty-tab
[]
(let [filter-status (rf/sub [:activity-center/filter-status])]
@ -50,8 +73,10 @@
(defn tabs
[]
(let [filter-type (rf/sub [:activity-center/filter-type])
types-with-unread (rf/sub [:activity-center/notification-types-with-unread])]
(let [filter-type (rf/sub [:activity-center/filter-type])
types-with-unread (rf/sub [:activity-center/notification-types-with-unread])
is-mark-all-as-read-undoable? (boolean (rf/sub
[:activity-center/mark-all-as-read-undoable-till]))]
[quo/tabs
{:size 32
:scrollable? true
@ -69,49 +94,67 @@
{:id types/admin
:label (i18n/label :t/admin)
:accessibility-label :tab-admin
:notification-dot? (contains? types-with-unread types/admin)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/admin))}
{:id types/mention
:label (i18n/label :t/mentions)
:accessibility-label :tab-mention
:notification-dot? (contains? types-with-unread types/mention)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/mention))}
{:id types/reply
:label (i18n/label :t/replies)
:accessibility-label :tab-reply
:notification-dot? (contains? types-with-unread types/reply)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/reply))}
{:id types/contact-request
:label (i18n/label :t/contact-requests)
:accessibility-label :tab-contact-request
:notification-dot? (contains? types-with-unread types/contact-request)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/contact-request))}
{:id types/contact-verification
:label (i18n/label :t/identity-verification)
:accessibility-label :tab-contact-verification
:notification-dot? (contains? types-with-unread
types/contact-verification)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread
types/contact-verification))}
{:id types/tx
:label (i18n/label :t/transactions)
:accessibility-label :tab-tx
:notification-dot? (contains? types-with-unread types/tx)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/tx))}
{:id types/membership
:label (i18n/label :t/membership)
:accessibility-label :tab-membership
:notification-dot? (contains? types-with-unread types/membership)}
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/membership))}
{:id types/system
:label (i18n/label :t/system)
:accessibility-label :tab-system
:notification-dot? (contains? types-with-unread types/system)}]}]))
:notification-dot? (when-not is-mark-all-as-read-undoable?
(contains? types-with-unread types/system))}]}]))
(defn header
[]
[rn/view
[quo/button
{:icon true
:type :blur-bg
:size 32
:accessibility-label :close-activity-center
:override-theme :dark
:style style/header-button
:on-press #(rf/dispatch [:hide-popover])}
:i/close]
[rn/view {:style style/header-container}
[quo/button
{:icon true
:type :blur-bg
:size 32
:accessibility-label :close-activity-center
:override-theme :dark
:on-press #(rf/dispatch [:hide-popover])}
:i/close]
[quo/button
{:icon true
:type :blur-bg
:size 32
:accessibility-label :activity-center-open-more
:override-theme :dark
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content options-bottom-sheet-content
:override-theme :dark}])}
:i/options]]
[quo/text
{:size :heading-1
:weight :semi-bold

View File

@ -34,6 +34,12 @@
vals
(reduce + 0))))
(re-frame/reg-sub
:activity-center/mark-all-as-read-undoable-till
:<- [:activity-center]
(fn [activity-center]
(:mark-all-as-read-undoable-till activity-center)))
(re-frame/reg-sub
:activity-center/filter-status
:<- [:activity-center]

View File

@ -1960,5 +1960,7 @@
"my-albums": "My albums",
"images": "images",
"only-6-images": "You can only add 6 images to your message",
"delivered": "Delivered"
"delivered": "Delivered",
"mark-all-notifications-as-read": "Mark all notifications as read",
"notifications-marked-as-read": "{{count}} notifications marked as read"
}