chats list performance

Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
andrey 2021-09-03 09:45:57 +02:00
parent 6387bba9f5
commit 82b640abe1
No known key found for this signature in database
GPG Key ID: 89B67245FD2F0272
22 changed files with 351 additions and 461 deletions

View File

@ -15,7 +15,8 @@
[status-im.utils.types :as types]
[status-im.add-new.db :as new-public-chat.db]
[status-im.chat.models.loading :as loading]
[status-im.ui.screens.chat.state :as chat.state]))
[status-im.ui.screens.chat.state :as chat.state]
[clojure.set :as set]))
(defn chats []
(:chats (types/json->clj (js/require "./chats.js"))))
@ -44,11 +45,8 @@
([cofx chat-id]
(community-chat? (get-chat cofx chat-id))))
(defn active-chat?
([chat]
(:is-active chat))
([cofx chat-id]
(active-chat? (get-chat cofx chat-id))))
(defn active-chat? [cofx chat-id]
(not (nil? (get-chat cofx chat-id))))
(defn foreground-chat?
[{{:keys [current-chat-id view-id]} :db} chat-id]
@ -87,22 +85,10 @@
:color (rand-nth colors/chat-colors)
:chat-type constants/one-to-one-chat-type
:group-chat false
:is-active true
:timestamp now
:contacts #{chat-id}
:last-clock-value 0}))
(fx/defn ensure-chat
"Add chat to db and update"
[{:keys [db] :as cofx} {:keys [chat-id timeline?] :as chat-props}]
(let [chat (merge
(or (get (:chats db) chat-id)
(create-new-chat chat-id cofx))
chat-props)
new? (not (get-in db [:chats chat-id]))
public? (public-chat? chat)]
{:db (update-in db [:chats chat-id] merge chat)}))
(defn map-chats [{:keys [db] :as cofx}]
(fn [val]
(assoc
@ -119,13 +105,24 @@
(fx/defn ensure-chats
"Add chats to db and update"
[{:keys [db] :as cofx} chats]
(let [chats (map (map-chats cofx) chats)
filtered-chats (filter (filter-chats db) chats)]
{:db (update db :chats #(reduce
(fn [acc {:keys [chat-id] :as chat}]
(update acc chat-id merge chat))
%
chats))}))
(let [{:keys [all-chats chats-home-list removed-chats]}
(reduce (fn [acc {:keys [chat-id profile-public-key timeline? community-id active] :as chat}]
(if (not active)
(update acc :removed-chats conj chat-id)
(cond-> acc
(and (not profile-public-key) (not timeline?) (not community-id))
(update :chats-home-list conj chat-id)
:always
(assoc-in [:all-chats chat-id] chat))))
{:all-chats {}
:chats-home-list #{}
:removed-chats #{}}
(map (map-chats cofx) chats))]
{:db (-> db
(update :chats merge all-chats)
(update :chats-home-list set/union chats-home-list)
(update :chats #(apply dissoc % removed-chats))
(update :chats-home-list set/difference removed-chats))}))
(fx/defn clear-history
"Clears history of the particular chat"
@ -165,6 +162,7 @@
cofx
{:db (-> db
(assoc-in [:chats chat-id :is-active] false)
(update :chats-home-list disj chat-id)
(assoc-in [:current-chat-id] nil))
::json-rpc/call [{:method "wakuext_deactivateChat"
:params [{:id chat-id}]
@ -202,10 +200,16 @@
(when (not (= (:view-id db) :home))
(navigation/pop-to-root-tab :chat-stack))))
(fx/defn show-more-chats
{:events [:chat.ui/show-more-chats]}
[{:keys [db]}]
(when (< (:home-items-show-number db) (count (:chats db)))
{:db (update db :home-items-show-number + 40)}))
(fx/defn preload-chat-data
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
{:events [:chat.ui/preload-chat-data]}
[{:keys [db] :as cofx} chat-id]
[cofx chat-id]
(loading/load-messages cofx chat-id))
(fx/defn navigate-to-chat
@ -217,6 +221,8 @@
(fn [{:keys [db]}]
{:db (assoc db :current-chat-id chat-id :ignore-close-chat true)})
(preload-chat-data chat-id)
#(when (group-chat? cofx chat-id)
(loading/load-chat % chat-id))
#(when-not dont-reset?
(navigation/change-tab % :chat))
#(when-not dont-reset?
@ -225,7 +231,7 @@
(fx/defn handle-clear-history-response
{:events [::history-cleared]}
[{:keys [db] :as cofx} chat-id response]
[{:keys [db]} chat-id response]
(let [chat (chats-store/<-rpc (first (:chats response)))]
{:db (assoc-in db [:chats chat-id] chat)}))
@ -233,7 +239,9 @@
{:events [::one-to-one-chat-created]}
[{:keys [db]} chat-id response]
(let [chat (chats-store/<-rpc (first (:chats response)))]
{:db (assoc-in db [:chats chat-id] chat)
{:db (-> db
(assoc-in [:chats chat-id] chat)
(update :chats-home-list conj chat-id))
:dispatch [:chat.ui/navigate-to-chat chat-id]}))
(fx/defn navigate-to-user-pinned-messages
@ -261,14 +269,16 @@
(fx/defn handle-public-chat-created
{:events [::public-chat-created]}
[{:keys [db] :as cofx} chat-id {:keys [dont-navigate?]} response]
[{:keys [db]} chat-id {:keys [dont-navigate?]} response]
(let [chat (chats-store/<-rpc (first (:chats response)))
db-with-chat {:db (assoc-in db [:chats chat-id] chat)}]
db-with-chat {:db (-> db
(assoc-in [:chats chat-id] chat)
(update :chats-home-list conj chat-id))}]
(if dont-navigate?
db-with-chat
(assoc db-with-chat :dispatch [:chat.ui/navigate-to-chat chat-id]))))
(fx/defn create-public-chat-go [cofx chat-id opts]
(fx/defn create-public-chat-go [_ chat-id opts]
{::json-rpc/call [{:method "wakuext_createPublicChat"
:params [{:id chat-id}]
:on-success #(re-frame/dispatch [::public-chat-created chat-id opts %])

View File

@ -21,22 +21,35 @@
(fx/defn update-chats-in-app-db
{:events [:chats-list/load-success]}
[{:keys [db]} new-chats]
(let [old-chats (:chats db)
chats (reduce (fn [acc {:keys [chat-id] :as chat}]
(assoc acc chat-id chat))
{}
new-chats)
chats (merge old-chats chats)]
{:db (assoc db :chats chats
[{:keys [db]} ^js new-chats-js]
(let [{:keys [all-chats chats-home-list]}
(reduce (fn [acc ^js chat-js]
(let [{:keys [chat-id profile-public-key timeline? community-id] :as chat}
(data-store.chats/<-rpc-js chat-js)]
(cond-> acc
(and (not profile-public-key) (not timeline?) (not community-id))
(update :chats-home-list conj chat-id)
:always
(assoc-in [:all-chats chat-id] chat))))
{:all-chats {}
:chats-home-list #{}}
new-chats-js)]
{:db (assoc db :chats all-chats
:chats-home-list chats-home-list
:chats/loading? false)}))
(fx/defn initialize-chats
"Initialize persisted chats on startup"
[cofx]
(data-store.chats/fetch-chats-rpc cofx {:on-success
#(re-frame/dispatch
[:chats-list/load-success %])}))
(fx/defn load-chat-success
{:events [:chats-list/load-chat-success]}
[{:keys [db]} ^js chat]
(let [{:keys [chat-id] :as chat} (data-store.chats/<-rpc chat)]
{:db (update-in db [:chats chat-id] merge chat)}))
(fx/defn load-chat
[_ chat-id]
{::json-rpc/call [{:method (json-rpc/call-ext-method "chat")
:params [chat-id]
:on-success #(re-frame/dispatch [:chats-list/load-chat-success %])
:on-failure #(log/error "failed to fetch chats" 0 -1 %)}]})
(fx/defn handle-failed-loading-messages
{:events [::failed-loading-messages]}

View File

@ -50,10 +50,7 @@
(is (= nil (get-in actual [:db :messages chat-id])))))
(testing "it sets a deleted-at-clock-value equal to the last message clock-value"
(let [actual (chat/remove-chat cofx chat-id)]
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
(testing "it sets the chat as inactive"
(let [actual (chat/remove-chat cofx chat-id)]
(is (= false (get-in actual [:db :chats chat-id :is-active])))))))
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))))
(deftest multi-user-chat?
(let [chat-id "1"]

View File

@ -6,43 +6,45 @@
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
(defn rpc->type [{:keys [chatType name] :as chat}]
(defn rpc->type [{:keys [chat-type name] :as chat}]
(cond
(or (= constants/public-chat-type chatType)
(= constants/profile-chat-type chatType)
(= constants/timeline-chat-type chatType)) (assoc chat
:chat-name (str "#" name)
:public? true
:group-chat true
:timeline? (= constants/timeline-chat-type chatType))
(= constants/community-chat-type chatType) (assoc chat
:chat-name name
:group-chat true)
(= constants/private-group-chat-type chatType) (assoc chat
:chat-name name
:public? false
:group-chat true)
(or (= constants/public-chat-type chat-type)
(= constants/profile-chat-type chat-type)
(= constants/timeline-chat-type chat-type)) (assoc chat
:chat-name (str "#" name)
:public? true
:group-chat true
:timeline? (= constants/timeline-chat-type chat-type))
(= constants/community-chat-type chat-type) (assoc chat
:chat-name name
:group-chat true)
(= constants/private-group-chat-type chat-type) (assoc chat
:chat-name name
:public? false
:group-chat true)
:else (assoc chat :public? false :group-chat false)))
(defn- unmarshal-members [{:keys [members chatType] :as chat}]
(defn members-reducer [acc member]
(cond-> acc
(:admin member)
(update :admins conj (:id member))
(:joined member)
(update :members-joined conj (:id member))
:always
(update :contacts conj (:id member))))
(defn- unmarshal-members [{:keys [members chat-type] :as chat}]
(cond
(= constants/public-chat-type chatType) (assoc chat
:contacts #{}
:admins #{}
:members-joined #{})
(= constants/private-group-chat-type chatType) (merge chat
(reduce (fn [acc member]
(cond-> acc
(:admin member)
(update :admins conj (:id member))
(:joined member)
(update :members-joined conj (:id member))
:always
(update :contacts conj (:id member))))
{:admins #{}
:members-joined #{}
:contacts #{}}
members))
(= constants/public-chat-type chat-type) (assoc chat
:contacts #{}
:admins #{}
:members-joined #{})
(= constants/private-group-chat-type chat-type) (merge chat
(reduce members-reducer
{:admins #{}
:members-joined #{}
:contacts #{}}
members))
:else
(assoc chat
:contacts #{(:id chat)}
@ -51,8 +53,6 @@
(defn <-rpc [chat]
(-> chat
rpc->type
unmarshal-members
(clojure.set/rename-keys {:id :chat-id
:communityId :community-id
:syncedFrom :synced-from
@ -63,15 +63,42 @@
:unviewedMessagesCount :unviewed-messages-count
:unviewedMentionsCount :unviewed-mentions-count
:lastMessage :last-message
:active :is-active
:lastClockValue :last-clock-value
:invitationAdmin :invitation-admin
:profile :profile-public-key})
rpc->type
unmarshal-members
(update :last-message #(when % (messages/<-rpc %)))
(dissoc :members)))
(fx/defn fetch-chats-rpc [cofx {:keys [on-success]}]
{::json-rpc/call [{:method (json-rpc/call-ext-method "chats")
(defn <-rpc-js [^js chat]
(-> {:name (.-name chat)
:description (.-description chat)
:color (.-color chat)
:timestamp (.-timestamp chat)
:alias (.-alias chat)
:identicon (.-identicon chat)
:muted (.-muted chat)
:joined (.-joined chat)
:chat-id (.-id chat)
:community-id (.-communityId chat)
:synced-from (.-syncedFrom chat)
:synced-to (.-syncedTo chat)
:deleted-at-clock-value (.-deletedAtClockValue chat)
:chat-type (.-chatType chat)
:unviewed-messages-count (.-unviewedMessagesCount chat)
:unviewed-mentions-count (.-unviewedMentionsCount chat)
:last-message {:content {:text (.-text chat)}
:content-type (.-contentType chat)}
:last-clock-value (.-lastClockValue chat)
:profile-public-key (.-profile chat)}
rpc->type
unmarshal-members))
(fx/defn fetch-chats-rpc [_ {:keys [on-success]}]
{::json-rpc/call [{:method (json-rpc/call-ext-method "chatsPreview")
:params []
:on-success #(on-success (map <-rpc %))
:js-response true
:on-success #(on-success ^js %)
:on-failure #(log/error "failed to fetch chats" 0 -1 %)}]})

View File

@ -22,7 +22,6 @@
:lastClockValue 10
:membershipUpdateEvents :events
:unviewedMessagesCount 2
:active true
:timestamp 2}
expected-chat {:public? false
:group-chat true
@ -37,7 +36,6 @@
:name "name"
:membership-update-events :events
:unviewed-messages-count 2
:is-active true
:chat-id "chat-id"
:timestamp 2}]
(testing "from-rpc"

View File

@ -33,14 +33,14 @@
:nickname :localNickname})))
(fx/defn fetch-contacts-rpc
[cofx on-success]
[_ on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "contacts")
:params []
:on-success #(on-success (map <-rpc %))
:on-failure #(log/error "failed to fetch contacts" %)}]})
(fx/defn save-contact
[cofx {:keys [public-key] :as contact} on-success]
[_ {:keys [public-key] :as contact} on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "saveContact")
:params [(->rpc contact)]
:on-success #(do
@ -49,7 +49,7 @@
(on-success)))
:on-failure #(log/error "failed to save contact" public-key %)}]})
(fx/defn block [cofx contact on-success]
(fx/defn block [_ contact on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "blockContact")
:params [(->rpc contact)]
:on-success on-success

View File

@ -27,6 +27,8 @@
:chat/cooldown-enabled? false
:chat/last-outgoing-message-sent-at 0
:chat/spam-messages-frequency 0
:chats-home-list #{}
:home-items-show-number 20
:tooltips {}
:dimensions/window (dimensions/window)
:registry {}

View File

@ -72,8 +72,9 @@
"wakuext_removeFilters" {}
"wakuext_sendContactUpdate" {}
"wakuext_sendContactUpdates" {}
"wakuext_chats" {}
"wakuext_chatsPreview" {}
"wakuext_activeChats" {}
"wakuext_chat" {}
"wakuext_addSystemMessages" {}
"wakuext_deleteMessagesFrom" {}
"wakuext_deleteMessagesByChatID" {}

View File

@ -13,7 +13,7 @@
(fx/defn navigate-chat-updated
{:events [:navigate-chat-updated]}
[cofx chat-id]
(when (get-in cofx [:db :chats chat-id :is-active])
(when (get-in cofx [:db :chats chat-id])
(fx/merge cofx
{:dispatch-later [{:ms 1000 :dispatch [:chat.ui/navigate-to-chat chat-id]}]}
(navigation/pop-to-root-tab :chat-stack))))
@ -59,7 +59,7 @@
(fx/defn create-from-link
[cofx {:keys [chat-id invitation-admin chat-name]}]
(if (get-in cofx [:db :chats chat-id :is-active])
(if (get-in cofx [:db :chats chat-id])
{:dispatch-n [[:accept-all-activity-center-notifications-from-chat chat-id]
[:chat.ui/navigate-to-chat chat-id false]]}
{::json-rpc/call [{:method (json-rpc/call-ext-method "createGroupChatFromInvitation")

View File

@ -1,7 +1,6 @@
(ns status-im.multiaccounts.login.core
(:require [re-frame.core :as re-frame]
[status-im.anon-metrics.core :as anon-metrics]
[status-im.chat.models.loading :as chat.loading]
[status-im.contact.core :as contact]
[status-im.utils.config :as config]
[status-im.data-store.settings :as data-store.settings]
@ -37,7 +36,8 @@
[status-im.async-storage.core :as async-storage]
[status-im.notifications-center.core :as notifications-center]
[status-im.navigation :as navigation]
[status-im.signing.eip1559 :as eip1559]))
[status-im.signing.eip1559 :as eip1559]
[status-im.data-store.chats :as data-store.chats]))
(re-frame/reg-fx
::initialize-communities-enabled
@ -250,10 +250,19 @@
(.catch (fn [_]
(log/error "Failed to initialize wallet"))))))
(fx/defn initialize-browser [_]
{::json-rpc/call
[{:method "browsers_getBrowsers"
:on-success #(re-frame/dispatch [::initialize-browsers %])}
{:method "browsers_getBookmarks"
:on-success #(re-frame/dispatch [::initialize-bookmarks %])}
{:method "permissions_getDappPermissions"
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}]})
(fx/defn initialize-appearance [cofx]
{::multiaccounts/switch-theme (get-in cofx [:db :multiaccount :appearance])})
(fx/defn get-group-chat-invitations [cofx]
(fx/defn get-group-chat-invitations [_]
{::json-rpc/call
[{:method (json-rpc/call-ext-method "getGroupChatInvitations")
:on-success #(re-frame/dispatch [::initialize-invitations %])}]})
@ -279,19 +288,36 @@
(fx/defn get-settings-callback
{:events [::get-settings-callback]}
[{:keys [db] :as cofx} settings]
(let [{:keys [notifications-enabled?]
:networks/keys [current-network networks]
(let [{:networks/keys [current-network networks]
:as settings}
(data-store.settings/rpc->settings settings)
multiaccount (dissoc settings :networks/current-network :networks/networks)
multiaccount (dissoc settings :networks/current-network :networks/networks)]
(fx/merge cofx
{:db (-> db
(dissoc :multiaccounts/login)
(assoc :networks/current-network current-network
:networks/networks networks
:multiaccount multiaccount))}
(data-store.chats/fetch-chats-rpc
{:on-success
#(do (re-frame/dispatch [:chats-list/load-success %])
(re-frame/dispatch [::get-chats-callback settings]))})
(acquisition/login)
(initialize-appearance)
(initialize-communities-enabled)
(get-node-config)
(communities/fetch)
(logging/set-log-level (:log-level multiaccount))
(notifications-center/get-activity-center-notifications-count))))
(fx/defn get-chats-callback
{:events [::get-chats-callback]}
[{:keys [db] :as cofx} settings]
(let [{:keys [notifications-enabled?]
:networks/keys [current-network networks]} settings
network-id (str (get-in networks [current-network :config :NetworkId]))]
(fx/merge cofx
(cond-> {:db (-> db
(dissoc :multiaccounts/login)
(assoc :networks/current-network current-network
:networks/networks networks
:multiaccount multiaccount))
::eip1559/check-eip1559-activation
(cond-> {::eip1559/check-eip1559-activation
{:network-id network-id
:on-enabled #(log/info "eip1550 is activated")
:on-disabled #(log/info "eip1559 is not activated")}
@ -301,24 +327,17 @@
accounts custom-tokens favourites]))}
notifications-enabled?
(assoc ::notifications/enable nil))
(acquisition/login)
(initialize-appearance)
(transport/start-messenger)
(initialize-communities-enabled)
(initialize-transactions-management-enabled)
(check-network-version network-id)
(chat.loading/initialize-chats)
(get-node-config)
(communities/fetch)
(contact/initialize-contacts)
(stickers/init-stickers-packs)
(initialize-browser)
(mobile-network/on-network-status-change)
(get-group-chat-invitations)
(logging/set-log-level (:log-level multiaccount))
(multiaccounts/get-profile-picture)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)
(notifications-center/get-activity-center-notifications-count))))
(link-preview/request-link-preview-whitelist))))
(defn get-new-auth-method [auth-method save-password?]
(when save-password?
@ -358,13 +377,7 @@
(fx/merge cofx
{:db (assoc db :chats/loading? true)
::json-rpc/call
[{:method "browsers_getBrowsers"
:on-success #(re-frame/dispatch [::initialize-browsers %])}
{:method "browsers_getBookmarks"
:on-success #(re-frame/dispatch [::initialize-bookmarks %])}
{:method "permissions_getDappPermissions"
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}
{:method "settings_getSettings"
[{:method "settings_getSettings"
:on-success #(do (re-frame/dispatch [::get-settings-callback %])
(redirect-to-root db))}]}
(notifications/load-notification-preferences)
@ -384,7 +397,7 @@
(fx/merge cofx
{:db (-> db
(dissoc :multiaccounts/login)
(assoc :tos/next-root :onboarding-notification)
(assoc :tos/next-root :onboarding-notification :chats/loading? false)
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
:dispatch-later [{:ms 2000 :dispatch [::initialize-wallet
accounts nil nil
@ -392,8 +405,9 @@
true]}]}
(finish-keycard-setup)
(transport/start-messenger)
(chat.loading/initialize-chats)
(communities/fetch)
(data-store.chats/fetch-chats-rpc
{:on-success #(re-frame/dispatch [:chats-list/load-success %])})
(initialize-communities-enabled)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)
@ -407,6 +421,22 @@
(defn- keycard-setup? [cofx]
(boolean (get-in cofx [:db :keycard :flow])))
(defn on-login-update-db [db login-only? now]
(-> db
(dissoc :connectivity/ui-status-properties)
(update :keycard dissoc :from-key-storage-and-migration?)
(update :keycard dissoc
:on-card-read
:card-read-in-progress?
:pin
:multiaccount)
(assoc :tos-accept-next-root
(if login-only?
:chat-stack
:onboarding-notification))
(assoc :logged-in-since now)
(assoc :view-id :home)))
(fx/defn multiaccount-login-success
[{:keys [db now] :as cofx}]
(let [{:keys [key-uid password save-password? creating?]}
@ -424,20 +454,7 @@
"login-only?" login-only?
"recovered-account?" recovered-account?)
(fx/merge cofx
{:db (-> db
(dissoc :connectivity/ui-status-properties)
(update :keycard dissoc :from-key-storage-and-migration?)
(update :keycard dissoc
:on-card-read
:card-read-in-progress?
:pin
:multiaccount)
(assoc :tos-accept-next-root
(if login-only?
:chat-stack
:onboarding-notification))
(assoc :logged-in-since now)
(assoc :view-id :home))
{:db (on-login-update-db db login-only? now)
::json-rpc/call
[{:method "web3_clientVersion"
:on-success #(re-frame/dispatch [::initialize-web3-client-version %])}]}

View File

@ -29,7 +29,6 @@
:membership-updates ()
:unviewed-messages-count 0
:last-message-content-type "text/plain"
:is-active true
:last-message-content {:chat-id "status" :text "darn typos...! "}
:debug? false
:group-chat true
@ -48,7 +47,6 @@
:membership-updates ()
:unviewed-messages-count 0
:last-message-content-type "text/plain"
:is-active true
:last-message-content {:chat-id "0x04173f7cdea0076a7998abb674cc79fe61337c42db77043c01d5b0f3e3ac1e5a45bca0c93bb9f3c3d38b7cc9a7337cd64f9f9b2114fe4bbdfe1ae2633ba14d8c9c"
:text "Hey"}
:debug? false
@ -68,7 +66,6 @@
:membership-updates ()
:unviewed-messages-count 0
:last-message-content-type "text/plain"
:is-active true
:last-message-content {:chat-id "0x04173f7cdea0076a7998abb674cc79fe61337c42db77043c01d5b0f3e3ac1e5a45bca0c93bb9f3c3d38b7cc9a7337cd64f9f9b2114fe4bbdfe1ae2633ba14d8c9c"
:text "Djndjd"}
:debug? false

View File

@ -68,6 +68,7 @@
{:id :tabs-stack
:options (merge (default-root)
{:bottomTabs {:titleDisplayMode :alwaysHide
:tabsAttachMode :onSwitchToTab
:backgroundColor colors/white}})
:children [;CHAT STACK
{:stack {:id :chat-stack

View File

@ -82,6 +82,7 @@
(reg-root-key-sub :logged-in-since :logged-in-since)
(reg-root-key-sub :link-previews-whitelist :link-previews-whitelist)
(reg-root-key-sub :app-state :app-state)
(reg-root-key-sub :home-items-show-number :home-items-show-number)
;;NOTE this one is not related to ethereum network
;; it is about cellular network/ wifi network
@ -120,6 +121,8 @@
(reg-root-key-sub :group-chat/invitations :group-chat/invitations)
(reg-root-key-sub :chats/mention-suggestions :chats/mention-suggestions)
(reg-root-key-sub :chat/inputs-with-mentions :chat/inputs-with-mentions)
(reg-root-key-sub :chats-home-list :chats-home-list)
;;browser
(reg-root-key-sub :browsers :browser/browsers)
(reg-root-key-sub :browser/options :browser/options)
@ -771,17 +774,17 @@
(re-frame/reg-sub
:chats/chat
:<- [:chats/active-chats]
:<- [::chats]
(fn [chats [_ chat-id]]
(get chats chat-id)))
(re-frame/reg-sub
:chats/by-community-id
:<- [:chats/active-chats]
:<- [::chats]
(fn [chats [_ community-id]]
(->> chats
(keep (fn [[_ chat]]
(when (= (:community-id chat) community-id)
(when (and (= (:community-id chat) community-id))
chat)))
(sort-by :timestamp >))))
@ -840,15 +843,11 @@
(get ui-props prop)))
(re-frame/reg-sub
:chats/active-chats
:chats/home-list-chats
:<- [::chats]
(fn [chats]
(reduce-kv (fn [acc id {:keys [is-active profile-public-key timeline?] :as chat}]
(if (and is-active (not profile-public-key) (not timeline?))
(assoc acc id chat)
acc))
{}
chats)))
:<- [:chats-home-list]
(fn [[chats active-chats]]
(map #(get chats %) active-chats)))
(re-frame/reg-sub
:chat-by-id
@ -1180,17 +1179,17 @@
(re-frame/reg-sub
:chats/unread-messages-number
:<- [:chats/active-chats]
:<- [:chats/home-list-chats]
(fn [chats _]
(reduce-kv (fn [{:keys [public other]} _ {:keys [unviewed-messages-count public?] :as chat}]
(if (or public? (chat.models/community-chat? chat))
{:public (+ public unviewed-messages-count)
:other other}
{:other (+ other unviewed-messages-count)
:public public}))
{:public 0
:other 0}
chats)))
(reduce (fn [{:keys [public other]} {:keys [unviewed-messages-count public?] :as chat}]
(if (or public? (chat.models/community-chat? chat))
{:public (+ public unviewed-messages-count)
:other other}
{:other (+ other unviewed-messages-count)
:public public}))
{:public 0
:other 0}
chats)))
(re-frame/reg-sub
:chats/cooldown-enabled?
@ -1497,7 +1496,8 @@
:<- [:search/filtered-chats]
:<- [:communities/communities]
:<- [:view-id]
(fn [[search-filter filtered-chats communities view-id]]
:<- [:home-items-show-number]
(fn [[search-filter filtered-chats communities view-id home-items-show-number]]
(if (= view-id :home)
(let [communities-count (count communities)
chats-count (count filtered-chats)
@ -1511,7 +1511,7 @@
assoc :last? true)
communities)
res {:search-filter search-filter
:items (concat communities-with-separator filtered-chats)}]
:items (concat communities-with-separator (take home-items-show-number filtered-chats))}]
(reset! memo-home-items res)
res)
;;we want to keep data unchanged so react doesn't change component when we leave screen
@ -1843,17 +1843,18 @@
(re-frame/reg-sub
:activity.center/notifications-grouped-by-date
:<- [:activity.center/notifications]
:<- [::chats]
(fn [[{:keys [notifications]} chats]]
(let [supported-notifications (filter (fn [{:keys [type chat-id last-message]}]
(and
(or (and (= constants/activity-center-notification-type-one-to-one-chat type)
(not (nil? last-message)))
(= constants/activity-center-notification-type-private-group-chat type)
(= constants/activity-center-notification-type-reply type)
(= constants/activity-center-notification-type-mention type))
(get chats chat-id))) notifications)]
(group-notifications-by-date (map #(assoc % :timestamp (or (:timestamp %) (:timestamp (or (:message %) (:last-message %))))) supported-notifications)))))
(fn [{:keys [notifications]}]
(let [supported-notifications
(filter (fn [{:keys [type last-message]}]
(or (and (= constants/activity-center-notification-type-one-to-one-chat type)
(not (nil? last-message)))
(= constants/activity-center-notification-type-private-group-chat type)
(= constants/activity-center-notification-type-reply type)
(= constants/activity-center-notification-type-mention type)))
notifications)]
(group-notifications-by-date
(map #(assoc % :timestamp (or (:timestamp %) (:timestamp (or (:message %) (:last-message %)))))
supported-notifications)))))
;;WALLET TRANSACTIONS ==================================================================================================
@ -2458,7 +2459,7 @@
(re-frame/reg-sub
:search/filtered-chats
:<- [:chats/active-chats]
:<- [:chats/home-list-chats]
:<- [:contacts/contacts]
:<- [:search/home-filter]
(fn [[chats contacts search-filter]]
@ -2468,13 +2469,9 @@
(partial filter-chat
contacts
(string/lower-case search-filter))
(vals chats))
(vals chats))]
(sort-by :timestamp > (filter (fn [{:keys [community-id]}]
;; Ignore communities
(not community-id))
filtered-chats)))))
chats)
chats)]
(sort-by :timestamp > filtered-chats))))
(defn extract-currency-attributes [currency]
(let [{:keys [code display-name]} (val currency)]

View File

@ -235,11 +235,9 @@
(defn button []
(if-not @(re-frame/subscribe [::invite.events/enabled])
[rn/view {:style {:align-items :center}}
[rn/view {:style (:tiny spacing/padding-vertical)}
[quo/button {:on-press #(re-frame/dispatch [::invite.events/share-link nil])
:accessibility-label :invite-friends-button}
(i18n/label :t/invite-friends)]]]
[quo/button {:on-press #(re-frame/dispatch [::invite.events/share-link nil])
:accessibility-label :invite-friends-button}
(i18n/label :t/invite-friends)]
(let [pack @(re-frame/subscribe [::invite.events/default-reward])
tokens (transform-tokens pack)]
[rn/view {:style {:align-items :center

View File

@ -35,12 +35,12 @@
:error error}])
(defn render-topic [topic]
^{:key topic}
[react/touchable-highlight {:on-press #(start-chat topic)
:accessibility-label :chat-item}
[react/view {:padding-right 8 :padding-vertical 8}
[react/view {:border-color colors/gray-lighter :border-radius 36 :border-width 1 :padding-horizontal 8 :padding-vertical 5}
[react/text {:style {:color colors/blue :typography :main-medium}} (str "#" topic)]]]])
[react/view {:border-color colors/gray-lighter :border-radius 36 :border-width 1 :padding-horizontal 8
:padding-vertical 5 :margin-right 8 :margin-vertical 8}
[react/text {:style {:color colors/blue :typography :main-medium}}
(str "#" topic)]]])
(def lang-names {"es" "status-espanol"
"pt" "statusbrasil"

View File

@ -36,6 +36,7 @@
(def no-chats-text
{:margin-top 50
:margin-bottom 8
:margin-horizontal 16
:line-height 22
:text-align :center})

View File

@ -29,42 +29,40 @@
(defn home-tooltip-view []
[react/view (styles/chat-tooltip)
[react/view {:style {:flex-direction :row}}
[react/view {:flex 1}
[react/view {:style styles/empty-chats-header-container}
[react/view {:style {:width 66 :position :absolute :top -6 :background-color colors/white
:align-items :center}}
[react/image {:source (resources/get-image :empty-chats-header)
:style {:width 50 :height 50}}]]]
[react/touchable-highlight
{:style {:position :absolute :right 0 :top 0
:width 44 :height 44 :align-items :center :justify-content :center}
:on-press #(re-frame/dispatch [:multiaccounts.ui/hide-home-tooltip])
:accessibility-label :hide-home-button}
[icons/icon :main-icons/close-circle {:color colors/gray}]]]]
[react/view
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]]
[react/view {:style {:width 66 :position :absolute :top -6 :background-color colors/white
:align-items :center}}
[react/image {:source (resources/get-image :empty-chats-header)
:style {:width 50 :height 50}}]]
[react/touchable-highlight
{:style {:position :absolute :right 0 :top 0
:width 44 :height 44 :align-items :center :justify-content :center}
:on-press #(re-frame/dispatch [:multiaccounts.ui/hide-home-tooltip])
:accessibility-label :hide-home-button}
[icons/icon :main-icons/close-circle {:color colors/gray}]]
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]
[invite/button]
[react/view {:align-items :center}
[react/view {:align-items :center :margin-bottom 16}
[react/view {:style (styles/hr-wrapper)}]
[react/i18n-text {:style (styles/or-text) :key :or}]]
[react/view {:margin-top 16}
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :follow-your-interests}]
[react/view {:style styles/tags-wrapper}
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center}
(for [chat (new-public-chat/featured-public-chats)]
(new-public-chat/render-topic chat))]]
(when @(re-frame/subscribe [:communities/enabled?])
[react/view
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :join-a-community}]
[react/view {:style styles/tags-wrapper}
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center}
(for [community communities/featured]
(communities.views/render-featured-community community))]]])]])
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :follow-your-interests}]
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center
:margin-top 10
:margin-bottom 18}
(for [chat (new-public-chat/featured-public-chats)]
^{:key chat}
[new-public-chat/render-topic chat])]
(when @(re-frame/subscribe [:communities/enabled?])
[:<>
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :join-a-community}]
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center
:margin-top 10
:margin-bottom 18}
(for [community communities/featured]
[communities.views/render-featured-community community])]])])
(defn welcome-blank-page []
[react/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :center}}
@ -150,7 +148,7 @@
[list/flat-list
{:key-fn chat-list-key-fn
:getItemLayout get-item-layout
:initialNumToRender 5
:on-end-reached #(re-frame/dispatch [:chat.ui/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn render-fn

View File

@ -10,105 +10,37 @@
[status-im.ui.components.react :as react]
[status-im.ui.screens.home.styles :as styles]
[status-im.ui.components.icons.icons :as icons]
[status-im.utils.contenthash :as contenthash]
[status-im.utils.core :as utils]
[status-im.utils.datetime :as time]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]))
(defn mention-element [from]
@(re-frame/subscribe [:contacts/contact-name-by-identity from]))
(defn preview-label [label-key]
[react/text {:style styles/last-message-text
:accessibility-label :no-messages-text}
(i18n/label label-key)])
;; if truncated subheader text is too short we won't get ellipsize at the end of text
(def max-subheader-length 100)
(defn truncate-literal [literal]
(let [size (min max-subheader-length (.-length literal))]
{:components (.substring literal 0 size)
:length size}))
(defn add-parsed-to-subheader [acc {:keys [type destination literal children]}]
(let [result (case type
"paragraph"
(reduce
(fn [{:keys [_ length] :as acc-paragraph} parsed-child]
(if (>= length max-subheader-length)
(reduced acc-paragraph)
(add-parsed-to-subheader acc-paragraph parsed-child)))
{:components [react/text-class]
:length 0}
children)
"mention"
{:components [react/text-class [mention-element literal]]
:length 4} ;; we can't predict name length so take the smallest possible
"status-tag"
(truncate-literal (str "#" literal))
"link"
(truncate-literal destination)
(truncate-literal literal))]
{:components (conj (:components acc) (:components result))
:length (+ (:length acc) (:length result))}))
(def subheader-wrapper
[react/text-class {:style styles/last-message-text
:number-of-lines 1
:ellipsize-mode :tail
:accessibility-label :chat-message-text}])
(defn render-subheader
"Render the preview of a last message to a maximum of max-subheader-length characters"
[parsed-text]
(let [result
(reduce
(fn [{:keys [_ length] :as acc-text} new-text-chunk]
(if (>= length max-subheader-length)
(reduced acc-text)
(add-parsed-to-subheader acc-text new-text-chunk)))
{:components subheader-wrapper
:length 0}
parsed-text)]
(:components result)))
(defn message-content-text [{:keys [content content-type community-id]}]
[react/view {:position :absolute :left 72 :top 32 :right 80}
(defn message-content-text [{:keys [content content-type]} absolute]
[react/view (when absolute {:position :absolute :left 72 :top 32 :right 80})
(cond
(not (and content content-type))
[react/text {:style styles/last-message-text
:accessibility-label :no-messages-text}
(i18n/label :t/no-messages)]
[preview-label :t/no-messages]
(and (= constants/content-type-text content-type)
(not (string/blank? (:text content))))
[react/text-class {:style styles/last-message-text
:number-of-lines 1
:ellipsize-mode :tail
:accessibility-label :chat-message-text}
(:text content)]
(= constants/content-type-sticker content-type)
[react/image {:style {:margin 1 :width 20 :height 20}
;;TODO (perf) move to event
:source {:uri (contenthash/url (-> content :sticker :hash))}}]
[preview-label :t/sticker]
(= constants/content-type-image content-type)
[react/text {:style styles/last-message-text
:accessibility-label :no-messages-text}
(i18n/label :t/image)]
[preview-label :t/image]
(= constants/content-type-audio content-type)
[react/text {:style styles/last-message-text
:accessibility-label :no-messages-text}
(i18n/label :t/audio)]
(= constants/content-type-community content-type)
(let [{:keys [name]}
@(re-frame/subscribe [:communities/community community-id])]
[react/text {:style styles/last-message-text
:accessibility-label :no-messages-text}
(i18n/label :t/community-message-preview {:community-name name})])
(string/blank? (:text content))
[react/text {:style styles/last-message-text}
""]
(:text content)
(render-subheader (:parsed-text content)))])
[preview-label :t/audio])])
(def memo-timestamp
(memoize
@ -186,5 +118,5 @@
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
(:whisper-timestamp last-message)
timestamp))]
[message-content-text (select-keys last-message [:content :content-type :community-id])]
[message-content-text (select-keys last-message [:content :content-type]) true]
[unviewed-indicator home-item]]]))

View File

@ -78,43 +78,44 @@
(reagent/create-class
{:display-name "activity-center"
:component-did-mount #(re-frame/dispatch [:get-activity-center-notifications])
:reagent-render (fn []
(let [notifications @(re-frame/subscribe [:activity.center/notifications-grouped-by-date])]
[react/keyboard-avoiding-view {:style {:flex 1}
:ignore-offset true}
[topbar/topbar {:navigation {:on-press #(do
(reset-state)
(re-frame/dispatch [:navigate-back]))}
:title (i18n/label :t/activity)}]
(if (= (count notifications) 0)
[react/view {:style {:flex 1
:justify-content :center
:align-items :center}}
[quo/text {:color :secondary
:size :large
:align :center}
(i18n/label :t/empty-activity-center)]]
[:<>
[filter-item]
[list/section-list
{:key-fn #(str (:timestamp %) (or (:chat-id %) (:id %)))
:on-end-reached #(re-frame/dispatch [:load-more-activity-center-notifications])
:keyboard-should-persist-taps :always
:sections notifications
:render-fn render-fn
:stickySectionHeadersEnabled false
:render-section-header-fn
(fn [{:keys [title]}]
[quo/list-header title])}]
(when (or @select-all (> (count @selected-items) 0))
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary
:theme :negative
:accessibility-label :reject-and-delete-activity-center
:on-press #(toolbar-action false)}
(i18n/label :t/reject-and-delete)]
:right [quo/button {:type :secondary
:accessibility-label :accept-and-add-activity-center
:on-press #(toolbar-action true)}
(i18n/label :t/accept-and-add)]}])])]))}))
:reagent-render
(fn []
(let [notifications @(re-frame/subscribe [:activity.center/notifications-grouped-by-date])]
[react/keyboard-avoiding-view {:style {:flex 1}
:ignore-offset true}
[topbar/topbar {:navigation {:on-press #(do
(reset-state)
(re-frame/dispatch [:navigate-back]))}
:title (i18n/label :t/activity)}]
(if (= (count notifications) 0)
[react/view {:style {:flex 1
:justify-content :center
:align-items :center}}
[quo/text {:color :secondary
:size :large
:align :center}
(i18n/label :t/empty-activity-center)]]
[:<>
[filter-item]
[list/section-list
{:key-fn #(str (:timestamp %) (or (:chat-id %) (:id %)))
:on-end-reached #(re-frame/dispatch [:load-more-activity-center-notifications])
:keyboard-should-persist-taps :always
:sections notifications
:render-fn render-fn
:stickySectionHeadersEnabled false
:render-section-header-fn
(fn [{:keys [title]}]
[quo/list-header title])}]
(when (or @select-all (> (count @selected-items) 0))
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary
:theme :negative
:accessibility-label :reject-and-delete-activity-center
:on-press #(toolbar-action false)}
(i18n/label :t/reject-and-delete)]
:right [quo/button {:type :secondary
:accessibility-label :accept-and-add-activity-center
:on-press #(toolbar-action true)}
(i18n/label :t/accept-and-add)]}])])]))}))

View File

@ -2,118 +2,17 @@
(:require [status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[quo.core :as quo]
[clojure.string :as string]
[status-im.i18n.i18n :as i18n]
[status-im.ui.screens.notifications-center.styles :as styles]
[status-im.utils.handlers :refer [<sub]]
[status-im.ui.screens.chat.photos :as photos]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.icons.icons :as icons]
[status-im.utils.contenthash :as contenthash]
[status-im.constants :as constants]
[quo.design-system.colors :as colors]
[status-im.ui.screens.home.views.inner-item :as home-item]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]))
(defn mention-element [from]
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
(str (when-not (= (subs contact-name 0 1) "@") "@") contact-name)))
(def max-notification-length 160)
(def max-notification-lines 2)
(def max-reply-lines 1)
(defn add-parsed-to-message [acc style text-weight {:keys [type destination literal children]}]
(let [result (case type
"paragraph"
(reduce
(fn [{:keys [_ length] :as acc-paragraph} parsed-child]
(if (>= length max-notification-length)
(reduced acc-paragraph)
(add-parsed-to-message acc-paragraph style text-weight parsed-child)))
{:components [quo/text {:style style
:weight text-weight}]
:length 0}
children)
"mention"
{:components [quo/text {:style (merge style styles/mention-text)} [mention-element literal]]
:length 4} ;; we can't predict name length so take the smallest possible
"status-tag"
(home-item/truncate-literal (str "#" literal))
"link"
(home-item/truncate-literal destination)
(home-item/truncate-literal (string/replace literal #"\n" " ")))]
{:components (conj (:components acc) (:components result))
:length (+ (:length acc) (:length result))}))
(defn message-wrapper
([] (message-wrapper 1 styles/notification-reply-text))
([number-of-lines style]
[react/text-class {:style style
:number-of-lines number-of-lines
:ellipsize-mode :tail
:accessibility-label :chat-message-text}]))
(defn render-message
"Render the preview of a message with a maximum length, maximum lines, style and font weight"
([parsed-text] (render-message parsed-text max-notification-length max-notification-lines styles/notification-message-text :regular))
([parsed-text max-length number-of-lines style text-weight]
(let [result
(reduce
(fn [{:keys [_ length] :as acc-text} new-text-chunk]
(if (>= length max-length)
(reduced acc-text)
(add-parsed-to-message acc-text style text-weight new-text-chunk)))
{:components (message-wrapper number-of-lines style)
:length 0}
parsed-text)]
(:components result))))
(defn message-content-text [{:keys [content content-type community-id]} max-number-of-lines style text-weight]
[react/view
(cond
(not (and content content-type))
[react/text {:style (merge
style
{:color colors/gray})
:accessibility-label :no-messages-text}
(i18n/label :t/no-messages)]
(= constants/content-type-sticker content-type)
[react/image {:style {:margin 1 :width 20 :height 20}
;;TODO (perf) move to event
:source {:uri (contenthash/url (-> content :sticker :hash))}}]
(= constants/content-type-image content-type)
[react/text {:style style
:accessibility-label :no-messages-text}
(i18n/label :t/image)]
(= constants/content-type-audio content-type)
[react/text {:style style
:accessibility-label :no-messages-text}
(i18n/label :t/audio)]
(= constants/content-type-community content-type)
(let [{:keys [name]}
@(re-frame/subscribe [:communities/community community-id])]
[react/text {:style style
:accessibility-label :no-messages-text}
(i18n/label :t/community-message-preview {:community-name name})])
(string/blank? (:text content))
[react/text {:style style}
""]
(:text content)
(render-message (:parsed-text content) max-notification-length max-number-of-lines style text-weight))])
(defn activity-text-item [home-item opts]
(let [{:keys [chat-id chat-name message last-message reply-message muted read group-chat timestamp type color]} home-item
message (or message last-message)
@ -155,7 +54,7 @@
;;TODO (perf) move to event
(home-item/memo-timestamp timestamp)]
[react/view {:style styles/notification-message-container}
[message-content-text (select-keys message [:content :content-type :community-id]) max-notification-lines styles/notification-message-text]
[home-item/message-content-text (select-keys message [:content :content-type]) false]
(cond (= type constants/activity-center-notification-type-mention)
[react/view {:style styles/group-info-container
:accessibility-label :chat-name-container}
@ -190,4 +89,4 @@
:width 18
:height 18
:container-style styles/reply-icon}]
[message-content-text (select-keys reply-message [:content :content-type :community-id]) max-reply-lines styles/notification-reply-text :medium]])]]]))
[home-item/message-content-text (select-keys reply-message [:content :content-type]) false]])]]]))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.87.0",
"commit-sha1": "fb218761d9d1620916ae7e8b19b9b4a03f92c767",
"src-sha256": "073qgjfn2cn1li6g4r38xizkifsl4xd1sm51784jmy7kq6gqs1gr"
"version": "v0.87.1",
"commit-sha1": "59eeed94368c1f0ee9d603e313a13f178e644514",
"src-sha256": "1pnyb4vw88nx5b8np0ajhfyjblfkxr8bl40vhilz5gpz1g1a9l3c"
}

View File

@ -1157,6 +1157,7 @@
"status-not-sent-click": "Not confirmed. Click for options",
"step-i-of-n": "Step {{step}} of {{number}}",
"sticker-market": "Sticker market",
"sticker": "Sticker",
"submit": "Submit",
"submit-bug": "Submit a bug",
"success": "Success",