Fix incorrect loading of messages

In some instances when receiving messages from a mailsever in the chat
you are in, the flag `all-loaded?` would not be reset, meaning that
messages not in the current view would be added to the db, but would not be seen until actually
reloading the chat (go back home, open again).

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2020-04-03 13:32:42 +02:00
parent 749faaeb1b
commit a914334fed
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
5 changed files with 101 additions and 24 deletions

View File

@ -162,7 +162,7 @@
(when-let [current-chat-id (:current-chat-id db)] (when-let [current-chat-id (:current-chat-id db)]
(if-not (get-in db [:chats current-chat-id :messages-initialized?]) (if-not (get-in db [:chats current-chat-id :messages-initialized?])
(do (do
; reset chat viewable-items state ; reset chat first-not-visible-items state
(chat.state/reset) (chat.state/reset)
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db

View File

@ -104,33 +104,32 @@
(fx/defn add-received-message (fx/defn add-received-message
[{:keys [db] :as cofx} [{:keys [db] :as cofx}
{:keys [from {:keys [chat-id
message-id clock-value] :as message}]
chat-id
clock-value
content] :as message}]
(let [{:keys [loaded-chat-id (let [{:keys [loaded-chat-id
view-id view-id
current-chat-id]} db current-chat-id]} db
cursor-clock-value (get-in db [:chats current-chat-id :cursor-clock-value]) cursor-clock-value (get-in db [:chats current-chat-id :cursor-clock-value])
current-chat? (= chat-id loaded-chat-id)] current-chat? (= chat-id loaded-chat-id)]
(when (and current-chat? (when current-chat?
(or (not cursor-clock-value) ;; If we don't have any hidden message or the hidden message is before
(<= cursor-clock-value clock-value))) ;; this one, we add the message to the UI
(if (or (not @view.state/viewable-item) (if (or (not @view.state/first-not-visible-item)
(not= current-chat-id (<= (:clock-value @view.state/first-not-visible-item)
(:chat-id @view.state/viewable-item))
(<= (:clock-value @view.state/viewable-item)
clock-value)) clock-value))
(add-message cofx {:message message (add-message cofx {:message message
:seen-by-user? (and current-chat? :seen-by-user? (and current-chat?
(= view-id :chat))}) (= view-id :chat))})
;; Not in the current view, offload to db and update cursor if necessary ;; Not in the current view, set all-loaded to false
(when (and (< clock-value ;; and offload to db and update cursor if necessary
cursor-clock-value) {:db (cond-> db
(= current-chat-id (>= clock-value
(:chat-id @view.state/viewable-item))) cursor-clock-value)
{:db (assoc-in db [:chats chat-id :cursor] (chat-loading/clock-value->cursor clock-value))}))))) (update-in [:chats chat-id] assoc
:cursor (chat-loading/clock-value->cursor clock-value)
:cursor-clock-value clock-value)
:always
(assoc-in [:chats chat-id :all-loaded?] false))}))))
(defn- add-to-chat? (defn- add-to-chat?
[{:keys [db]} {:keys [chat-id clock-value message-id from]}] [{:keys [db]} {:keys [chat-id clock-value message-id from]}]

View File

@ -1,6 +1,6 @@
(ns status-im.ui.screens.chat.state) (ns status-im.ui.screens.chat.state)
(defonce viewable-item (atom nil)) (defonce first-not-visible-item (atom nil))
(defn reset [] (defn reset []
(reset! viewable-item nil)) (reset! first-not-visible-item nil))

View File

@ -95,7 +95,7 @@
(defn on-viewable-items-changed [e] (defn on-viewable-items-changed [e]
(when @messages-list-ref (when @messages-list-ref
(reset! state/viewable-item (reset! state/first-not-visible-item
(when-let [last-visible-element (aget (.-viewableItems e) (dec (.-length (.-viewableItems e))))] (when-let [last-visible-element (aget (.-viewableItems e) (dec (.-length (.-viewableItems e))))]
(let [index (.-index last-visible-element) (let [index (.-index last-visible-element)
;; Get first not visible element, if it's a datemark/gap ;; Get first not visible element, if it's a datemark/gap
@ -158,4 +158,4 @@
[messages-view current-chat]]] [messages-view current-chat]]]
(when show-input? (when show-input?
[input/container]) [input/container])
[bottom-sheet]])) [bottom-sheet]]))

View File

@ -3,13 +3,91 @@
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon] [status-im.utils.identicon :as identicon]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.chat.models.loading :as chat-loading]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.transport.message.protocol :as protocol] [status-im.transport.message.protocol :as protocol]
[status-im.chat.models.message-list :as models.message-list] [status-im.chat.models.message-list :as models.message-list]
[status-im.ui.screens.chat.state :as view.state]
[status-im.chat.models.message :as message] [status-im.chat.models.message :as message]
[status-im.utils.datetime :as time])) [status-im.utils.datetime :as time]))
(deftest add-received-message-test
(with-redefs [message/add-message (constantly :added)]
(let [chat-id "chat-id"
clock-value 10
cursor-clock-value (dec clock-value)
cursor (chat-loading/clock-value->cursor cursor-clock-value)
cofx {:now 0
:db {:loaded-chat-id chat-id
:current-chat-id chat-id
:all-loaded? true
:chats {chat-id {:cursor cursor
:cursor-clock-value cursor-clock-value}}}}
message {:chat-id chat-id
:clock-value clock-value}]
(testing "not current-chat"
(is (nil? (message/add-received-message
(update cofx :db dissoc :loaded-chat-id)
message))))
;; <- cursor
;; <- message
;; <- top of the chat
(testing "there's no hidden item"
(with-redefs [view.state/first-not-visible-item (atom nil)]
(is (= :added (message/add-received-message
cofx
message)))))
;; <- cursor
;; <- first-hidden-item
;; <- message
;; <- top of the chat
(testing "the hidden item has a clock value less than the current"
(with-redefs [view.state/first-not-visible-item (atom {:clock-value (dec clock-value)})]
(is (= :added (message/add-received-message
cofx
message)))))
;; <- cursor
;; <- message
;; <- first-hidden-item
;; <- top of the chat
(testing "the message falls between the first-hidden-item and cursor"
(with-redefs [view.state/first-not-visible-item (atom {:clock-value (inc clock-value)})]
(let [result (message/add-received-message
cofx
message)]
(testing "it sets all-loaded? to false"
(is (not (get-in result [:db :chats chat-id :all-loaded?]))))
(testing "it updates cursor-clock-value & cursor"
(is (= clock-value (get-in result [:db :chats chat-id :cursor-clock-value])))
(is (= (chat-loading/clock-value->cursor clock-value) (get-in result [:db :chats chat-id :cursor])))))))
;; <- message
;; <- first-hidden-item
;; <- top of the chat
(testing "the message falls between the first-hidden-item and cursor is nil"
(with-redefs [view.state/first-not-visible-item (atom {:clock-value (inc clock-value)})]
(let [result (message/add-received-message
(update-in cofx [:db :chats chat-id] dissoc :cursor :cursor-clock-value)
message)]
(testing "it sets all-loaded? to false"
(is (not (get-in result [:db :chats chat-id :all-loaded?]))))
(testing "it updates cursor-clock-value & cursor"
(is (= clock-value (get-in result [:db :chats chat-id :cursor-clock-value])))
(is (= (chat-loading/clock-value->cursor clock-value) (get-in result [:db :chats chat-id :cursor])))))))
;; <- message
;; <- cursor
;; <- first-hidden-item
;; <- top of the chat
(testing "the message falls before both the first-hidden-item and cursor"
(with-redefs [view.state/first-not-visible-item (atom {:clock-value (inc clock-value)})]
(let [result (message/add-received-message
cofx
(update message :clock-value #(- % 2)))]
(testing "it sets all-loaded? to false"
(is (not (get-in result [:db :chats chat-id :all-loaded?]))))
(testing "it does not update cursor-clock-value & cursor"
(is (= cursor-clock-value (get-in result [:db :chats chat-id :cursor-clock-value])))
(is (= cursor (get-in result [:db :chats chat-id :cursor]))))))))))
(deftest add-to-chat? (deftest add-to-chat?
(testing "it returns true when it's not in loaded message" (testing "it returns true when it's not in loaded message"
(is (message/add-to-chat? {:db {:chats {"a" {}}}} (is (message/add-to-chat? {:db {:chats {"a" {}}}}