parent
bb4a4207df
commit
951fd43d10
|
@ -83,7 +83,7 @@
|
||||||
:optimizations :simple
|
:optimizations :simple
|
||||||
:target :node-test
|
:target :node-test
|
||||||
;; When running tests without a REPL you can uncomment below line to `make test-watch` a specific file
|
;; When running tests without a REPL you can uncomment below line to `make test-watch` a specific file
|
||||||
;; :ns-regexp "status-im.chat.models-test$"
|
;;:ns-regexp "status-im2.subs.subs-test$"
|
||||||
:main
|
:main
|
||||||
status-im.test-runner/main
|
status-im.test-runner/main
|
||||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||||
|
|
|
@ -184,9 +184,11 @@
|
||||||
|
|
||||||
(defn build-image-messages
|
(defn build-image-messages
|
||||||
[{db :db} chat-id]
|
[{db :db} chat-id]
|
||||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])]
|
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
|
||||||
|
album-id (str (random-uuid))]
|
||||||
(mapv (fn [[_ {:keys [uri]}]]
|
(mapv (fn [[_ {:keys [uri]}]]
|
||||||
{:chat-id chat-id
|
{:chat-id chat-id
|
||||||
|
:album-id album-id
|
||||||
:content-type constants/content-type-image
|
:content-type constants/content-type-image
|
||||||
:image-path (utils/safe-replace uri #"file://" "")
|
:image-path (utils/safe-replace uri #"file://" "")
|
||||||
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
|
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.data-store.chats :as data-store.chats]
|
[status-im.data-store.chats :as data-store.chats]
|
||||||
[status-im.data-store.messages :as data-store.messages]
|
[status-im.data-store.messages :as data-store.messages]
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im2.contexts.activity-center.events :as activity-center]
|
[status-im2.contexts.activity-center.events :as activity-center]
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn cursor->clock-value
|
(defn cursor->clock-value
|
||||||
[^js cursor]
|
[^js cursor]
|
||||||
|
@ -101,6 +101,17 @@
|
||||||
:on-success #(re-frame/dispatch
|
:on-success #(re-frame/dispatch
|
||||||
[::mark-all-read-in-community-successful %])}]}))
|
[::mark-all-read-in-community-successful %])}]}))
|
||||||
|
|
||||||
|
;; For example, when a user receives a list of 4 image messages while inside the chat screen we
|
||||||
|
;; shouldn't group the images into albums. When the user exists the chat screen then enters the
|
||||||
|
;; chat screen again, we now need to group the images into albums (like WhatsApp). The albumize?
|
||||||
|
;; boolean is used to know whether we need to group these images into albums now or not. The
|
||||||
|
;; album-id can't be used for this because it will always be there.
|
||||||
|
(defn mark-album
|
||||||
|
[message]
|
||||||
|
(if (:album-id message)
|
||||||
|
(assoc message :albumize? true)
|
||||||
|
message))
|
||||||
|
|
||||||
(rf/defn messages-loaded
|
(rf/defn messages-loaded
|
||||||
"Loads more messages for current chat"
|
"Loads more messages for current chat"
|
||||||
{:events [::messages-loaded]}
|
{:events [::messages-loaded]}
|
||||||
|
@ -131,8 +142,8 @@
|
||||||
current-clock-value (get-in db
|
current-clock-value (get-in db
|
||||||
[:pagination-info chat-id
|
[:pagination-info chat-id
|
||||||
:cursor-clock-value])
|
:cursor-clock-value])
|
||||||
clock-value (when cursor
|
clock-value (when cursor (cursor->clock-value cursor))
|
||||||
(cursor->clock-value cursor))]
|
new-messages (map mark-album new-messages)]
|
||||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||||
:db (-> db
|
:db (-> db
|
||||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
from
|
from
|
||||||
outgoing
|
outgoing
|
||||||
whisper-timestamp
|
whisper-timestamp
|
||||||
deleted-for-me?]}]
|
deleted-for-me?
|
||||||
|
albumize?]}]
|
||||||
(-> {:whisper-timestamp whisper-timestamp
|
(-> {:whisper-timestamp whisper-timestamp
|
||||||
:from from
|
:from from
|
||||||
:one-to-one? (= constants/message-type-one-to-one message-type)
|
:one-to-one? (= constants/message-type-one-to-one message-type)
|
||||||
|
@ -32,7 +33,8 @@
|
||||||
:clock-value clock-value
|
:clock-value clock-value
|
||||||
:type :message
|
:type :message
|
||||||
:message-id message-id
|
:message-id message-id
|
||||||
:outgoing (boolean outgoing)}
|
:outgoing (boolean outgoing)
|
||||||
|
:albumize? albumize?}
|
||||||
add-datemark
|
add-datemark
|
||||||
add-timestamp))
|
add-timestamp))
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
:audioDurationMs :audio-duration-ms
|
:audioDurationMs :audio-duration-ms
|
||||||
:deleted :deleted?
|
:deleted :deleted?
|
||||||
:deletedForMe :deleted-for-me?
|
:deletedForMe :deleted-for-me?
|
||||||
|
:albumId :album-id
|
||||||
:new :new?})
|
:new :new?})
|
||||||
|
|
||||||
(update :quoted-message
|
(update :quoted-message
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
(defn build-message
|
(defn build-message
|
||||||
[{:keys [chat-id
|
[{:keys [chat-id
|
||||||
|
album-id
|
||||||
text
|
text
|
||||||
response-to
|
response-to
|
||||||
ens-name
|
ens-name
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
sticker
|
sticker
|
||||||
content-type]}]
|
content-type]}]
|
||||||
{:chatId chat-id
|
{:chatId chat-id
|
||||||
|
:albumId album-id
|
||||||
:text text
|
:text text
|
||||||
:responseTo response-to
|
:responseTo response-to
|
||||||
:ensName ens-name
|
:ensName ens-name
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed
|
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed
|
||||||
(def ^:const content-type-gif 12)
|
(def ^:const content-type-gif 12)
|
||||||
(def ^:const content-type-link 13)
|
(def ^:const content-type-link 13)
|
||||||
|
(def ^:const content-type-album 14)
|
||||||
|
|
||||||
(def ^:const contact-request-state-none 0)
|
(def ^:const contact-request-state-none 0)
|
||||||
(def ^:const contact-request-state-mutual 1)
|
(def ^:const contact-request-state-mutual 1)
|
||||||
|
@ -200,3 +201,20 @@
|
||||||
|
|
||||||
(def ^:const delete-message-undo-time-limit-ms 4000)
|
(def ^:const delete-message-undo-time-limit-ms 4000)
|
||||||
(def ^:const delete-message-for-me-undo-time-limit-ms 4000)
|
(def ^:const delete-message-for-me-undo-time-limit-ms 4000)
|
||||||
|
|
||||||
|
(def ^:const album-image-sizes
|
||||||
|
{4 {0 146
|
||||||
|
1 146
|
||||||
|
2 146
|
||||||
|
3 146}
|
||||||
|
5 {0 146
|
||||||
|
1 146
|
||||||
|
2 97
|
||||||
|
3 97
|
||||||
|
4 97}
|
||||||
|
:default {0 146
|
||||||
|
1 146
|
||||||
|
2 72.5
|
||||||
|
3 72.5
|
||||||
|
4 72.5
|
||||||
|
5 72.5}})
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
(ns status-im2.contexts.chat.messages.content.album.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def album-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:flex-wrap :wrap
|
||||||
|
:overflow :hidden})
|
||||||
|
|
||||||
|
(defn image
|
||||||
|
[size index]
|
||||||
|
{:width size
|
||||||
|
:height size
|
||||||
|
:margin-left (when (and (not= index 0) (not= index 2)) 1)
|
||||||
|
:margin-bottom (when (< index 2) 1)})
|
||||||
|
|
||||||
|
(def overlay
|
||||||
|
{:position :absolute
|
||||||
|
:width 73
|
||||||
|
:height 73
|
||||||
|
:background-color colors/neutral-80-opa-60
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center})
|
|
@ -0,0 +1,51 @@
|
||||||
|
(ns status-im2.contexts.chat.messages.content.album.view
|
||||||
|
(:require [quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[react-native.fast-image :as fast-image]
|
||||||
|
[status-im2.contexts.chat.messages.content.album.style :as style]
|
||||||
|
[status-im2.common.constants :as constants]))
|
||||||
|
|
||||||
|
(def max-display-count 6)
|
||||||
|
|
||||||
|
(defn border-tlr
|
||||||
|
[index]
|
||||||
|
(when (= index 0) 12))
|
||||||
|
|
||||||
|
(defn border-trr
|
||||||
|
[index]
|
||||||
|
(when (= index 1) 12))
|
||||||
|
|
||||||
|
(defn border-blr
|
||||||
|
[index count]
|
||||||
|
(when (and (= index 2) (> count 2)) 12))
|
||||||
|
|
||||||
|
(defn border-brr
|
||||||
|
[index count]
|
||||||
|
(when (and (= index (- (min count max-display-count) 1)) (> count 2)) 12))
|
||||||
|
|
||||||
|
(defn album-message
|
||||||
|
[message]
|
||||||
|
[rn/view
|
||||||
|
{:style style/album-container}
|
||||||
|
(map-indexed
|
||||||
|
(fn [index item]
|
||||||
|
(let [images-count (count (:album message))
|
||||||
|
images-size-key (if (< images-count 6) images-count :default)
|
||||||
|
size (get-in constants/album-image-sizes [images-size-key index])]
|
||||||
|
[rn/view {:key (:message-id item)}
|
||||||
|
[fast-image/fast-image
|
||||||
|
{:style (merge (style/image size index)
|
||||||
|
{:border-top-left-radius (border-tlr index)
|
||||||
|
:border-top-right-radius (border-trr index)
|
||||||
|
:border-bottom-left-radius (border-blr index images-count)
|
||||||
|
:border-bottom-right-radius (border-brr index images-count)})
|
||||||
|
:source {:uri (:image (:content item))}}]
|
||||||
|
(when (and (> images-count max-display-count) (= index (- max-display-count 1)))
|
||||||
|
[rn/view
|
||||||
|
{:style (merge style/overlay {:border-bottom-right-radius (border-brr index images-count)})}
|
||||||
|
[quo/text
|
||||||
|
{:weight :bold
|
||||||
|
:size :heading-2
|
||||||
|
:style {:color colors/white}} (str "+" (- images-count 5))]])]))
|
||||||
|
(:album message))])
|
|
@ -10,6 +10,7 @@
|
||||||
[status-im2.contexts.chat.messages.content.reactions.view :as reactions]
|
[status-im2.contexts.chat.messages.content.reactions.view :as reactions]
|
||||||
[status-im2.contexts.chat.messages.content.status.view :as status]
|
[status-im2.contexts.chat.messages.content.status.view :as status]
|
||||||
[status-im2.contexts.chat.messages.content.system.text.view :as system.text]
|
[status-im2.contexts.chat.messages.content.system.text.view :as system.text]
|
||||||
|
[status-im2.contexts.chat.messages.content.album.view :as album]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[status-im.ui2.screens.chat.messages.message :as old-message]
|
[status-im.ui2.screens.chat.messages.message :as old-message]
|
||||||
|
@ -94,6 +95,8 @@
|
||||||
constants/content-type-audio [not-implemented/not-implemented
|
constants/content-type-audio [not-implemented/not-implemented
|
||||||
[old-message/audio message-data]]
|
[old-message/audio message-data]]
|
||||||
|
|
||||||
|
constants/content-type-album [album/album-message message-data]
|
||||||
|
|
||||||
[not-implemented/not-implemented [content.unknown/unknown-content message-data]])
|
[not-implemented/not-implemented [content.unknown/unknown-content message-data]])
|
||||||
[status/status message-data]]]]]))
|
[status/status message-data]]]]]))
|
||||||
|
|
||||||
|
|
|
@ -147,9 +147,10 @@
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/sending-image
|
:chats/sending-image
|
||||||
:<- [:chats/current-chat-inputs]
|
:<- [:chats/current-chat-id]
|
||||||
(fn [{:keys [metadata]}]
|
:<- [:chat/inputs]
|
||||||
(:sending-image metadata)))
|
(fn [[chat-id inputs]]
|
||||||
|
(get-in inputs [chat-id :metadata :sending-image])))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/timeline-chat-input-text
|
:chats/timeline-chat-input-text
|
||||||
|
|
|
@ -102,6 +102,25 @@
|
||||||
(fn [messages]
|
(fn [messages]
|
||||||
(empty? messages)))
|
(empty? messages)))
|
||||||
|
|
||||||
|
(defn albumize-messages
|
||||||
|
[messages]
|
||||||
|
(get (reduce (fn [{:keys [messages albums]} message]
|
||||||
|
(let [album-id (when (:albumize? message) (:album-id message))
|
||||||
|
albums (cond-> albums album-id (update album-id conj message))
|
||||||
|
messages (if (and album-id (> (count (get albums album-id)) 3))
|
||||||
|
(conj (filterv #(not= album-id (:album-id %)) messages)
|
||||||
|
{:album (get albums album-id)
|
||||||
|
:album-id album-id
|
||||||
|
:message-id album-id
|
||||||
|
:content-type constants/content-type-album})
|
||||||
|
(conj messages message))]
|
||||||
|
{:messages messages
|
||||||
|
:albums albums}))
|
||||||
|
{:messages []
|
||||||
|
:albums {}}
|
||||||
|
messages)
|
||||||
|
:messages))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/raw-chat-messages-stream
|
:chats/raw-chat-messages-stream
|
||||||
(fn [[_ chat-id] _]
|
(fn [[_ chat-id] _]
|
||||||
|
@ -126,7 +145,8 @@
|
||||||
(datetime/timestamp)
|
(datetime/timestamp)
|
||||||
chat-type
|
chat-type
|
||||||
joined
|
joined
|
||||||
loading-messages?))))))
|
loading-messages?)
|
||||||
|
(albumize-messages))))))
|
||||||
|
|
||||||
;;we want to keep data unchanged so react doesn't change component when we leave screen
|
;;we want to keep data unchanged so react doesn't change component when we leave screen
|
||||||
(def memo-profile-messages-stream (atom nil))
|
(def memo-profile-messages-stream (atom nil))
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
(ns status-im2.subs.chat.messages-test
|
||||||
|
(:require [cljs.test :refer [deftest is testing]]
|
||||||
|
[status-im2.subs.chat.messages :as messages]
|
||||||
|
[status-im2.common.constants :as constants]))
|
||||||
|
|
||||||
|
(def messages-state
|
||||||
|
[{:message-id "0x111" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x222" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x333" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x444" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x555" :album-id "efg" :albumize? true}])
|
||||||
|
|
||||||
|
(def messages-albumized-state
|
||||||
|
[{:album [{:message-id "0x444" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x333" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x222" :album-id "abc" :albumize? true}
|
||||||
|
{:message-id "0x111" :album-id "abc" :albumize? true}]
|
||||||
|
:album-id "abc"
|
||||||
|
:message-id "abc"
|
||||||
|
:content-type constants/content-type-album}
|
||||||
|
{:message-id "0x555" :album-id "efg" :albumize? true}])
|
||||||
|
|
||||||
|
(deftest albumize-messages
|
||||||
|
(testing "Finding albums in the messages list"
|
||||||
|
(is (= (messages/albumize-messages messages-state) messages-albumized-state))))
|
Loading…
Reference in New Issue