chore(activity-center): Various small refactors (#20690)
Potentially a solution to https://github.com/status-im/status-mobile/issues/15706 - [x] Fixes swipe button on Android and iOS. - [x] Performance: we now subscribe only to the minimum from each community. This could be the reason the AC would lag as described in the parent issue. - [x] Performance: was able to use flex and removed swipe button height calculation that was using `onLayout` and was causing a re-render. - [x] Performance: reduced the initial number of items to render in the flatlist from 10 to 7. - [x] Performance: delay rendering the heavy list of notification components. See in the video below how slow it is to open the AC with just 6 notifications and that the opening animation is never displayed. And then check the improved version with the artificial delay provided by `rn/delay-render`. By opening the AC first and animating, this gives the user something to look for, and hopefully a few milliseconds more to think the app is not stuck, which will be preciously used to render notifications. We refactor all views in the AC to: - [x] Follow our newest standards with React hooks. - [x] Removed prop-drilling by creating a separate React context to store the current swipeable item (because we need to call `.close` on a `Gesture Swipeable` instance whenever a new swipeable opens.
This commit is contained in:
parent
7b09402fcb
commit
b3e88508ac
|
@ -45,6 +45,11 @@
|
||||||
(def ^:const activity-center-membership-status-accepted 2)
|
(def ^:const activity-center-membership-status-accepted 2)
|
||||||
(def ^:const activity-center-membership-status-declined 3)
|
(def ^:const activity-center-membership-status-declined 3)
|
||||||
|
|
||||||
|
;; Choose the maximum number of notifications that *usually/safely* fit on
|
||||||
|
;; most screens, so that the UI doesn't have to needlessly render
|
||||||
|
;; notifications.
|
||||||
|
(def ^:const notifications-per-page 7)
|
||||||
|
|
||||||
(def ^:const mute-for-15-mins-type 1)
|
(def ^:const mute-for-15-mins-type 1)
|
||||||
(def ^:const mute-for-1-hour-type 2)
|
(def ^:const mute-for-1-hour-type 2)
|
||||||
(def ^:const mute-for-8-hours-type 3)
|
(def ^:const mute-for-8-hours-type 3)
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
(ns status-im.contexts.shell.activity-center.context
|
||||||
|
(:require
|
||||||
|
["react" :as react]
|
||||||
|
[oops.core :as oops]
|
||||||
|
[react-native.core :as rn]))
|
||||||
|
|
||||||
|
(defonce ^:private context
|
||||||
|
(react/createContext {}))
|
||||||
|
|
||||||
|
(defn provider
|
||||||
|
[state & children]
|
||||||
|
(into [:> (oops/oget context :Provider) {:value state}]
|
||||||
|
children))
|
||||||
|
|
||||||
|
(defn use-context
|
||||||
|
[]
|
||||||
|
(let [ctx (rn/use-context context)]
|
||||||
|
{:active-swipeable (oops/oget ctx :activeSwipeable)}))
|
|
@ -15,10 +15,7 @@
|
||||||
(def defaults
|
(def defaults
|
||||||
{:filter-status :unread
|
{:filter-status :unread
|
||||||
:filter-type types/no-type
|
:filter-type types/no-type
|
||||||
;; Choose the maximum number of notifications that *usually/safely* fit on
|
:notifications-per-page constants/notifications-per-page})
|
||||||
;; most screens, so that the UI doesn't have to needlessly render
|
|
||||||
;; notifications.
|
|
||||||
:notifications-per-page 8})
|
|
||||||
|
|
||||||
;;;; Navigation
|
;;;; Navigation
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.admin.view
|
(ns status-im.contexts.shell.activity-center.notification.admin.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
||||||
|
@ -23,42 +24,50 @@
|
||||||
:text (i18n/label :t/decline)}])
|
:text (i18n/label :t/decline)}])
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable notification extra-fn]} child]
|
[{:keys [notification extra-fn]} child]
|
||||||
(let [{:keys [community-id id membership-status]} notification]
|
(let [{:keys [community-id id
|
||||||
|
membership-status]} notification
|
||||||
|
accept (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:communities/accept-request-to-join-pressed
|
||||||
|
community-id id]))
|
||||||
|
[community-id id])
|
||||||
|
decline (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:communities/decline-request-to-join-pressed
|
||||||
|
community-id id]))
|
||||||
|
[community-id id])]
|
||||||
(cond
|
(cond
|
||||||
(#{constants/activity-center-membership-status-accepted
|
(#{constants/activity-center-membership-status-accepted
|
||||||
constants/activity-center-membership-status-declined}
|
constants/activity-center-membership-status-declined}
|
||||||
membership-status)
|
membership-status)
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
(= membership-status constants/activity-center-membership-status-pending)
|
(= membership-status constants/activity-center-membership-status-pending)
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button swipe-button-accept
|
{:left-button swipe-button-accept
|
||||||
:left-on-press #(rf/dispatch [:communities/accept-request-to-join-pressed community-id id])
|
:left-on-press accept
|
||||||
:right-button swipe-button-decline
|
:right-button swipe-button-decline
|
||||||
:right-on-press #(rf/dispatch [:communities/decline-request-to-join-pressed community-id
|
:right-on-press decline
|
||||||
id])
|
:extra-fn extra-fn}
|
||||||
:active-swipeable active-swipeable
|
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
child)))
|
child)))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification] :as props}]
|
||||||
(let [{:keys [author community-id id membership-status
|
(let [{:keys [author community-id id membership-status
|
||||||
read timestamp]} notification
|
read timestamp]} notification
|
||||||
community (rf/sub [:communities/community community-id])
|
community-name (rf/sub [:communities/name community-id])
|
||||||
community-name (:name community)
|
community-logo (rf/sub [:communities/logo community-id])
|
||||||
community-image (get-in community [:images :thumbnail :uri])]
|
customization-color (rf/sub [:profile/customization-color])]
|
||||||
[swipeable props
|
[swipeable props
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/join-request)
|
{:title (i18n/label :t/join-request)
|
||||||
|
@ -66,14 +75,13 @@
|
||||||
:icon :i/add-user
|
:icon :i/add-user
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:context [[common/user-avatar-tag author]
|
:context [[common/user-avatar-tag author]
|
||||||
(i18n/label :t/wants-to-join)
|
(i18n/label :t/wants-to-join)
|
||||||
[quo/context-tag
|
[quo/context-tag
|
||||||
{:type :community
|
{:type :community
|
||||||
:size 24
|
:size 24
|
||||||
:blur? true
|
:blur? true
|
||||||
:community-logo community-image
|
:community-logo community-logo
|
||||||
:community-name community-name}]]
|
:community-name community-name}]]
|
||||||
:items (condp = membership-status
|
:items (condp = membership-status
|
||||||
constants/activity-center-membership-status-accepted
|
constants/activity-center-membership-status-accepted
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
(def swipe-action-width 80)
|
(def swipe-action-width 80)
|
||||||
(def swipe-button-border-radius 16)
|
(def swipe-button-border-radius 16)
|
||||||
|
(def swipe-button-margin 8)
|
||||||
|
|
||||||
(def user-avatar-tag
|
(def user-avatar-tag
|
||||||
{:background-color colors/white-opa-10})
|
{:background-color colors/white-opa-10})
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.common.view
|
(ns status-im.contexts.shell.activity-center.notification.common.view
|
||||||
(:require
|
(:require
|
||||||
|
[oops.core :as oops]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.gesture :as gesture]
|
[react-native.gesture :as gesture]
|
||||||
[status-im.contexts.profile.utils :as profile.utils]
|
[status-im.contexts.profile.utils :as profile.utils]
|
||||||
|
[status-im.contexts.shell.activity-center.context :as ac.context]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as style]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -14,7 +16,7 @@
|
||||||
(let [profile (rf/sub [:contacts/contact-by-identity user-id])]
|
(let [profile (rf/sub [:contacts/contact-by-identity user-id])]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:on-start-should-set-responder
|
{:on-start-should-set-responder
|
||||||
(fn [_event]
|
(fn []
|
||||||
(rf/dispatch [:navigate-back])
|
(rf/dispatch [:navigate-back])
|
||||||
(rf/dispatch [:chat.ui/show-profile user-id])
|
(rf/dispatch [:chat.ui/show-profile user-id])
|
||||||
true)}
|
true)}
|
||||||
|
@ -33,35 +35,27 @@
|
||||||
swipe-button
|
swipe-button
|
||||||
swipeable-ref
|
swipeable-ref
|
||||||
style]}]
|
style]}]
|
||||||
(fn [_ ^js drag-x]
|
(fn [_ drag-x]
|
||||||
(let [{:keys [height] :as extra} (extra-fn)
|
(let [extra (extra-fn)
|
||||||
opacity (.interpolate drag-x interpolation-opacity)
|
opacity (oops/ocall drag-x :interpolate interpolation-opacity)
|
||||||
translate-x (.interpolate drag-x interpolation-translate-x)]
|
translate-x (oops/ocall drag-x :interpolate interpolation-translate-x)]
|
||||||
[gesture/rect-button
|
[gesture/rect-button
|
||||||
{:style (merge {:border-radius style/swipe-button-border-radius} style)
|
{:style (merge {:border-radius style/swipe-button-border-radius} style)
|
||||||
:accessibility-label :notification-swipe-action-button
|
:accessibility-label :notification-swipe-action-button
|
||||||
:on-press (fn []
|
:on-press (fn []
|
||||||
(when @swipeable-ref
|
(when @swipeable-ref
|
||||||
(.close ^js @swipeable-ref)
|
(oops/ocall @swipeable-ref :close)
|
||||||
(reset! active-swipeable nil))
|
(reset! active-swipeable nil))
|
||||||
(on-press extra))}
|
(on-press extra))}
|
||||||
[swipe-button
|
[swipe-button
|
||||||
{:style {:opacity opacity
|
{:style {:opacity opacity
|
||||||
:transform [{:translateX translate-x}]
|
:transform [{:translateX translate-x}]
|
||||||
:height height
|
:flex 1
|
||||||
:width style/swipe-action-width}}
|
:width style/swipe-action-width}}
|
||||||
extra]])))
|
extra]])))
|
||||||
|
|
||||||
(defn- close-active-swipeable
|
|
||||||
[active-swipeable swipeable]
|
|
||||||
(fn [_]
|
|
||||||
(when (and @active-swipeable
|
|
||||||
(not= @active-swipeable @swipeable))
|
|
||||||
(.close ^js @active-swipeable))
|
|
||||||
(reset! active-swipeable @swipeable)))
|
|
||||||
|
|
||||||
(defn swipe-button-container
|
(defn swipe-button-container
|
||||||
[{:keys [style icon text]} _]
|
[{:keys [style icon text]}]
|
||||||
[rn/animated-view
|
[rn/animated-view
|
||||||
{:accessibility-label :notification-swipe
|
{:accessibility-label :notification-swipe
|
||||||
:style style}
|
:style style}
|
||||||
|
@ -103,47 +97,54 @@
|
||||||
(rf/dispatch [:activity-center.notifications/delete (:id notification)]))
|
(rf/dispatch [:activity-center.notifications/delete (:id notification)]))
|
||||||
|
|
||||||
(defn swipeable
|
(defn swipeable
|
||||||
[_]
|
[{:keys [extra-fn
|
||||||
(let [swipeable-ref (atom nil)]
|
left-button
|
||||||
(fn [{:keys [active-swipeable
|
left-on-press
|
||||||
extra-fn
|
right-button
|
||||||
left-button
|
right-on-press]}
|
||||||
left-on-press
|
child]
|
||||||
right-button
|
(let [{:keys [active-swipeable]} (ac.context/use-context)
|
||||||
right-on-press]}
|
this-swipeable (rn/use-ref-atom nil)
|
||||||
& children]
|
set-this-swipeable (rn/use-callback #(reset! this-swipeable %)
|
||||||
(into
|
[this-swipeable])
|
||||||
[gesture/swipeable
|
on-swipeable-will-open (rn/use-callback
|
||||||
(merge
|
(fn []
|
||||||
{:ref #(reset! swipeable-ref %)
|
(when (and @active-swipeable
|
||||||
:accessibility-label :notification-swipeable
|
(not= @active-swipeable @this-swipeable))
|
||||||
:friction 2
|
(oops/ocall @active-swipeable :close))
|
||||||
:on-swipeable-will-open (close-active-swipeable active-swipeable swipeable-ref)
|
(reset! active-swipeable @this-swipeable))
|
||||||
:children-container-style {:padding-horizontal 20}}
|
[@active-swipeable @this-swipeable])]
|
||||||
(when left-button
|
[gesture/swipeable
|
||||||
{:overshoot-left false
|
(cond-> {:ref set-this-swipeable
|
||||||
:left-threshold style/swipe-action-width
|
:accessibility-label :notification-swipeable
|
||||||
:render-left-actions (render-swipe-action
|
:friction 2
|
||||||
{:active-swipeable active-swipeable
|
:on-swipeable-will-open on-swipeable-will-open
|
||||||
:extra-fn extra-fn
|
:children-container-style {:padding-horizontal 20}}
|
||||||
:interpolation-opacity style/left-swipe-opacity-interpolation-js
|
left-button
|
||||||
:interpolation-translate-x
|
(assoc :overshoot-left false
|
||||||
style/left-swipe-translate-x-interpolation-js
|
:left-threshold style/swipe-action-width
|
||||||
:on-press left-on-press
|
:render-left-actions (render-swipe-action
|
||||||
:swipe-button left-button
|
{:active-swipeable active-swipeable
|
||||||
:swipeable-ref swipeable-ref
|
:extra-fn extra-fn
|
||||||
:style {:left 8}})})
|
:interpolation-opacity style/left-swipe-opacity-interpolation-js
|
||||||
(when right-button
|
:interpolation-translate-x
|
||||||
{:overshoot-right false
|
style/left-swipe-translate-x-interpolation-js
|
||||||
:right-threshold style/swipe-action-width
|
:on-press left-on-press
|
||||||
:render-right-actions (render-swipe-action
|
:swipe-button left-button
|
||||||
{:active-swipeable active-swipeable
|
:swipeable-ref this-swipeable
|
||||||
:extra-fn extra-fn
|
:style {:left style/swipe-button-margin}}))
|
||||||
:interpolation-opacity style/right-swipe-opacity-interpolation-js
|
|
||||||
:interpolation-translate-x
|
right-button
|
||||||
style/right-swipe-translate-x-interpolation-js
|
(assoc :overshoot-right false
|
||||||
:on-press right-on-press
|
:right-threshold style/swipe-action-width
|
||||||
:swipe-button right-button
|
:render-right-actions (render-swipe-action
|
||||||
:swipeable-ref swipeable-ref
|
{:active-swipeable active-swipeable
|
||||||
:style {:right -8}})}))]
|
:extra-fn extra-fn
|
||||||
children))))
|
:interpolation-opacity style/right-swipe-opacity-interpolation-js
|
||||||
|
:interpolation-translate-x
|
||||||
|
style/right-swipe-translate-x-interpolation-js
|
||||||
|
:on-press right-on-press
|
||||||
|
:swipe-button right-button
|
||||||
|
:swipeable-ref this-swipeable
|
||||||
|
:style {:right (- style/swipe-button-margin)}})))
|
||||||
|
child]))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.community-kicked.view
|
(ns status-im.contexts.shell.activity-center.notification.community-kicked.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
[react-native.gesture :as gesture]
|
[react-native.gesture :as gesture]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
||||||
|
@ -9,33 +10,34 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn]} child]
|
[{:keys [extra-fn]} child]
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child])
|
child])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification extra-fn]}]
|
||||||
(let [{:keys [community-id read
|
(let [{:keys [id community-id read
|
||||||
timestamp]} notification
|
timestamp]} notification
|
||||||
community (rf/sub [:communities/community community-id])
|
community (rf/sub [:communities/community community-id])
|
||||||
community-name (:name community)
|
community-name (:name community)
|
||||||
community-image (get-in community [:images :thumbnail :uri])]
|
community-image (get-in community [:images :thumbnail :uri])
|
||||||
[swipeable props
|
customization-color (rf/sub [:profile/customization-color])
|
||||||
[gesture/touchable-without-feedback
|
on-press (rn/use-callback
|
||||||
{:on-press (fn []
|
(fn []
|
||||||
(rf/dispatch [:navigate-back])
|
(rf/dispatch [:navigate-back])
|
||||||
(rf/dispatch [:activity-center.notifications/mark-as-read (:id notification)]))}
|
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
|
||||||
|
[id])]
|
||||||
|
[swipeable {:extra-fn extra-fn}
|
||||||
|
[gesture/touchable-without-feedback {:on-press on-press}
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/community-kicked-heading)
|
{:title (i18n/label :t/community-kicked-heading)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:icon :i/placeholder
|
:icon :i/placeholder
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
:context [[quo/text {:style common-style/user-avatar-tag-text}
|
:context [[quo/text {:style common-style/user-avatar-tag-text}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.community-request.view
|
(ns status-im.contexts.shell.activity-center.notification.community-request.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
[react-native.gesture :as gesture]
|
[react-native.gesture :as gesture]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
||||||
|
@ -10,27 +11,23 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn]} child]
|
[{:keys [extra-fn]} child]
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child])
|
child])
|
||||||
|
|
||||||
(defn- get-header-text-and-context
|
(defn- get-header-text-and-context
|
||||||
[community membership-status]
|
[community-logo community-name community-permissions membership-status]
|
||||||
(let [community-name (:name community)
|
(let [open? (not= 3 (:access community-permissions))
|
||||||
permissions (:permissions community)
|
|
||||||
open? (not= 3 (:access permissions))
|
|
||||||
community-image (get-in community [:images :thumbnail :uri])
|
|
||||||
community-context-tag [quo/context-tag
|
community-context-tag [quo/context-tag
|
||||||
{:type :community
|
{:type :community
|
||||||
:size 24
|
:size 24
|
||||||
:blur? true
|
:blur? true
|
||||||
:community-logo community-image
|
:community-logo community-logo
|
||||||
:community-name community-name}]]
|
:community-name community-name}]]
|
||||||
(cond
|
(cond
|
||||||
(= membership-status constants/activity-center-membership-status-idle)
|
(= membership-status constants/activity-center-membership-status-idle)
|
||||||
|
@ -56,27 +53,33 @@
|
||||||
:t/joined-community
|
:t/joined-community
|
||||||
:t/community-request-accepted-body-text)
|
:t/community-request-accepted-body-text)
|
||||||
(when open? {:community community-name}))]
|
(when open? {:community community-name}))]
|
||||||
community-context-tag]}
|
community-context-tag]})))
|
||||||
|
|
||||||
:else nil)))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification extra-fn]}]
|
||||||
(let [{:keys [community-id membership-status read
|
(let [{:keys [community-id membership-status read
|
||||||
timestamp]} notification
|
timestamp]} notification
|
||||||
community (rf/sub [:communities/community community-id])
|
community-name (rf/sub [:communities/name community-id])
|
||||||
{:keys [header-text context]} (get-header-text-and-context community
|
community-logo (rf/sub [:communities/logo community-id])
|
||||||
membership-status)]
|
community-permissions (rf/sub [:communities/permissions community-id])
|
||||||
[swipeable props
|
customization-color (rf/sub [:profile/customization-color])
|
||||||
[gesture/touchable-without-feedback
|
{:keys [header-text
|
||||||
{:on-press (fn []
|
context]} (get-header-text-and-context community-logo
|
||||||
(rf/dispatch [:navigate-back])
|
community-name
|
||||||
(rf/dispatch [:communities/navigate-to-community-overview community-id]))}
|
community-permissions
|
||||||
|
membership-status)
|
||||||
|
on-press (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:navigate-back])
|
||||||
|
(rf/dispatch [:communities/navigate-to-community-overview
|
||||||
|
community-id]))
|
||||||
|
[community-id])]
|
||||||
|
[swipeable {:extra-fn extra-fn}
|
||||||
|
[gesture/touchable-without-feedback {:on-press on-press}
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title header-text
|
{:title header-text
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:icon :i/communities
|
:icon :i/communities
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
:context context}]]]))
|
:context context}]]]))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.contact-requests.view
|
(ns status-im.contexts.shell.activity-center.notification.contact-requests.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
quo.theme
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
||||||
|
@ -24,48 +25,52 @@
|
||||||
:text (i18n/label :t/decline)}])
|
:text (i18n/label :t/decline)}])
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn notification]} child]
|
[{:keys [extra-fn notification]} child]
|
||||||
(let [{:keys [id author message]} notification
|
(let [{:keys [id author message]} notification
|
||||||
{:keys [contact-request-state]} message
|
{:keys [contact-request-state]} message
|
||||||
{:keys [public-key]} (rf/sub [:multiaccount/contact])
|
{:keys [public-key]} (rf/sub [:multiaccount/contact])
|
||||||
outgoing? (= public-key author)]
|
outgoing? (= public-key author)
|
||||||
|
accept (rn/use-callback
|
||||||
|
#(rf/dispatch [:activity-center.contact-requests/accept id])
|
||||||
|
[id])
|
||||||
|
decline (rn/use-callback
|
||||||
|
#(rf/dispatch [:activity-center.contact-requests/decline id])
|
||||||
|
[id])]
|
||||||
(cond
|
(cond
|
||||||
(or (#{constants/contact-request-message-state-accepted
|
(or (#{constants/contact-request-message-state-accepted
|
||||||
constants/contact-request-message-state-declined}
|
constants/contact-request-message-state-declined}
|
||||||
contact-request-state)
|
contact-request-state)
|
||||||
(and outgoing? (= contact-request-state constants/contact-request-message-state-pending)))
|
(and outgoing? (= contact-request-state constants/contact-request-message-state-pending)))
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
(and (= contact-request-state constants/contact-request-message-state-pending)
|
(and (= contact-request-state constants/contact-request-message-state-pending)
|
||||||
(not outgoing?))
|
(not outgoing?))
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button swipe-button-accept
|
{:left-button swipe-button-accept
|
||||||
:left-on-press #(rf/dispatch [:activity-center.contact-requests/accept id])
|
:left-on-press accept
|
||||||
:right-button swipe-button-decline
|
:right-button swipe-button-decline
|
||||||
:right-on-press #(rf/dispatch [:activity-center.contact-requests/decline id])
|
:right-on-press decline
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
child)))
|
child)))
|
||||||
|
|
||||||
(defn- outgoing-contact-request-view
|
(defn- outgoing-contact-request-view
|
||||||
[{:keys [notification set-swipeable-height customization-color]} theme]
|
[{:keys [notification]} theme]
|
||||||
(let [{:keys [chat-id message last-message accepted]} notification
|
(let [{:keys [chat-id message last-message accepted]} notification
|
||||||
{:keys [contact-request-state] :as message} (or message last-message)]
|
{:keys [contact-request-state] :as message} (or message last-message)
|
||||||
|
customization-color (rf/sub [:profile/customization-color])]
|
||||||
(if accepted
|
(if accepted
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/contact-request-was-accepted)
|
{:title (i18n/label :t/contact-request-was-accepted)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/add-user
|
:icon :i/add-user
|
||||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||||
:unread? (not (:read notification))
|
:unread? (not (:read notification))
|
||||||
|
@ -76,7 +81,6 @@
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/contact-request)
|
{:title (i18n/label :t/contact-request)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/add-user
|
:icon :i/add-user
|
||||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||||
:unread? (not (:read notification))
|
:unread? (not (:read notification))
|
||||||
|
@ -102,13 +106,22 @@
|
||||||
nil)}])))
|
nil)}])))
|
||||||
|
|
||||||
(defn- incoming-contact-request-view
|
(defn- incoming-contact-request-view
|
||||||
[{:keys [notification set-swipeable-height customization-color]} theme]
|
[{:keys [notification]} theme]
|
||||||
(let [{:keys [id author message last-message]} notification
|
(let [{:keys [id author message
|
||||||
message (or message last-message)]
|
last-message]} notification
|
||||||
|
customization-color (rf/sub [:profile/customization-color])
|
||||||
|
message (or message last-message)
|
||||||
|
accept (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:activity-center.contact-requests/accept id]))
|
||||||
|
[id])
|
||||||
|
decline (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:activity-center.contact-requests/decline id]))
|
||||||
|
[id])]
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/contact-request)
|
{:title (i18n/label :t/contact-request)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/add-user
|
:icon :i/add-user
|
||||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||||
:unread? (not (:read notification))
|
:unread? (not (:read notification))
|
||||||
|
@ -140,13 +153,13 @@
|
||||||
:key :button-decline
|
:key :button-decline
|
||||||
:label (i18n/label :t/decline)
|
:label (i18n/label :t/decline)
|
||||||
:accessibility-label :decline-contact-request
|
:accessibility-label :decline-contact-request
|
||||||
:on-press #(rf/dispatch [:activity-center.contact-requests/decline id])}
|
:on-press decline}
|
||||||
{:type :button
|
{:type :button
|
||||||
:subtype :positive
|
:subtype :positive
|
||||||
:key :button-accept
|
:key :button-accept
|
||||||
:label (i18n/label :t/accept)
|
:label (i18n/label :t/accept)
|
||||||
:accessibility-label :accept-contact-request
|
:accessibility-label :accept-contact-request
|
||||||
:on-press #(rf/dispatch [:activity-center.contact-requests/accept id])}]
|
:on-press accept}]
|
||||||
|
|
||||||
nil)}]))
|
nil)}]))
|
||||||
|
|
||||||
|
@ -155,16 +168,16 @@
|
||||||
(let [{:keys [author message last-message]} notification
|
(let [{:keys [author message last-message]} notification
|
||||||
{:keys [public-key]} (rf/sub [:multiaccount/contact])
|
{:keys [public-key]} (rf/sub [:multiaccount/contact])
|
||||||
{:keys [contact-request-state]} (or message last-message)
|
{:keys [contact-request-state]} (or message last-message)
|
||||||
app-theme (rf/sub [:theme])]
|
theme (quo.theme/use-theme)]
|
||||||
[swipeable props
|
[swipeable props
|
||||||
(cond
|
(cond
|
||||||
(= public-key author)
|
(= public-key author)
|
||||||
[outgoing-contact-request-view props app-theme]
|
[outgoing-contact-request-view props theme]
|
||||||
|
|
||||||
(= contact-request-state constants/contact-request-message-state-accepted)
|
(= contact-request-state constants/contact-request-message-state-accepted)
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:on-press #(rf/dispatch [:chat.ui/start-chat author])}
|
{:on-press #(rf/dispatch [:chat.ui/start-chat author])}
|
||||||
[incoming-contact-request-view props app-theme]]
|
[incoming-contact-request-view props theme]]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[incoming-contact-request-view props app-theme])]))
|
[incoming-contact-request-view props theme])]))
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
|
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn notification replying?] :as props} child]
|
[{:keys [extra-fn notification replying?] :as props} child]
|
||||||
(let [{:keys [id message
|
(let [{:keys [id message
|
||||||
contact-verification-status]} notification
|
contact-verification-status]} notification
|
||||||
challenger? (:outgoing message)]
|
challenger? (:outgoing message)]
|
||||||
|
@ -116,23 +116,21 @@
|
||||||
(and (not challenger?)
|
(and (not challenger?)
|
||||||
(= contact-verification-status constants/contact-verification-status-pending))
|
(= contact-verification-status constants/contact-verification-status-pending))
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button swipe-button-reply
|
{:left-button swipe-button-reply
|
||||||
:left-on-press #(prepare-challenge-reply props)
|
:left-on-press #(prepare-challenge-reply props)
|
||||||
:right-button swipe-button-decline
|
:right-button swipe-button-decline
|
||||||
:right-on-press #(decline-challenge id)
|
:right-on-press #(decline-challenge id)
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
(and challenger?
|
(and challenger?
|
||||||
(= contact-verification-status constants/contact-verification-status-accepted))
|
(= contact-verification-status constants/contact-verification-status-accepted))
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button swipe-button-trust
|
{:left-button swipe-button-trust
|
||||||
:left-on-press #(mark-challenge-trusted id)
|
:left-on-press #(mark-challenge-trusted id)
|
||||||
:right-button swipe-button-untrustworthy
|
:right-button swipe-button-untrustworthy
|
||||||
:right-on-press #(mark-challenge-untrustworthy id)
|
:right-on-press #(mark-challenge-untrustworthy id)
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
(#{constants/contact-verification-status-accepted
|
(#{constants/contact-verification-status-accepted
|
||||||
|
@ -140,12 +138,11 @@
|
||||||
constants/contact-verification-status-trusted}
|
constants/contact-verification-status-trusted}
|
||||||
contact-verification-status)
|
contact-verification-status)
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
@ -154,8 +151,9 @@
|
||||||
(defn view
|
(defn view
|
||||||
[_]
|
[_]
|
||||||
(let [reply (atom "")]
|
(let [reply (atom "")]
|
||||||
(fn [{:keys [notification set-swipeable-height replying? customization-color] :as props}]
|
(fn [{:keys [notification replying?] :as props}]
|
||||||
(let [{:keys [id message
|
(let [customization-color (rf/sub [:profile/customization-color])
|
||||||
|
{:keys [id message
|
||||||
contact-verification-status]} notification
|
contact-verification-status]} notification
|
||||||
challenger? (:outgoing message)]
|
challenger? (:outgoing message)]
|
||||||
;; TODO(@ilmotta): Declined challenges should only be displayed for the challengee, not the
|
;; TODO(@ilmotta): Declined challenges should only be displayed for the challengee, not the
|
||||||
|
@ -165,86 +163,84 @@
|
||||||
(= contact-verification-status constants/contact-verification-status-declined))
|
(= contact-verification-status constants/contact-verification-status-declined))
|
||||||
[swipeable props
|
[swipeable props
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
(merge
|
{:title (i18n/label :t/identity-verification-request)
|
||||||
(when-not replying?
|
:customization-color customization-color
|
||||||
{:on-layout set-swipeable-height})
|
:icon :i/friend
|
||||||
{:title (i18n/label :t/identity-verification-request)
|
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
||||||
:customization-color customization-color
|
:unread? (not (:read notification))
|
||||||
:icon :i/friend
|
:on-update-reply #(reset! reply %)
|
||||||
:timestamp (datetime/timestamp->relative (:timestamp notification))
|
:replying? replying?
|
||||||
:unread? (not (:read notification))
|
:max-reply-length max-reply-length
|
||||||
:on-update-reply #(reset! reply %)
|
:valid-reply? valid-reply?
|
||||||
:replying? replying?
|
:context (context-tags challenger? notification)
|
||||||
:max-reply-length max-reply-length
|
:message (activity-message challenger? notification)
|
||||||
:valid-reply? valid-reply?
|
:items
|
||||||
:context (context-tags challenger? notification)
|
(cond-> []
|
||||||
:message (activity-message challenger? notification)
|
(and challenger?
|
||||||
:items
|
(= contact-verification-status constants/contact-verification-status-accepted))
|
||||||
(cond-> []
|
(concat
|
||||||
(and challenger?
|
[{:type :button
|
||||||
(= contact-verification-status constants/contact-verification-status-accepted))
|
:subtype :danger
|
||||||
(concat
|
:key :button-mark-as-untrustworthy
|
||||||
[{:type :button
|
:label (i18n/label :t/untrustworthy)
|
||||||
:subtype :danger
|
:accessibility-label :mark-contact-verification-as-untrustworthy
|
||||||
:key :button-mark-as-untrustworthy
|
:on-press #(mark-challenge-untrustworthy id)}
|
||||||
:label (i18n/label :t/untrustworthy)
|
{:type :button
|
||||||
:accessibility-label :mark-contact-verification-as-untrustworthy
|
:subtype :positive
|
||||||
:on-press #(mark-challenge-untrustworthy id)}
|
:key :button-accept
|
||||||
{:type :button
|
:label (i18n/label :t/accept)
|
||||||
:subtype :positive
|
:accessibility-label :mark-contact-verification-as-trusted
|
||||||
:key :button-accept
|
:on-press #(mark-challenge-trusted id)}])
|
||||||
:label (i18n/label :t/accept)
|
|
||||||
:accessibility-label :mark-contact-verification-as-trusted
|
|
||||||
:on-press #(mark-challenge-trusted id)}])
|
|
||||||
|
|
||||||
(and challenger?
|
(and challenger?
|
||||||
(= contact-verification-status constants/contact-verification-status-trusted))
|
(= contact-verification-status constants/contact-verification-status-trusted))
|
||||||
(concat [{:type :status
|
(concat [{:type :status
|
||||||
:subtype :positive
|
:subtype :positive
|
||||||
:key :status-trusted
|
:key :status-trusted
|
||||||
:label (i18n/label :t/status-confirmed)}])
|
:label (i18n/label :t/status-confirmed)}])
|
||||||
|
|
||||||
(and challenger?
|
(and challenger?
|
||||||
(= contact-verification-status constants/contact-verification-status-untrustworthy))
|
(= contact-verification-status
|
||||||
(concat [{:type :status
|
constants/contact-verification-status-untrustworthy))
|
||||||
:subtype :negative
|
(concat [{:type :status
|
||||||
:key :status-untrustworthy
|
:subtype :negative
|
||||||
:label (i18n/label :t/untrustworthy)}])
|
:key :status-untrustworthy
|
||||||
|
:label (i18n/label :t/untrustworthy)}])
|
||||||
|
|
||||||
(and (not challenger?)
|
(and (not challenger?)
|
||||||
(= contact-verification-status constants/contact-verification-status-accepted))
|
(= contact-verification-status constants/contact-verification-status-accepted))
|
||||||
(concat [{:type :status
|
(concat [{:type :status
|
||||||
:subtype :positive
|
:subtype :positive
|
||||||
:key :status-accepted
|
:key :status-accepted
|
||||||
:label (i18n/label :t/replied)}])
|
:label (i18n/label :t/replied)}])
|
||||||
|
|
||||||
(and (not challenger?)
|
(and (not challenger?)
|
||||||
(= contact-verification-status constants/contact-verification-status-declined))
|
(= contact-verification-status constants/contact-verification-status-declined))
|
||||||
(concat [{:type :status
|
(concat [{:type :status
|
||||||
:subtype :negative
|
:subtype :negative
|
||||||
:key :status-declined
|
:key :status-declined
|
||||||
:label (i18n/label :t/declined)}])
|
:label (i18n/label :t/declined)}])
|
||||||
|
|
||||||
(and (not challenger?)
|
(and (not challenger?)
|
||||||
(= contact-verification-status constants/contact-verification-status-pending))
|
(= contact-verification-status constants/contact-verification-status-pending))
|
||||||
(concat
|
(concat
|
||||||
[{:type :button
|
[{:type :button
|
||||||
:subtype :danger
|
:subtype :danger
|
||||||
:key :button-decline
|
:key :button-decline
|
||||||
:label (i18n/label :t/decline)
|
:label (i18n/label :t/decline)
|
||||||
:accessibility-label :decline-contact-verification
|
:accessibility-label :decline-contact-verification
|
||||||
:on-press #(decline-challenge id)}
|
:on-press #(decline-challenge id)}
|
||||||
(if replying?
|
(if replying?
|
||||||
{:type :button
|
{:type :button
|
||||||
:subtype :primary
|
:subtype :primary
|
||||||
:key :button-reply
|
:key :button-reply
|
||||||
:label (i18n/label :t/send-reply)
|
:label (i18n/label :t/send-reply)
|
||||||
:accessibility-label :reply-to-contact-verification
|
:accessibility-label :reply-to-contact-verification
|
||||||
:disable-when invalid-reply?
|
:disable-when invalid-reply?
|
||||||
:on-press #(send-challenge-reply id @reply)}
|
:on-press #(send-challenge-reply id @reply)}
|
||||||
{:type :button
|
{:type :button
|
||||||
:subtype :primary
|
:subtype :primary
|
||||||
:key :button-send-reply
|
:key :button-send-reply
|
||||||
:label (i18n/label :t/message-reply)
|
:label (i18n/label :t/message-reply)
|
||||||
:accessibility-label :send-reply-to-contact-verification
|
:accessibility-label :send-reply-to-contact-verification
|
||||||
:on-press #(prepare-challenge-reply props)})]))})]])))))
|
:on-press #(prepare-challenge-reply props)})]))}]])))))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.contexts.shell.activity-center.notification.membership.view
|
(ns status-im.contexts.shell.activity-center.notification.membership.view
|
||||||
(:require
|
(:require
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
[react-native.gesture :as gesture]
|
[react-native.gesture :as gesture]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
|
||||||
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
[status-im.contexts.shell.activity-center.notification.common.view :as common]
|
||||||
|
@ -33,35 +34,50 @@
|
||||||
:text (i18n/label :t/decline)}])
|
:text (i18n/label :t/decline)}])
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable notification extra-fn]} child]
|
[{:keys [notification extra-fn]} child]
|
||||||
(let [{:keys [accepted dismissed id]} notification]
|
(let [{:keys [accepted dismissed
|
||||||
|
id]} notification
|
||||||
|
accept (rn/use-callback
|
||||||
|
(fn [] (rf/dispatch [:activity-center.notifications/accept id]))
|
||||||
|
[id])
|
||||||
|
dismiss (rn/use-callback
|
||||||
|
(fn [] (rf/dispatch [:activity-center.notifications/dismiss id]))
|
||||||
|
[id])]
|
||||||
(if (or accepted dismissed)
|
(if (or accepted dismissed)
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child]
|
child]
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button swipe-button-accept
|
{:left-button swipe-button-accept
|
||||||
:left-on-press #(rf/dispatch [:activity-center.notifications/accept id])
|
:left-on-press accept
|
||||||
:right-button swipe-button-decline
|
:right-button swipe-button-decline
|
||||||
:right-on-press #(rf/dispatch [:activity-center.notifications/dismiss id])
|
:right-on-press dismiss
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child])))
|
child])))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification] :as props}]
|
||||||
(let [{:keys [id accepted dismissed author read timestamp chat-name chat-id]} notification]
|
(let [{:keys [id accepted dismissed author read
|
||||||
|
timestamp chat-name
|
||||||
|
chat-id]} notification
|
||||||
|
customization-color (rf/sub [:profile/customization-color])
|
||||||
|
accept (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:activity-center.notifications/accept id]))
|
||||||
|
[id])
|
||||||
|
dismiss (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:activity-center.notifications/dismiss id]))
|
||||||
|
[id])]
|
||||||
[swipeable props
|
[swipeable props
|
||||||
[pressable {:accepted accepted :chat-id chat-id}
|
[pressable {:accepted accepted :chat-id chat-id}
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/added-to-group-chat)
|
{:title (i18n/label :t/added-to-group-chat)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/add-user
|
:icon :i/add-user
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
|
@ -78,13 +94,10 @@
|
||||||
:key :button-accept
|
:key :button-accept
|
||||||
:label (i18n/label :t/accept)
|
:label (i18n/label :t/accept)
|
||||||
:accessibility-label :accept-group-chat-invitation
|
:accessibility-label :accept-group-chat-invitation
|
||||||
:on-press #(rf/dispatch
|
:on-press accept}
|
||||||
[:activity-center.notifications/accept id])}
|
|
||||||
{:type :button
|
{:type :button
|
||||||
:subtype :danger
|
:subtype :danger
|
||||||
:key :button-decline
|
:key :button-decline
|
||||||
:label (i18n/label :t/decline)
|
:label (i18n/label :t/decline)
|
||||||
:accessibility-label :decline-group-chat-invitation
|
:accessibility-label :decline-group-chat-invitation
|
||||||
:on-press #(rf/dispatch
|
:on-press dismiss}])}]]]))
|
||||||
[:activity-center.notifications/dismiss
|
|
||||||
id])}])}]]]))
|
|
||||||
|
|
|
@ -30,25 +30,24 @@
|
||||||
parsed-text-children))))
|
parsed-text-children))))
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn]} child]
|
[{:keys [extra-fn]} child]
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child])
|
child])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification extra-fn]}]
|
||||||
(let [{:keys [author chat-name community-id chat-id
|
(let [{:keys [author chat-name community-id chat-id
|
||||||
message read timestamp]} notification
|
message read timestamp]} notification
|
||||||
community-chat? (not (string/blank? community-id))
|
community-chat? (not (string/blank? community-id))
|
||||||
community (rf/sub [:communities/community community-id])
|
community-name (rf/sub [:communities/name community-id])
|
||||||
community-name (:name community)
|
community-logo (rf/sub [:communities/logo community-id])
|
||||||
community-image (get-in community [:images :thumbnail :uri])]
|
customization-color (rf/sub [:profile/customization-color])]
|
||||||
[swipeable props
|
[swipeable {:extra-fn extra-fn}
|
||||||
[gesture/touchable-without-feedback
|
[gesture/touchable-without-feedback
|
||||||
{:on-press (fn []
|
{:on-press (fn []
|
||||||
(rf/dispatch [:hide-popover])
|
(rf/dispatch [:hide-popover])
|
||||||
|
@ -56,7 +55,6 @@
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/mention)
|
{:title (i18n/label :t/mention)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/mention
|
:icon :i/mention
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
|
@ -68,7 +66,7 @@
|
||||||
{:type :channel
|
{:type :channel
|
||||||
:blur? true
|
:blur? true
|
||||||
:size 24
|
:size 24
|
||||||
:community-logo community-image
|
:community-logo community-logo
|
||||||
:community-name community-name
|
:community-name community-name
|
||||||
:channel-name chat-name}]
|
:channel-name chat-name}]
|
||||||
[quo/context-tag
|
[quo/context-tag
|
||||||
|
|
|
@ -51,26 +51,26 @@
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(defn- swipeable
|
(defn- swipeable
|
||||||
[{:keys [active-swipeable extra-fn]} child]
|
[{:keys [extra-fn]} child]
|
||||||
[common/swipeable
|
[common/swipeable
|
||||||
{:left-button common/swipe-button-read-or-unread
|
{:left-button common/swipe-button-read-or-unread
|
||||||
:left-on-press common/swipe-on-press-toggle-read
|
:left-on-press common/swipe-on-press-toggle-read
|
||||||
:right-button common/swipe-button-delete
|
:right-button common/swipe-button-delete
|
||||||
:right-on-press common/swipe-on-press-delete
|
:right-on-press common/swipe-on-press-delete
|
||||||
:active-swipeable active-swipeable
|
:extra-fn extra-fn}
|
||||||
:extra-fn extra-fn}
|
|
||||||
child])
|
child])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [notification set-swipeable-height customization-color] :as props}]
|
[{:keys [notification extra-fn]}]
|
||||||
(let [{:keys [author chat-name community-id chat-id
|
(let [{:keys [author chat-name community-id chat-id
|
||||||
message read timestamp album-messages]} notification
|
message read timestamp
|
||||||
community-chat? (not (string/blank? community-id))
|
album-messages]} notification
|
||||||
community (rf/sub [:communities/community community-id])
|
community-chat? (not (string/blank? community-id))
|
||||||
community-name (:name community)
|
community-name (rf/sub [:communities/name community-id])
|
||||||
community-image (get-in community [:images :thumbnail :uri])
|
community-logo (rf/sub [:communities/logo community-id])
|
||||||
media-server-port (rf/sub [:mediaserver/port])]
|
customization-color (rf/sub [:profile/customization-color])
|
||||||
[swipeable props
|
media-server-port (rf/sub [:mediaserver/port])]
|
||||||
|
[swipeable {:extra-fn extra-fn}
|
||||||
[gesture/touchable-without-feedback
|
[gesture/touchable-without-feedback
|
||||||
{:on-press (fn []
|
{:on-press (fn []
|
||||||
(rf/dispatch [:hide-popover])
|
(rf/dispatch [:hide-popover])
|
||||||
|
@ -78,7 +78,6 @@
|
||||||
[quo/activity-log
|
[quo/activity-log
|
||||||
{:title (i18n/label :t/message-reply)
|
{:title (i18n/label :t/message-reply)
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-layout set-swipeable-height
|
|
||||||
:icon :i/reply
|
:icon :i/reply
|
||||||
:timestamp (datetime/timestamp->relative timestamp)
|
:timestamp (datetime/timestamp->relative timestamp)
|
||||||
:unread? (not read)
|
:unread? (not read)
|
||||||
|
@ -89,7 +88,7 @@
|
||||||
{:type :channel
|
{:type :channel
|
||||||
:blur? true
|
:blur? true
|
||||||
:size 24
|
:size 24
|
||||||
:community-logo community-image
|
:community-logo community-logo
|
||||||
:community-name community-name
|
:community-name community-name
|
||||||
:channel-name chat-name}]
|
:channel-name chat-name}]
|
||||||
[quo/context-tag
|
[quo/context-tag
|
||||||
|
@ -113,10 +112,7 @@
|
||||||
|
|
||||||
(= (:content-type message)
|
(= (:content-type message)
|
||||||
constants/content-type-gif)
|
constants/content-type-gif)
|
||||||
:gif
|
:gif)
|
||||||
|
|
||||||
:else
|
|
||||||
nil)
|
|
||||||
:body (get-message-content message
|
:body (get-message-content message
|
||||||
album-messages
|
album-messages
|
||||||
media-server-port)}}]]]))
|
media-server-port)}}]]]))
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
(ns status-im.contexts.shell.activity-center.view
|
(ns status-im.contexts.shell.activity-center.view
|
||||||
(:require
|
(:require
|
||||||
[oops.core :as oops]
|
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.navigation :as navigation]
|
[react-native.navigation :as navigation]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.contexts.shell.activity-center.context :as ac.context]
|
||||||
[status-im.contexts.shell.activity-center.header.view :as header]
|
[status-im.contexts.shell.activity-center.header.view :as header]
|
||||||
[status-im.contexts.shell.activity-center.notification-types :as types]
|
[status-im.contexts.shell.activity-center.notification-types :as types]
|
||||||
[status-im.contexts.shell.activity-center.notification.admin.view :as admin]
|
[status-im.contexts.shell.activity-center.notification.admin.view :as admin]
|
||||||
|
@ -23,61 +24,68 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn notification-component
|
(defn notification-component
|
||||||
|
[{:keys [type] :as notification} index]
|
||||||
|
(let [extra-fn (rn/use-callback
|
||||||
|
(fn []
|
||||||
|
{:notification notification})
|
||||||
|
[notification])
|
||||||
|
props {:notification notification
|
||||||
|
:extra-fn extra-fn}]
|
||||||
|
;; Notifications are expensive to render. Without `delay-render` the opening
|
||||||
|
;; animation of the Activity Center can be clunky and the time to open the
|
||||||
|
;; AC after pressing the bell icon can be high.
|
||||||
|
[rn/view {:style (style/notification-container index)}
|
||||||
|
(cond
|
||||||
|
(= type types/contact-verification)
|
||||||
|
[contact-verification/view props]
|
||||||
|
|
||||||
|
(= type types/contact-request)
|
||||||
|
[contact-requests/view props]
|
||||||
|
|
||||||
|
(= type types/mention)
|
||||||
|
[mentions/view props]
|
||||||
|
|
||||||
|
(= type types/reply)
|
||||||
|
[reply/view props]
|
||||||
|
|
||||||
|
(= type types/admin)
|
||||||
|
[admin/view props]
|
||||||
|
|
||||||
|
(some types/membership [type])
|
||||||
|
(condp = type
|
||||||
|
types/private-group-chat [membership/view props]
|
||||||
|
types/community-request [community-request/view props]
|
||||||
|
types/community-kicked [community-kicked/view props]
|
||||||
|
nil))]))
|
||||||
|
|
||||||
|
(defn- fetch-next-page
|
||||||
[]
|
[]
|
||||||
(let [height (atom 0)
|
(rf/dispatch [:activity-center.notifications/fetch-next-page]))
|
||||||
set-swipeable-height #(reset! height (oops/oget % "nativeEvent.layout.height"))]
|
|
||||||
(fn [{:keys [type] :as notification} index _ {:keys [active-swipeable customization-color]}]
|
|
||||||
(let [props {:height height
|
|
||||||
:customization-color customization-color
|
|
||||||
:active-swipeable active-swipeable
|
|
||||||
:set-swipeable-height set-swipeable-height
|
|
||||||
:notification notification
|
|
||||||
:extra-fn (fn [] {:height @height :notification notification})}]
|
|
||||||
[rn/view {:style (style/notification-container index)}
|
|
||||||
(cond
|
|
||||||
(= type types/contact-verification)
|
|
||||||
[contact-verification/view props]
|
|
||||||
|
|
||||||
(= type types/contact-request)
|
|
||||||
[contact-requests/view props]
|
|
||||||
|
|
||||||
(= type types/mention)
|
|
||||||
[mentions/view props]
|
|
||||||
|
|
||||||
(= type types/reply)
|
|
||||||
[reply/view props]
|
|
||||||
|
|
||||||
(= type types/admin)
|
|
||||||
[admin/view props]
|
|
||||||
|
|
||||||
(some types/membership [type])
|
|
||||||
(condp = type
|
|
||||||
types/private-group-chat [membership/view props]
|
|
||||||
types/community-request [community-request/view props]
|
|
||||||
types/community-kicked [community-kicked/view props]
|
|
||||||
nil)
|
|
||||||
|
|
||||||
:else
|
|
||||||
nil)]))))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
(let [active-swipeable (atom nil)]
|
(let [notifications (rf/sub [:activity-center/notifications])
|
||||||
(rf/dispatch [:activity-center.notifications/fetch-first-page])
|
|
||||||
(fn []
|
;; We globally control the active swipeable for all notifications
|
||||||
(let [notifications (rf/sub [:activity-center/notifications])
|
;; because when a swipe left/right gesture initiates, the previously
|
||||||
customization-color (rf/sub [:profile/customization-color])]
|
;; active swiped notification (if any) must be removed & closed with
|
||||||
[quo/overlay {:type :shell}
|
;; animation.
|
||||||
[rn/view {:flex 1 :padding-top (navigation/status-bar-height)}
|
active-swipeable (rn/use-ref-atom nil)]
|
||||||
[header/header]
|
(rn/use-mount
|
||||||
[rn/flat-list
|
(fn []
|
||||||
{:data notifications
|
(rf/dispatch [:activity-center.notifications/fetch-first-page])))
|
||||||
:render-data {:active-swipeable active-swipeable
|
|
||||||
:customization-color customization-color}
|
[ac.context/provider {:active-swipeable active-swipeable}
|
||||||
:content-container-style {:flex-grow 1}
|
[quo/overlay {:type :shell}
|
||||||
:empty-component [empty-tab/empty-tab]
|
[rn/view {:style {:flex 1 :padding-top (navigation/status-bar-height)}}
|
||||||
:key-fn :id
|
[header/header]
|
||||||
:on-scroll-to-index-failed identity
|
(rn/delay-render
|
||||||
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
|
[rn/flat-list
|
||||||
:render-fn notification-component}]]
|
{:data notifications
|
||||||
]))))
|
:initial-num-to-render constants/notifications-per-page
|
||||||
|
:content-container-style {:flex-grow 1}
|
||||||
|
:empty-component [empty-tab/empty-tab]
|
||||||
|
:key-fn :id
|
||||||
|
:on-scroll-to-index-failed identity
|
||||||
|
:on-end-reached fetch-next-page
|
||||||
|
:render-fn notification-component}])]]]))
|
||||||
|
|
|
@ -16,12 +16,33 @@
|
||||||
(fn [info [_ id]]
|
(fn [info [_ id]]
|
||||||
(get info id)))
|
(get info id)))
|
||||||
|
|
||||||
|
;; Do not use this subscription directly in views. There is a significant risk
|
||||||
|
;; of re-rendering views too frequently because an active community can change
|
||||||
|
;; for numerous reasons.
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:communities/community
|
:communities/community
|
||||||
:<- [:communities]
|
:<- [:communities]
|
||||||
(fn [communities [_ id]]
|
(fn [communities [_ id]]
|
||||||
(get communities id)))
|
(get communities id)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub :communities/logo
|
||||||
|
(fn [[_ community-id]]
|
||||||
|
[(re-frame/subscribe [:communities/community community-id])])
|
||||||
|
(fn [[community]]
|
||||||
|
(get-in community [:images :thumbnail :uri])))
|
||||||
|
|
||||||
|
(re-frame/reg-sub :communities/name
|
||||||
|
(fn [[_ community-id]]
|
||||||
|
[(re-frame/subscribe [:communities/community community-id])])
|
||||||
|
(fn [[{:keys [name]}]]
|
||||||
|
name))
|
||||||
|
|
||||||
|
(re-frame/reg-sub :communities/permissions
|
||||||
|
(fn [[_ community-id]]
|
||||||
|
[(re-frame/subscribe [:communities/community community-id])])
|
||||||
|
(fn [[{:keys [permissions]}]]
|
||||||
|
permissions))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:communities/community-color
|
:communities/community-color
|
||||||
(fn [[_ community-id]]
|
(fn [[_ community-id]]
|
||||||
|
|
Loading…
Reference in New Issue