Allow to fetch more history in public chats (up to 30 days)

This commit is contained in:
Roman Volosovskyi 2019-04-24 22:32:06 +03:00
parent f6fce850b2
commit 9b9eefbf0e
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
7 changed files with 168 additions and 58 deletions

View File

@ -6,7 +6,8 @@
[status-im.chat.commands.input :as commands.input] [status-im.chat.commands.input :as commands.input]
[status-im.group-chats.db :as group-chats.db] [status-im.group-chats.db :as group-chats.db]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.transport.partitioned-topic :as topic])) [status-im.transport.partitioned-topic :as topic]
[status-im.mailserver.core :as mailserver]))
(defn group-chat-name (defn group-chat-name
[{:keys [public? name]}] [{:keys [public? name]}]
@ -86,10 +87,14 @@
(defn datemark? [{:keys [type]}] (defn datemark? [{:keys [type]}]
(= type :datemark)) (= type :datemark))
(defn gap? [{:keys [type]}]
(= type :gap))
(defn transform-message (defn transform-message
[messages message-statuses referenced-messages] [messages message-statuses referenced-messages]
(fn [{:keys [message-id timestamp-str] :as reference}] (fn [{:keys [message-id timestamp-str] :as reference}]
(if (datemark? reference) (if (or (datemark? reference)
(gap? reference))
reference reference
(let [{:keys [content] :as message} (get messages message-id) (let [{:keys [content] :as message} (get messages message-id)
{:keys [response-to response-to-v2]} content {:keys [response-to response-to-v2]} content
@ -141,14 +146,27 @@
(defn messages-with-datemarks-and-statuses (defn messages-with-datemarks-and-statuses
"Converts message groups into sequence of messages interspersed with datemarks, "Converts message groups into sequence of messages interspersed with datemarks,
with correct user statuses associated into message" with correct user statuses associated into message"
[message-groups messages message-statuses referenced-messages messages-gaps] [message-groups messages message-statuses referenced-messages messages-gaps
{:keys [highest-request-to lowest-request-from]} all-loaded? public?]
(transduce (transduce
(comp (comp
(mapcat add-datemark) (mapcat add-datemark)
(map (transform-message messages message-statuses referenced-messages))) (map (transform-message messages message-statuses referenced-messages)))
(completing (fn
(fn [{:keys [messages datemark-reference previous-message gaps]} ([]
message] (let [acc {:messages (list)
:previous-message nil
:gaps messages-gaps}]
(if (and
public?
all-loaded?
(< (- highest-request-to lowest-request-from)
mailserver/max-gaps-range))
(update acc :messages conj {:type :gap
:value (str :first-gap)
:first-gap? true})
acc)))
([{:keys [messages datemark-reference previous-message gaps]} message]
(let [new-datemark? (datemark? message) (let [new-datemark? (datemark? message)
{:keys [gaps-number gap]} {:keys [gaps-number gap]}
(check-gap gaps previous-message message) (check-gap gaps previous-message message)
@ -172,13 +190,10 @@
:gaps (if add-gap? :gaps (if add-gap?
(drop gaps-number gaps) (drop gaps-number gaps)
gaps)})) gaps)}))
(fn [{:keys [messages gaps]}] ([{:keys [messages gaps]}]
(cond-> messages (cond-> messages
(seq gaps) (seq gaps)
(add-gap {:ids (map :id gaps)})))) (add-gap {:ids (map :id gaps)}))))
{:messages (list)
:previous-message nil
:gaps messages-gaps}
message-groups)) message-groups))
(defn- set-previous-message-info [stream] (defn- set-previous-message-info [stream]

View File

@ -178,6 +178,25 @@
(fn [[gaps chat-id]] (fn [[gaps chat-id]]
(sort-by :from (vals (get gaps chat-id))))) (sort-by :from (vals (get gaps chat-id)))))
(re-frame/reg-sub
:chats/range
:<- [:get-in [:mailserver/ranges]]
:<- [:chats/current-chat-id]
(fn [[ranges chat-id]]
(get ranges chat-id)))
(re-frame/reg-sub
:chats/all-loaded?
:<- [:chats/current-chat]
(fn [chat]
(:all-loaded? chat)))
(re-frame/reg-sub
:chats/public?
:<- [:chats/current-chat]
(fn [chat]
(:public? chat)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat-messages-stream :chats/current-chat-messages-stream
:<- [:chats/current-chat-messages] :<- [:chats/current-chat-messages]
@ -185,9 +204,15 @@
:<- [:chats/current-chat-message-statuses] :<- [:chats/current-chat-message-statuses]
:<- [:chats/current-chat-referenced-messages] :<- [:chats/current-chat-referenced-messages]
:<- [:chats/messages-gaps] :<- [:chats/messages-gaps]
(fn [[messages message-groups message-statuses referenced-messages messages-gaps]] :<- [:chats/range]
:<- [:chats/all-loaded?]
:<- [:chats/public?]
(fn [[messages message-groups message-statuses referenced-messages
messages-gaps range all-loaded? public?]]
(-> (chat.db/sort-message-groups message-groups messages) (-> (chat.db/sort-message-groups message-groups messages)
(chat.db/messages-with-datemarks-and-statuses messages message-statuses referenced-messages messages-gaps) (chat.db/messages-with-datemarks-and-statuses
messages message-statuses referenced-messages
messages-gaps range all-loaded? public?)
chat.db/messages-stream))) chat.db/messages-stream)))
(re-frame/reg-sub (re-frame/reg-sub

View File

@ -753,6 +753,24 @@
:topic topic :topic topic
:chat-id chat-id})))) :chat-id chat-id}))))
(handlers/register-handler-fx
:chat.ui/fetch-more
(fn [{:keys [db] :as cofx}]
(let [chat-id (:current-chat-id db)
{:keys [lowest-request-from]}
(get-in db [:mailserver/ranges chat-id])
topic (chat.db/topic-by-current-chat db)
gaps [{:id :first-gap
:to lowest-request-from
:from (- lowest-request-from mailserver/one-day)}]]
(mailserver/fill-the-gap
cofx
{:gaps gaps
:topic topic
:chat-id chat-id}))))
(handlers/register-handler-fx (handlers/register-handler-fx
:chat.ui/remove-chat-pressed :chat.ui/remove-chat-pressed
(fn [_ [_ chat-id]] (fn [_ [_ chat-id]]

View File

@ -45,24 +45,24 @@
[(view-profile chat-id) [(view-profile chat-id)
(clear-history) (clear-history)
(fetch-history chat-id) (fetch-history chat-id)
(fetch-history48-60 chat-id) #_(fetch-history48-60 chat-id)
(fetch-history84-96 chat-id) #_(fetch-history84-96 chat-id)
(delete-chat chat-id false)]) (delete-chat chat-id false)])
(defn- group-chat-actions [chat-id] (defn- group-chat-actions [chat-id]
[(group-info chat-id) [(group-info chat-id)
(clear-history) (clear-history)
(fetch-history chat-id) (fetch-history chat-id)
(fetch-history48-60 chat-id) #_(fetch-history48-60 chat-id)
(fetch-history84-96 chat-id) #_(fetch-history84-96 chat-id)
(delete-chat chat-id true)]) (delete-chat chat-id true)])
(defn- public-chat-actions [chat-id] (defn- public-chat-actions [chat-id]
[(share-chat chat-id) [(share-chat chat-id)
(clear-history) (clear-history)
(fetch-history chat-id) (fetch-history chat-id)
(fetch-history48-60 chat-id) #_(fetch-history48-60 chat-id)
(fetch-history84-96 chat-id) #_(fetch-history84-96 chat-id)
(delete-chat chat-id false)]) (delete-chat chat-id false)])
(defn actions [group-chat? chat-id public?] (defn actions [group-chat? chat-id public?]

View File

@ -26,7 +26,8 @@
[status-im.ui.screens.chat.styles.main :as style] [status-im.ui.screens.chat.styles.main :as style]
[status-im.ui.screens.chat.toolbar-content :as toolbar-content] [status-im.ui.screens.chat.toolbar-content :as toolbar-content]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.utils.utils :as utils]) [status-im.utils.utils :as utils]
[status-im.utils.datetime :as datetime])
(:require-macros [status-im.utils.views :refer [defview letsubs]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn add-contact-bar [public-key] (defn add-contact-bar [public-key]
@ -71,7 +72,8 @@
[message-datemark/chat-datemark-mobile value]) [message-datemark/chat-datemark-mobile value])
(defview gap (defview gap
[ids idx list-ref in-progress? connected?] [ids idx list-ref in-progress? connected? range first-gap? intro-loading?]
(when-not (and first-gap? intro-loading?)
[react/view {:align-self :stretch [react/view {:align-self :stretch
:margin-top 24 :margin-top 24
:margin-bottom 24 :margin-bottom 24
@ -89,26 +91,45 @@
(.scrollToIndex @list-ref #js {:index (max 0 (dec idx)) (.scrollToIndex @list-ref #js {:index (max 0 (dec idx))
:viewOffset 20 :viewOffset 20
:viewPosition 0.5})) :viewPosition 0.5}))
(re-frame/dispatch [:chat.ui/fill-gaps ids])))} (if first-gap?
[react/view {:flex 1 (re-frame/dispatch [:chat.ui/fetch-more])
(re-frame/dispatch [:chat.ui/fill-gaps ids]))))}
[react/view {:style {:flex 1
:align-items :center :align-items :center
:justify-content :center} :justify-content :center
:text-align :center}}
(if in-progress? (if in-progress?
[react/activity-indicator] [react/activity-indicator]
[react/text [react/nested-text
{:style {:color (if connected? {:style {:text-align :center
:color (if connected?
colors/blue colors/blue
colors/gray)}} colors/gray)}}
(i18n/label :t/fetch-messages)])]]]) (i18n/label (if first-gap?
:t/load-more-messages
:t/fetch-messages))
(when first-gap?
[{:style {:typography :caption
:color colors/gray}}
(str "\n"
(i18n/label :t/load-messages-before
{:date (datetime/timestamp->long-date
(* 1000 (:lowest-request-from range)))}))])])]]]))
(defview gap-wrapper [{:keys [ids]} idx list-ref] (defview gap-wrapper [{:keys [gaps first-gap?]} idx list-ref]
(letsubs [in-progress? [:chats/fetching-gap-in-progress? ids] (letsubs [in-progress? [:chats/fetching-gap-in-progress?
connected? [:mailserver/connected?]] (if first-gap?
[gap ids idx list-ref in-progress? connected?])) [:first-gap]
(:ids gaps))]
connected? [:mailserver/connected?]
range [:chats/range]
intro-status [:chats/current-chat-intro-status]]
[gap (:ids gaps) idx list-ref in-progress?
connected? range first-gap? (= intro-status :loading)]))
(defmethod message-row :gap (defmethod message-row :gap
[{:keys [row idx list-ref]}] [{:keys [row idx list-ref]}]
[gap-wrapper (:gaps row) idx list-ref]) [gap-wrapper row idx list-ref])
(defmethod message-row :default (defmethod message-row :default
[{:keys [group-chat current-public-key modal? row]}] [{:keys [group-chat current-public-key modal? row]}]
@ -182,7 +203,8 @@
universal-link]} no-messages] universal-link]} no-messages]
(letsubs [intro-status [:chats/current-chat-intro-status] (letsubs [intro-status [:chats/current-chat-intro-status]
height [:chats/content-layout-height] height [:chats/content-layout-height]
input-height [:chats/current-chat-ui-prop :input-height]] input-height [:chats/current-chat-ui-prop :input-height]
{:keys [:lowest-request-from :highest-request-to]} [:chats/range]]
(let [icon-text (if public? chat-id name) (let [icon-text (if public? chat-id name)
intro-name (if public? chat-name name)] intro-name (if public? chat-name name)]
;; TODO This when check ought to be unnecessary but for now it prevents ;; TODO This when check ought to be unnecessary but for now it prevents
@ -226,7 +248,15 @@
(when public? (when public?
[react/nested-text {:style (merge style/intro-header-description [react/nested-text {:style (merge style/intro-header-description
{:margin-bottom 36})} {:margin-bottom 36})}
(i18n/label :t/empty-chat-description-public) (let [quiet-hours (quot (- highest-request-to lowest-request-from)
(* 60 60))
quiet-time (if (<= quiet-hours 24)
(i18n/label :t/quiet-hours
{:quiet-hours quiet-hours})
(i18n/label :t/quiet-days
{:quiet-days (quot quiet-hours 24)}))]
(i18n/label :t/empty-chat-description-public
{:quiet-hours quiet-time}))
[{:style {:color colors/blue} [{:style {:color colors/blue}
:on-press #(list-selection/open-share :on-press #(list-selection/open-share
{:message {:message

View File

@ -132,7 +132,25 @@
nil nil
nil nil
nil nil
nil)))) nil
nil
false
false))))
(testing "empty state pub-chat"
(is (=
[{:type :gap
:value ":first-gap"
:first-gap? true}]
(db/messages-with-datemarks-and-statuses
nil
nil
nil
nil
nil
{:lowest-request-from 10
:highest-request-to 30}
true
true))))
(testing "simple case" (testing "simple case"
(is (= (is (=
'({:whisper-timestamp 40 '({:whisper-timestamp 40

View File

@ -283,7 +283,9 @@
"wallet-set-up-title": "Set up your wallet", "wallet-set-up-title": "Set up your wallet",
"loading": "Loading... ", "loading": "Loading... ",
"empty-chat-description": "There are no messages \nin this chat yet", "empty-chat-description": "There are no messages \nin this chat yet",
"empty-chat-description-public": "It's been quiet here for the last 24h. Start the conversation or ", "empty-chat-description-public": "It's been quiet here for the last {{quiet-hours}}. Start the conversation or ",
"quiet-hours": "{{quiet-hours}} hours",
"quiet-days": "{{quiet-days}} days",
"empty-chat-description-public-share-this": "share this chat.", "empty-chat-description-public-share-this": "share this chat.",
"camera-access-error": "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected.", "camera-access-error": "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected.",
"wallet-invalid-address": "Invalid address: \n {{data}}", "wallet-invalid-address": "Invalid address: \n {{data}}",
@ -1000,6 +1002,8 @@
"mailserver-format": "enode://{enode-id}:{password}@{ip-address}:{port}", "mailserver-format": "enode://{enode-id}:{password}@{ip-address}:{port}",
"bootnode-format": "enode://{enode-id}@{ip-address}:{port}", "bootnode-format": "enode://{enode-id}@{ip-address}:{port}",
"fetch-messages": "↓ Fetch messages", "fetch-messages": "↓ Fetch messages",
"load-more-messages": "↓ Fetch more messages",
"load-messages-before": "before {{date}}",
"open-dapp-store": "Discover ÐApps", "open-dapp-store": "Discover ÐApps",
"browsed-websites": "Browsed websites will appear here." "browsed-websites": "Browsed websites will appear here."
} }