[Fixes: #10471] Parse markdown in chat subheader.
This commit adds parsing of markdown in the chat subheader. Because of the added complexity performance are impacted but I have also noticed that on each loading of the chat screen we calculate alias & identicon through status-go, so that has been changed so that they are returned from status-go. Overall performance is now roughly identical, tested loading 150 one-to-one chats. Another issue that I've spotted is that some `subs` are unnecessarely recalculated (`active-chats`), when unrelated fields changes. I will address this in a separate PR that should improve performance. Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
d0216674da
commit
34755500d5
|
@ -1,10 +1,10 @@
|
||||||
(ns status-im.chat.db
|
(ns status-im.chat.db
|
||||||
(:require [clojure.set :as clojure.set]
|
(:require [clojure.set :as clojure.set]
|
||||||
[clojure.string :as clojure.string]
|
[clojure.string :as clojure.string]
|
||||||
[status-im.contact.db :as contact.db]
|
|
||||||
[status-im.group-chats.db :as group-chats.db]
|
[status-im.group-chats.db :as group-chats.db]
|
||||||
[status-im.mailserver.constants :as mailserver.constants]
|
[status-im.mailserver.constants :as mailserver.constants]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
|
[status-im.utils.identicon :as identicon]
|
||||||
[status-im.utils.gfycat.core :as gfycat]))
|
[status-im.utils.gfycat.core :as gfycat]))
|
||||||
|
|
||||||
(defn group-chat-name
|
(defn group-chat-name
|
||||||
|
@ -12,7 +12,10 @@
|
||||||
(str (when public? "#") name))
|
(str (when public? "#") name))
|
||||||
|
|
||||||
(defn enrich-active-chat
|
(defn enrich-active-chat
|
||||||
[contacts {:keys [chat-id group-chat] :as chat} current-public-key]
|
[contacts {:keys [chat-id
|
||||||
|
identicon
|
||||||
|
alias
|
||||||
|
group-chat] :as chat} current-public-key]
|
||||||
(if group-chat
|
(if group-chat
|
||||||
(let [pending-invite-inviter-name
|
(let [pending-invite-inviter-name
|
||||||
(group-chats.db/get-pending-invite-inviter-name contacts
|
(group-chats.db/get-pending-invite-inviter-name contacts
|
||||||
|
@ -29,15 +32,25 @@
|
||||||
(assoc :inviter-name inviter-name)
|
(assoc :inviter-name inviter-name)
|
||||||
:always
|
:always
|
||||||
(assoc :chat-name (group-chat-name chat))))
|
(assoc :chat-name (group-chat-name chat))))
|
||||||
(let [{contact-name :name :as contact}
|
(let [photo (if (seq identicon)
|
||||||
|
identicon
|
||||||
|
(identicon/identicon chat-id))
|
||||||
|
alias (if (seq alias)
|
||||||
|
alias
|
||||||
|
(gfycat/generate-gfy chat-id))
|
||||||
|
{contact-name :name :as contact}
|
||||||
(get contacts chat-id
|
(get contacts chat-id
|
||||||
(contact.db/public-key->new-contact chat-id))
|
{:public-key chat-id
|
||||||
random-name (gfycat/generate-gfy chat-id)]
|
:identicon photo
|
||||||
|
:alias alias
|
||||||
|
:name alias
|
||||||
|
:system-tags #{}})]
|
||||||
(-> chat
|
(-> chat
|
||||||
(assoc :contact contact
|
(assoc :contact contact
|
||||||
:chat-name (multiaccounts/displayed-name contact)
|
:chat-name (multiaccounts/displayed-name contact)
|
||||||
:name contact-name
|
:name contact-name
|
||||||
:random-name random-name)
|
:identicon photo
|
||||||
|
:alias alias)
|
||||||
(update :tags clojure.set/union (:tags contact))))))
|
(update :tags clojure.set/union (:tags contact))))))
|
||||||
|
|
||||||
(defn active-chats
|
(defn active-chats
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
|
|
||||||
(deftest filter-chats
|
(deftest filter-chats
|
||||||
(let [chats {:chat-1 {:name "name1"
|
(let [chats {:chat-1 {:name "name1"
|
||||||
:random-name "random-name1"
|
:alias "alias1"
|
||||||
:tags #{"tag1"}}
|
:tags #{"tag1"}}
|
||||||
:chat-2 {:name "name2"
|
:chat-2 {:name "name2"
|
||||||
:random-name "random-name2"
|
:alias "alias2"
|
||||||
:tags #{"tag2" "tag3"}}
|
:tags #{"tag2" "tag3"}}
|
||||||
:chat-3 {:name "name3"
|
:chat-3 {:name "name3"
|
||||||
:random-name "random-name3"
|
:alias "alias3"
|
||||||
:tags #{}}
|
:tags #{}}
|
||||||
:chat-4 {:name "name4"
|
:chat-4 {:name "name4"
|
||||||
:random-name "random-name4"
|
:alias "alias4"
|
||||||
:tags #{"tag4"}}}]
|
:tags #{"tag4"}}}]
|
||||||
(testing "no search filter"
|
(testing "no search filter"
|
||||||
(is (= (count chats)
|
(is (= (count chats)
|
||||||
|
@ -33,15 +33,15 @@
|
||||||
chats
|
chats
|
||||||
search.subs/extract-chat-attributes
|
search.subs/extract-chat-attributes
|
||||||
false)))))
|
false)))))
|
||||||
(testing "searching for a specific random-name"
|
(testing "searching for a specific alias"
|
||||||
(is (= 1
|
(is (= 1
|
||||||
(count (search.subs/apply-filter "random-name1"
|
(count (search.subs/apply-filter "alias4"
|
||||||
chats
|
chats
|
||||||
search.subs/extract-chat-attributes
|
search.subs/extract-chat-attributes
|
||||||
false)))))
|
false)))))
|
||||||
(testing "searching for a partial random-name"
|
(testing "searching for a partial alias"
|
||||||
(is (= 4
|
(is (= 4
|
||||||
(count (search.subs/apply-filter "random-name"
|
(count (search.subs/apply-filter "alias"
|
||||||
chats
|
chats
|
||||||
search.subs/extract-chat-attributes
|
search.subs/extract-chat-attributes
|
||||||
false)))))
|
false)))))
|
||||||
|
|
|
@ -1786,8 +1786,8 @@
|
||||||
;;SEARCH ==============================================================================================================
|
;;SEARCH ==============================================================================================================
|
||||||
|
|
||||||
(defn extract-chat-attributes [chat]
|
(defn extract-chat-attributes [chat]
|
||||||
(let [{:keys [name random-name tags]} (val chat)]
|
(let [{:keys [name alias tags]} (val chat)]
|
||||||
(into [name random-name] tags)))
|
(into [name alias] tags)))
|
||||||
|
|
||||||
(defn sort-by-timestamp
|
(defn sort-by-timestamp
|
||||||
[coll]
|
[coll]
|
||||||
|
|
|
@ -11,7 +11,60 @@
|
||||||
[status-im.ui.screens.home.styles :as styles]
|
[status-im.ui.screens.home.styles :as styles]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
[status-im.utils.contenthash :as contenthash]
|
||||||
[status-im.utils.core :as utils]
|
[status-im.utils.core :as utils]
|
||||||
[status-im.utils.datetime :as time]))
|
[status-im.utils.datetime :as time])
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
|
(defview mention-element [from]
|
||||||
|
(letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]]
|
||||||
|
(if ens-name (str "@" ens-name) alias)))
|
||||||
|
|
||||||
|
(defn render-subheader-inline [acc {:keys [type destination literal children]}]
|
||||||
|
(case type
|
||||||
|
"paragraph"
|
||||||
|
(conj acc (reduce
|
||||||
|
(fn [acc e] (render-subheader-inline acc e))
|
||||||
|
[react/text-class " "]
|
||||||
|
children))
|
||||||
|
|
||||||
|
"blockquote"
|
||||||
|
(conj acc (.substring literal 0 (dec (.-length literal))))
|
||||||
|
|
||||||
|
"codeblock"
|
||||||
|
(conj acc (.substring literal 0 (dec (.-length literal))))
|
||||||
|
|
||||||
|
"mention"
|
||||||
|
(conj acc [react/text-class
|
||||||
|
[mention-element literal]])
|
||||||
|
|
||||||
|
"status-tag"
|
||||||
|
(conj acc [react/text-class
|
||||||
|
"#"
|
||||||
|
literal])
|
||||||
|
|
||||||
|
"link"
|
||||||
|
(conj acc destination)
|
||||||
|
|
||||||
|
(conj acc literal)))
|
||||||
|
|
||||||
|
(def max-length 40)
|
||||||
|
|
||||||
|
(defn render-subheader
|
||||||
|
"Render the chat subheader markdown inline, to a maximum of max-length characters"
|
||||||
|
[parsed-text]
|
||||||
|
(:elements
|
||||||
|
(reduce
|
||||||
|
(fn [{:keys [elements l] :as acc} {:keys [literal] :as e}]
|
||||||
|
(if (> l max-length)
|
||||||
|
(reduced acc)
|
||||||
|
{:elements (render-subheader-inline elements e)
|
||||||
|
:l (+ l (count literal))}))
|
||||||
|
{:length 0
|
||||||
|
:elements
|
||||||
|
[react/text-class {:style styles/last-message-text
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsize-mode :tail
|
||||||
|
:accessibility-label :chat-message-text}]}
|
||||||
|
parsed-text)))
|
||||||
|
|
||||||
(defn message-content-text [{:keys [content content-type]}]
|
(defn message-content-text [{:keys [content content-type]}]
|
||||||
[react/view styles/last-message-container
|
[react/view styles/last-message-container
|
||||||
|
@ -32,14 +85,7 @@
|
||||||
""]
|
""]
|
||||||
|
|
||||||
(:text content)
|
(:text content)
|
||||||
[react/text {:style styles/last-message-text
|
(render-subheader (:parsed-text content)))])
|
||||||
:number-of-lines 1
|
|
||||||
:ellipsize-mode :tail
|
|
||||||
:accessibility-label :chat-message-text}
|
|
||||||
;;TODO (perf) move to event
|
|
||||||
(-> (:text content)
|
|
||||||
(subs 0 40)
|
|
||||||
(string/trim-newline))])])
|
|
||||||
|
|
||||||
(defn message-timestamp [timestamp]
|
(defn message-timestamp [timestamp]
|
||||||
(when timestamp
|
(when timestamp
|
||||||
|
@ -75,12 +121,8 @@
|
||||||
:title-row-accessory [message-timestamp (if (pos? (:whisper-timestamp last-message))
|
:title-row-accessory [message-timestamp (if (pos? (:whisper-timestamp last-message))
|
||||||
(:whisper-timestamp last-message)
|
(:whisper-timestamp last-message)
|
||||||
timestamp)]
|
timestamp)]
|
||||||
:subtitle
|
:subtitle [message-content-text {:content (:content last-message)
|
||||||
(let [{:keys [tribute-status tribute-label]} (:tribute-to-talk contact)]
|
:content-type (:content-type last-message)}]
|
||||||
(if (not (#{:require :pending} tribute-status))
|
|
||||||
[message-content-text {:content (:content last-message)
|
|
||||||
:content-type (:content-type last-message)}]
|
|
||||||
tribute-label))
|
|
||||||
:subtitle-row-accessory [unviewed-indicator home-item]
|
:subtitle-row-accessory [unviewed-indicator home-item]
|
||||||
:on-press #(do
|
:on-press #(do
|
||||||
(re-frame/dispatch [:dismiss-keyboard])
|
(re-frame/dispatch [:dismiss-keyboard])
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
|
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.52.4",
|
"version": "v0.53.2",
|
||||||
"commit-sha1": "7bbe9561de16f3bfd9675a8640212cc75410fd75",
|
"commit-sha1": "ee0a83fdc4a19f70fa8d08347ef67c0ca3d67f1e",
|
||||||
"src-sha256": "1s5iv49ck152aq8d0ibr4aja3nf7s4njgmkfx4kn5ds0dy4zq533"
|
"src-sha256": "1jv7cw6a41czhslmqxbqjw2alv9yb0ddpbxyin2l0kdpnxvph965"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue