[#11958] Add activity center

This commit is contained in:
andrey 2021-04-07 12:33:37 +02:00 committed by Andrea Maria Piana
parent 5bb849f9c1
commit 93ce02b547
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
24 changed files with 469 additions and 161 deletions

View File

@ -64,8 +64,8 @@
(defn checkbox-view [props]
(let [{:keys [value onChange disabled]} (bean/bean props)]
(reagent/as-element
[rn/touchable-highlight
{:on-press (when onChange onChange)}
[rn/touchable-without-feedback
{:on-press (when (and onChange (not disabled)) onChange)}
[rn/view {:style (styles/checkbox-style value disabled)
:accessibility-label :checkbox
:accessibility-role :checkbox}

View File

@ -69,4 +69,4 @@
{:db (-> db
(update :contacts/blocked disj public-key)
(assoc-in [:contacts/contacts public-key] contact))}
(contacts-store/save-contact contact))))
(contacts-store/save-contact contact nil))))

View File

@ -58,10 +58,14 @@
{:db (-> db
(update-in [:contacts/contacts public-key] merge contact))}
(transport.filters/load-contact contact)
#(contacts-store/save-contact % (get-in % [:db :contacts/contacts public-key]))))
(fn [cf]
(contacts-store/save-contact cf
(get-in cf [:db :contacts/contacts public-key])
#(re-frame/dispatch [::send-contact-request public-key])))))
(fx/defn send-contact-request
[{:keys [db] :as cofx} {:keys [public-key] :as contact}]
{:events [::send-contact-request]}
[{:keys [db] :as cofx} public-key]
(let [{:keys [name profile-image]} (own-info db)]
{::json-rpc/call [{:method (json-rpc/call-ext-method "sendContactUpdate")
:params [public-key name profile-image]
@ -85,7 +89,6 @@
:dispatch-n [[:start-profile-chat public-key]
[:offload-messages constants/timeline-chat-id]]}
(upsert-contact contact)
(send-contact-request contact)
(mailserver/process-next-messages-request)))))
(fx/defn remove-contact
@ -98,7 +101,7 @@
(fx/merge cofx
{:db (assoc-in db [:contacts/contacts public-key] new-contact)
:dispatch [:offload-messages constants/timeline-chat-id]}
(contacts-store/save-contact new-contact))))
(contacts-store/save-contact new-contact nil))))
(fx/defn create-contact
"Create entry in contacts"

View File

@ -0,0 +1,27 @@
(ns status-im.data-store.activities
(:require [status-im.data-store.messages :as messages]
[status-im.constants :as constants]
[status-im.ui.components.colors :as colors]
clojure.set))
(defn rpc->type [{:keys [type name] :as chat}]
(cond
(= 2 type) (assoc chat
:chat-type constants/private-group-chat-type
:chat-name name
:public? false
:group-chat true)
(= 1 type) (assoc chat
:chat-type constants/one-to-one-chat-type
:chat-name name
:public? false
:group-chat false)))
(defn <-rpc [item]
(-> item
rpc->type
(clojure.set/rename-keys {:lastMessage :last-message
:chatId :chat-id})
(assoc :color (rand-nth colors/chat-colors))
(update :last-message #(when % (messages/<-rpc %)))
(dissoc :chatId)))

View File

@ -40,10 +40,13 @@
:on-failure #(log/error "failed to fetch contacts" %)}]})
(fx/defn save-contact
[cofx {:keys [public-key] :as contact}]
[cofx {:keys [public-key] :as contact} on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "saveContact")
:params [(->rpc contact)]
:on-success #(log/debug "saved contact" public-key "successfuly")
:on-success #(do
(log/debug "saved contact" public-key "successfuly")
(when on-success
(on-success)))
:on-failure #(log/error "failed to save contact" public-key %)}]})
(fx/defn block [cofx contact on-success]

View File

@ -111,6 +111,7 @@
"wakuext_getPushNotificationsServers" {}
"wakuext_enablePushNotificationsBlockMentions" {}
"wakuext_disablePushNotificationsBlockMentions" {}
"wakuext_unreadActivityCenterNotificationsCount" {}
"multiaccounts_getIdentityImages" {}
"multiaccounts_getIdentityImage" {}
"multiaccounts_storeIdentityImage" {}
@ -131,6 +132,12 @@
"wakuext_importCommunity" {}
"wakuext_exportCommunity" {}
"wakuext_ensVerified" {}
"wakuext_dismissActivityCenterNotifications" {}
"wakuext_acceptActivityCenterNotifications" {}
"wakuext_dismissAllActivityCenterNotifications" {}
"wakuext_acceptAllActivityCenterNotifications" {}
"wakuext_markAllActivityCenterNotificationsRead" {}
"wakuext_activityCenterNotifications" {}
"status_chats" {}
"rpcstats_getStats" {}
"rpcstats_reset" {}

View File

@ -55,6 +55,7 @@
status-im.browser.core
status-im.browser.permissions
status-im.chat.models.transport
status-im.notifications-center.core
[status-im.navigation :as navigation]))
(re-frame/reg-fx

View File

@ -34,7 +34,8 @@
[status-im.chat.models.link-preview :as link-preview]
[status-im.utils.mobile-sync :as utils.mobile-sync]
[status-im.async-storage.core :as async-storage]
[status-im.chat.models :as chat.models]))
[status-im.chat.models :as chat.models]
[status-im.notifications-center.core :as notifications-center]))
(re-frame/reg-fx
::login
@ -276,7 +277,8 @@
(logging/set-log-level (:log-level multiaccount))
(multiaccounts/get-profile-picture)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist))))
(link-preview/request-link-preview-whitelist)
(notifications-center/get-activity-center-notifications-count))))
(defn get-new-auth-method [auth-method save-password?]
(when save-password?

View File

@ -0,0 +1,118 @@
(ns status-im.notifications-center.core
(:require [status-im.utils.fx :as fx]
[status-im.ethereum.json-rpc :as json-rpc]
[taoensso.timbre :as log]
[re-frame.core :as re-frame]
[status-im.data-store.activities :as data-store.activities]))
(fx/defn handle-activities [{:keys [db]} activities]
(if (= (:view-id db) :notifications-center)
{:db (-> db
(update-in [:activity.center/notifications :notifications] #(concat activities %)))
:dispatch [:mark-all-activity-center-notifications-as-read]}
{:db (-> db
(update :activity.center/notifications-count + (count activities)))}))
(fx/defn get-activity-center-notifications-count
{:events [:get-activity-center-notifications-count]}
[_]
{::json-rpc/call [{:method (json-rpc/call-ext-method "unreadActivityCenterNotificationsCount")
:params []
:on-success #(re-frame/dispatch [:get-activity-center-notifications-count-success %])
:on-error #()}]})
(fx/defn get-activity-center-notifications-count-success
{:events [:get-activity-center-notifications-count-success]}
[{:keys [db]} result]
{:db (assoc db :activity.center/notifications-count result)})
(fx/defn dismiss-activity-center-notifications
{:events [:dismiss-activity-center-notifications]}
[{:keys [db]} ids]
{:db (update-in db [:activity.center/notifications :notifications]
(fn [items] (remove #(get ids (:id %)) items)))
::json-rpc/call [{:method (json-rpc/call-ext-method "dismissActivityCenterNotifications")
:params [ids]
:on-success #()
:on-error #()}]})
(fx/defn accept-activity-center-notifications
{:events [:accept-activity-center-notifications]}
[{:keys [db]} ids]
{:db (update-in db [:activity.center/notifications :notifications]
(fn [items] (remove #(get ids (:id %)) items)))
::json-rpc/call [{:method (json-rpc/call-ext-method "acceptActivityCenterNotifications")
:params [ids]
:js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
:on-error #()}]})
(fx/defn accept-activity-center-notification-and-open-chat
{:events [:accept-activity-center-notification-and-open-chat]}
[{:keys [db]} id]
{:db (update-in db [:activity.center/notifications :notifications]
(fn [items] (remove #(= id (:id %)) items)))
::json-rpc/call [{:method (json-rpc/call-ext-method "acceptActivityCenterNotifications")
:params [[id]]
:js-response true
:on-success #(re-frame/dispatch [:ensure-and-open-chat %])
:on-error #()}]})
(fx/defn ensure-and-open-chat
{:events [:ensure-and-open-chat]}
[{:keys [db]} response-js]
{:db (update db :activity.center/notifications dissoc :cursor)
:dispatch-n [[:sanitize-messages-and-process-response response-js]
[:chat.ui/navigate-to-chat (.-id (aget (.-chats response-js) 0))]]})
(fx/defn dismiss-all-activity-center-notifications
{:events [:dismiss-all-activity-center-notifications]}
[{:keys [db]}]
{:db (assoc-in db [:activity.center/notifications :notifications] [])
::json-rpc/call [{:method (json-rpc/call-ext-method "dismissAllActivityCenterNotifications")
:params []
:on-success #()
:on-error #()}]})
(fx/defn accept-all-activity-center-notifications
{:events [:accept-all-activity-center-notifications]}
[{:keys [db]}]
{:db (assoc-in db [:activity.center/notifications :notifications] [])
::json-rpc/call [{:method (json-rpc/call-ext-method "acceptAllActivityCenterNotifications")
:params []
:js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
:on-error #()}]})
(fx/defn mark-all-activity-center-notifications-as-read
{:events [:mark-all-activity-center-notifications-as-read]}
[{:keys [db]}]
{:db (assoc db :activity.center/notifications-count 0)
::json-rpc/call [{:method (json-rpc/call-ext-method "markAllActivityCenterNotificationsRead")
:params []
:on-success #()
:on-error #()}]})
(fx/defn get-activity-center-notifications
{:events [:get-activity-center-notifications]}
[{:keys [db]}]
(let [{:keys [cursor]} (:activity.center/notifications db)]
(when (not= cursor "")
{::json-rpc/call [{:method (json-rpc/call-ext-method "activityCenterNotifications")
:params [cursor 20]
:on-success #(re-frame/dispatch [:activity-center-notifications-success %])
:on-error #(log/warn "failed to get notification center activities" %)}]})))
(fx/defn activity-center-notifications-success
{:events [:activity-center-notifications-success]}
[{:keys [db]} {:keys [cursor notifications]}]
{:db (-> db
(assoc-in [:activity.center/notifications :cursor] cursor)
(update-in [:activity.center/notifications :notifications]
concat
(map data-store.activities/<-rpc notifications)))})
(fx/defn close-center
{:events [:close-notifications-center]}
[{:keys [db]}]
{:db (dissoc db :activity.center/notifications)})

View File

@ -217,6 +217,9 @@
(reg-root-key-sub :communities/requests-to-join :communities/requests-to-join)
(reg-root-key-sub :communities/community-id-input :communities/community-id-input)
(reg-root-key-sub :activity.center/notifications :activity.center/notifications)
(reg-root-key-sub :activity.center/notifications-count :activity.center/notifications-count)
(re-frame/reg-sub
:communities
(fn [db]

View File

@ -11,11 +11,13 @@
[status-im.data-store.contacts :as data-store.contacts]
[status-im.data-store.chats :as data-store.chats]
[status-im.data-store.invitations :as data-store.invitations]
[status-im.data-store.activities :as data-store.activities]
[status-im.group-chats.core :as models.group]
[status-im.utils.fx :as fx]
[status-im.utils.types :as types]
[status-im.constants :as constants]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.notifications-center.core :as notifications-center]
[clojure.string :as string]))
(fx/defn process-next
@ -26,7 +28,7 @@
(fx/defn process-response
{:events [:process-response]}
[cofx ^js response-js process-async]
[{:keys [db] :as cofx} ^js response-js process-async]
(let [^js communities (.-communities response-js)
^js requests-to-join-community (.-requestsToJoinCommunity response-js)
^js chats (.-chats response-js)
@ -38,6 +40,7 @@
^js removed-filters (.-removedFilters response-js)
^js invitations (.-invitations response-js)
^js removed-chats (.-removedChats response-js)
^js activity-notifications (.-activityCenterNotifications response-js)
sync-handler (when-not process-async process-response)]
(cond
@ -56,6 +59,14 @@
(seq messages)
(models.message/receive-many cofx response-js)
(seq activity-notifications)
(do
(js-delete response-js "activityCenterNotifications")
(fx/merge cofx
(notifications-center/handle-activities (map data-store.activities/<-rpc
(types/js->clj activity-notifications)))
(process-next response-js sync-handler)))
(seq installations)
(let [installations-clj (types/js->clj installations)]
(js-delete response-js "installations")

View File

@ -164,7 +164,6 @@
(when-let [icon (get-icon state)]
[quo/button {:type :icon
:accessibility-label (str "conn-button-" (name icon))
:style {:margin-right 16}
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content connectivity-sheet}])
:theme (if (= (:peers state) :offline) :negative :secondary)} icon])))

View File

@ -199,6 +199,7 @@
:attribution
{:db (assoc-in db [:acquisition :accounts account :bonuses] data)}))
;;TODO this one rerender whole root many times FIX IT
(re-frame/reg-sub-raw
::default-reward
(fn [db]

View File

@ -240,7 +240,6 @@
(let [loading-messages? @(re-frame/subscribe [:chats/loading-messages? chat-id])
no-messages? @(re-frame/subscribe [:chats/chat-no-messages? chat-id])
all-loaded? @(re-frame/subscribe [:chats/all-loaded? chat-id])]
(println "LIST FOOTER" (or loading-messages? (not chat-id) (not all-loaded?)))
[react/view {:style (when platform/android? {:scaleY -1})}
(if (or loading-messages? (not chat-id) (not all-loaded?))
[react/view {:height 324 :align-items :center :justify-content :center}

View File

@ -17,7 +17,9 @@
[status-im.ui.components.icons.icons :as icons]
[status-im.utils.core :as utils]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.utils.config :as config]))
[status-im.utils.config :as config]
[re-frame.core :as re-frame]
[status-im.ui.screens.chat.sheets :as sheets]))
(def request-cooldown-ms (* 60 1000))
@ -121,8 +123,16 @@
:color :secondary}
(i18n/label :t/welcome-community-blank-message)]])
(defn community-chat-item [home-item]
[inner-item/home-list-item home-item])
(defn community-chat-item [{:keys [chat-id] :as home-item}]
[inner-item/home-list-item
home-item
{:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[sheets/actions home-item])}])}])
(defn community-chat-list [chats]
(if (empty? chats)

View File

@ -89,7 +89,3 @@
:background-color colors/gray
:align-items :center
:justify-content :center})
(def home-container
(merge
{:flex 1}))

View File

@ -25,7 +25,9 @@
[status-im.multiaccounts.login.core :as multiaccounts.login]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.plus-button :as components.plus-button])
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.tabbar.styles :as tabs.styles]
[status-im.ui.screens.chat.sheets :as sheets])
(:require-macros [status-im.utils.views :as views]))
(defn welcome-image-wrapper []
@ -148,7 +150,15 @@
(defn render-fn [{:keys [chat-id] :as home-item}]
;; We use `chat-id` to distinguish communities from chats
(if chat-id
[inner-item/home-list-item home-item]
[inner-item/home-list-item
home-item
{:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[sheets/actions home-item])}])}]
[communities.views/community-home-list-item home-item]))
(defn chat-list-key-fn [item]
@ -195,10 +205,30 @@
:loading logging-in?
:accessibility-label :new-chat-button}]))
(views/defview notifications-button []
(views/letsubs [notif-count [:activity.center/notifications-count]]
[react/view
[quo/button {:type :icon
:style {:margin-left 10}
:accessibility-label "notifications-button"
:on-press #(do
(re-frame/dispatch [:get-activity-center-notifications])
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
(re-frame/dispatch [:navigate-to :notifications-center]))
:theme :icon}
:main-icons/notification]
(when (pos? notif-count)
[react/view {:style (merge (tabs.styles/counter-public-container) {:top 5 :right 5})
:pointer-events :none}
[react/view {:style tabs.styles/counter-public
:accessibility-label :notifications-unread-badge}]])]))
(defn home []
[react/keyboard-avoiding-view {:style styles/home-container}
[react/keyboard-avoiding-view {:style {:flex 1}}
[topbar/topbar {:title (i18n/label :t/chat)
:navigation :none
:right-component [connectivity/connectivity-button]}]
:right-component [react/view {:flex-direction :row :margin-right 16}
[connectivity/connectivity-button]
[notifications-button]]}]
[chats-list]
[plus-button]])

View File

@ -8,7 +8,6 @@
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[quo.core :as quo]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.screens.home.styles :as styles]
[status-im.ui.components.icons.icons :as icons]
[status-im.utils.contenthash :as contenthash]
@ -137,55 +136,49 @@
:height 15
:margin-right 2}})
(defn home-list-item [home-item]
(defn home-list-item [home-item opts]
(let [{:keys [chat-id chat-name color online group-chat
public? timestamp last-message muted]}
home-item
private-group? (and group-chat (not public?))
public-group? (and group-chat public?)]
[quo/list-item
{:icon [chat-icon.screen/chat-icon-view-chat-list
chat-id group-chat chat-name color online false]
:title [react/view {:flex-direction :row
:flex 1}
[react/view {:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
(cond
muted
[icons/icon :main-icons/tiny-muted (assoc (icon-style) :color colors/gray)]
private-group?
[icons/icon :main-icons/tiny-group (icon-style)]
public-group?
[icons/icon :main-icons/tiny-public (icon-style)]
:else
[icons/icon :main-icons/tiny-new-contact (icon-style)])
[quo/text {:weight :medium
:color (when muted :secondary)
:accessibility-label :chat-name-text
:ellipsize-mode :tail
:number-of-lines 1}
(if group-chat
(utils/truncate-str chat-name 30)
;; This looks a bit odd, but I would like only to subscribe
;; if it's a one-to-one. If wrapped in a component styling
;; won't be applied correctly.
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))]]
[message-timestamp (if (pos? (:whisper-timestamp last-message))
(:whisper-timestamp last-message)
timestamp)]]
:title-accessibility-label :chat-name-text
:subtitle [react/view {:flex-direction :row}
[react/view {:flex 1}
[message-content-text (select-keys last-message [:content
:content-type
:community-id])]]
[unviewed-indicator home-item]]
:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[sheets/actions home-item])}])}]))
(merge {:icon [chat-icon.screen/chat-icon-view-chat-list
chat-id group-chat chat-name color online false]
:title [react/view {:flex-direction :row
:flex 1}
[react/view {:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
(cond
muted
[icons/icon :main-icons/tiny-muted (assoc (icon-style) :color colors/gray)]
private-group?
[icons/icon :main-icons/tiny-group (icon-style)]
public-group?
[icons/icon :main-icons/tiny-public (icon-style)]
:else
[icons/icon :main-icons/tiny-new-contact (icon-style)])
[quo/text {:weight :medium
:color (when muted :secondary)
:accessibility-label :chat-name-text
:ellipsize-mode :tail
:number-of-lines 1}
(if group-chat
(utils/truncate-str chat-name 30)
;; This looks a bit odd, but I would like only to subscribe
;; if it's a one-to-one. If wrapped in a component styling
;; won't be applied correctly.
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))]]
[message-timestamp (if (pos? (:whisper-timestamp last-message))
(:whisper-timestamp last-message)
timestamp)]]
:title-accessibility-label :chat-name-text
:subtitle [react/view {:flex-direction :row}
[react/view {:flex 1}
[message-content-text (select-keys last-message [:content
:content-type
:community-id])]]
[unviewed-indicator home-item]]}
opts)]))

View File

@ -0,0 +1,100 @@
(ns status-im.ui.screens.notifications-center.views
(:require [status-im.ui.components.react :as react]
[status-im.ui.components.topbar :as topbar]
[status-im.i18n.i18n :as i18n]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[re-frame.core :as re-frame]
[quo.core :as quo]
[status-im.ui.components.colors :as colors]
[reagent.core :as reagent]
[status-im.ui.components.toolbar :as toolbar]
[clojure.string :as string]))
(def selecting (reagent/atom nil))
(def select-all (reagent/atom nil))
(def selected-items (reagent/atom #{}))
(defn render-fn [{:keys [id] :as home-item}]
(when id
(let [selected (get @selected-items id)
on-change (fn []
(swap! selected-items #(if selected (disj % id) (conj % id))))]
[react/view {:flex-direction :row :flex 1 :align-items :center}
(when @selecting
[react/view {:padding-left 16}
[quo/checkbox {:value (or @select-all selected)
:disabled @select-all
:on-change on-change}]])
[react/view {:flex 1}
[inner-item/home-list-item
home-item
{:on-press (fn []
(if @selecting
(on-change)
(re-frame/dispatch [:accept-activity-center-notification-and-open-chat id])))
:on-long-press #(do (reset! selecting true)
(swap! selected-items conj id))}]]])))
(defn filter-item []
[react/view {:padding-vertical 8 :border-bottom-width 1 :border-bottom-color colors/gray-lighter}
[react/view {:align-items :center :justify-content :space-between :padding-horizontal 16 :flex-direction :row}
(if @selecting
[react/view {:flex-direction :row}
[quo/checkbox {:value @select-all
:on-change #(do
(reset! selected-items #{})
(swap! select-all not))}]
[react/text {:style {:color colors/gray :margin-left 20}}
(str (if @select-all (i18n/label :t/all) (count @selected-items))
" " (string/lower-case (i18n/label :t/selected)))]]
[quo/button {:type :secondary
:on-press #(reset! selecting true)}
(i18n/label :t/select)])
(when @selecting
[quo/button {:type :secondary
:on-press #(do (reset! selecting false)
(reset! select-all false)
(reset! selected-items #{}))}
(i18n/label :t/cancel)])]])
(defn reset-state []
(reset! selecting nil)
(reset! select-all nil)
(reset! selected-items #{}))
(defn toolbar-action [accept]
(if accept
(if @select-all
(re-frame/dispatch [:accept-all-activity-center-notifications])
(re-frame/dispatch [:accept-activity-center-notifications @selected-items]))
(if @select-all
(re-frame/dispatch [:dismiss-all-activity-center-notifications])
(re-frame/dispatch [:dismiss-activity-center-notifications @selected-items])))
(reset-state))
(defn center []
(let [{:keys [notifications]} @(re-frame/subscribe [:activity.center/notifications])]
[react/keyboard-avoiding-view {:style {:flex 1}}
[topbar/topbar {:navigation {:on-press #(do
(reset-state)
(re-frame/dispatch [:close-notifications-center])
(re-frame/dispatch [:navigate-back]))}
:title (i18n/label :t/activity)}]
[filter-item]
[list/flat-list
{:key-fn #(or (:chat-id %) (:id %))
:on-end-reached #(re-frame/dispatch [:get-activity-center-notifications])
:keyboard-should-persist-taps :always
:data notifications
:render-fn render-fn}]
(when (or @select-all (> (count @selected-items) 0))
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary
:theme :negative
:on-press #(toolbar-action false)}
(i18n/label :t/reject-and-delete)]
:right [quo/button {:type :secondary
:on-press #(toolbar-action true)}
(i18n/label :t/accept-and-add)]}])]))

View File

@ -16,18 +16,18 @@
(views/defview messages-from-contacts-only []
(views/letsubs [{:keys [messages-from-contacts-only]} [:multiaccount]]
[react/view {:flex 1}
[topbar/topbar {:title (i18n/label :t/accept-new-chats-from)}]
[react/view {:margin-top 8}
[quo/list-item
{:active (not messages-from-contacts-only)
:accessory :radio
:title (i18n/label :t/anyone)
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched false])}]
[quo/list-item
{:active messages-from-contacts-only
:accessory :radio
:title (i18n/label :t/contacts)
:subtitle (i18n/label :t/messages-from-contacts-only-subtitle)
:subtitle-max-lines 4
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched true])}]]]))
[react/view {:flex 1}
[topbar/topbar {:title (i18n/label :t/accept-new-chats-from)}]
[react/view {:margin-top 8}
[quo/list-item
{:active (not messages-from-contacts-only)
:accessory :radio
:title (i18n/label :t/anyone)
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched false])}]
[quo/list-item
{:active messages-from-contacts-only
:accessory :radio
:title (i18n/label :t/contacts)
:subtitle (i18n/label :t/messages-from-contacts-only-subtitle)
:subtitle-max-lines 4
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched true])}]]]))

View File

@ -20,27 +20,27 @@
webview-allow-permission-requests?]} [:multiaccount]
supported-biometric-auth [:supported-biometric-auth]
auth-method [:auth-method]]
[react/view {:flex 1 :background-color colors/white}
[topbar/topbar {:title (i18n/label :t/privacy-and-security)}]
[react/scroll-view {:padding-vertical 8}
[quo/list-header (i18n/label :t/security)]
[quo/list-item {:size :small
:title (i18n/label :t/back-up-seed-phrase)
:accessibility-label :back-up-recovery-phrase-button
:disabled (not mnemonic)
:chevron (boolean mnemonic)
:accessory (when mnemonic [components.common/counter {:size 22} 1])
:on-press #(re-frame/dispatch [:navigate-to :backup-seed])}]
(when supported-biometric-auth
[quo/list-item
{:size :small
:title (str (i18n/label :t/lock-app-with) " " (biometric/get-label supported-biometric-auth))
:active (= auth-method "biometric")
:accessibility-label :biometric-auth-settings-switch
:accessory :switch
:on-press #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched
((complement boolean) (= auth-method "biometric"))])}])
[separator]
[react/view {:flex 1 :background-color colors/white}
[topbar/topbar {:title (i18n/label :t/privacy-and-security)}]
[react/scroll-view {:padding-vertical 8}
[quo/list-header (i18n/label :t/security)]
[quo/list-item {:size :small
:title (i18n/label :t/back-up-seed-phrase)
:accessibility-label :back-up-recovery-phrase-button
:disabled (not mnemonic)
:chevron (boolean mnemonic)
:accessory (when mnemonic [components.common/counter {:size 22} 1])
:on-press #(re-frame/dispatch [:navigate-to :backup-seed])}]
(when supported-biometric-auth
[quo/list-item
{:size :small
:title (str (i18n/label :t/lock-app-with) " " (biometric/get-label supported-biometric-auth))
:active (= auth-method "biometric")
:accessibility-label :biometric-auth-settings-switch
:accessory :switch
:on-press #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched
((complement boolean) (= auth-method "biometric"))])}])
[separator]
;; TODO - uncomment when implemented
;; {:size :small
;; :title (i18n/label :t/change-password)
@ -49,51 +49,51 @@
;; :title (i18n/label :t/change-passcode)
;; :chevron true}
[quo/list-header (i18n/label :t/privacy)]
[quo/list-item {:size :small
:title (i18n/label :t/set-dapp-access-permissions)
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
:accessibility-label :dapps-permissions-button
:chevron true}]
[quo/list-item {:size :small
:title (if platform/android?
(i18n/label :t/hide-content-when-switching-apps)
(i18n/label :t/hide-content-when-switching-apps-ios))
:container-margin-bottom 8
:active preview-privacy?
:accessory :switch
:on-press #(re-frame/dispatch
[:multiaccounts.ui/preview-privacy-mode-switched
((complement boolean) preview-privacy?)])}]
[quo/list-item {:size :small
:title (i18n/label :t/chat-link-previews)
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :link-previews-settings])
:accessibility-label :chat-link-previews}]
[quo/list-item {:size :small
:title (i18n/label :t/accept-new-chats-from)
:chevron true
:accessory :text
:accessory-text (i18n/label (if messages-from-contacts-only
:t/contacts
:t/anyone))
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
:accessibility-label :accept-new-chats-from}]
(when platform/android?
[quo/list-item {:size :small
:title (i18n/label :t/webview-camera-permission-requests)
:active webview-allow-permission-requests?
:accessory :switch
:subtitle (i18n/label :t/webview-camera-permission-requests-subtitle)
:subtitle-max-lines 2
:on-press #(re-frame/dispatch
[:multiaccounts.ui/webview-permission-requests-switched
((complement boolean) webview-allow-permission-requests?)])}])
[separator]
[quo/list-item
{:size :small
:theme :negative
:title (i18n/label :t/delete-my-profile)
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
:accessibility-label :dapps-permissions-button
:chevron true}]]]))
[quo/list-header (i18n/label :t/privacy)]
[quo/list-item {:size :small
:title (i18n/label :t/set-dapp-access-permissions)
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
:accessibility-label :dapps-permissions-button
:chevron true}]
[quo/list-item {:size :small
:title (if platform/android?
(i18n/label :t/hide-content-when-switching-apps)
(i18n/label :t/hide-content-when-switching-apps-ios))
:container-margin-bottom 8
:active preview-privacy?
:accessory :switch
:on-press #(re-frame/dispatch
[:multiaccounts.ui/preview-privacy-mode-switched
((complement boolean) preview-privacy?)])}]
[quo/list-item {:size :small
:title (i18n/label :t/chat-link-previews)
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :link-previews-settings])
:accessibility-label :chat-link-previews}]
[quo/list-item {:size :small
:title (i18n/label :t/accept-new-chats-from)
:chevron true
:accessory :text
:accessory-text (i18n/label (if messages-from-contacts-only
:t/contacts
:t/anyone))
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
:accessibility-label :accept-new-chats-from}]
(when platform/android?
[quo/list-item {:size :small
:title (i18n/label :t/webview-camera-permission-requests)
:active webview-allow-permission-requests?
:accessory :switch
:subtitle (i18n/label :t/webview-camera-permission-requests-subtitle)
:subtitle-max-lines 2
:on-press #(re-frame/dispatch
[:multiaccounts.ui/webview-permission-requests-switched
((complement boolean) webview-allow-permission-requests?)])}])
[separator]
[quo/list-item
{:size :small
:theme :negative
:title (i18n/label :t/delete-my-profile)
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
:accessibility-label :dapps-permissions-button
:chevron true}]]]))

