mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-26 16:39:24 +00:00
[#11958] Add activity center
This commit is contained in:
parent
5bb849f9c1
commit
93ce02b547
@ -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}
|
||||
|
@ -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))))
|
||||
|
@ -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"
|
||||
|
27
src/status_im/data_store/activities.cljs
Normal file
27
src/status_im/data_store/activities.cljs
Normal 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)))
|
@ -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]
|
||||
|
@ -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" {}
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
|
118
src/status_im/notifications_center/core.cljs
Normal file
118
src/status_im/notifications_center/core.cljs
Normal 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)})
|
@ -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]
|
||||
|
@ -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")
|
||||
|
@ -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])))
|
@ -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]
|
||||
|
@ -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}
|
||||
|
@ -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)
|
||||
|
@ -89,7 +89,3 @@
|
||||
:background-color colors/gray
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def home-container
|
||||
(merge
|
||||
{:flex 1}))
|
||||
|
@ -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]])
|
||||
|
@ -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)]))
|
||||
|
100
src/status_im/ui/screens/notifications_center/views.cljs
Normal file
100
src/status_im/ui/screens/notifications_center/views.cljs
Normal 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)]}])]))
|
@ -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])}]]]))
|
||||
|
@ -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}]]]))
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user