View File

@ -17,6 +17,7 @@
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
[status-im.ui.components.tabbar.styles :as tabbar.styles]
[status-im.ui.screens.stickers.views :as stickers]
[status-im.ui.screens.notifications-center.views :as notifications-center]
[status-im.utils.config :as config]))
(defonce stack (navigation/create-stack))
@ -42,6 +43,8 @@
:component stickers/packs}
{:name :stickers-pack
:component stickers/pack}
{:name :notifications-center
:component notifications-center/center}
;; Community
{:name :community
:component community/community}

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "feature/notification-center-2",
"commit-sha1": "6322d0c1ed9cee5f00eba53ad60daa47fc388944",
"src-sha256": "1ljcds0qfx2n2fm4in5ja12dfbkr0xi5y1h30hkzh1wr104d03gb"
"version": "v0.76.0",
"commit-sha1": "c739f73f497b2cc1f22be0a176683193766d5193",
"src-sha256": "1db355sqsaj9g2hdzs9db29azrf8s1mzp0x62a6sny9gyiwwl5vd"
}

View File

@ -1102,7 +1102,6 @@
"sharing-share": "Share",
"show-less": "Show less",
"show-more": "Show more",
"show-notifications": "Show notifications",
"show-qr": "Show QR code",
"show-transaction-data": "Show transaction data",
"sign-and-send": "Sign and send",
@ -1509,5 +1508,8 @@
"rpc-usage-filter": "Filter methods",
"rpc-usage-copy": "Copy",
"community-message-preview": "Invitation to join {{community-name}}",
"non-contacts": "Non contacts"
"non-contacts": "Non contacts",
"activity": "Activity",
"reject-and-delete": "Reject and delete",
"accept-and-add": "Accept and add"
}