parent
bb4a4207df
commit
951fd43d10
|
@ -83,7 +83,7 @@
|
|||
:optimizations :simple
|
||||
:target :node-test
|
||||
;; 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
|
||||
status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
|
|
|
@ -184,9 +184,11 @@
|
|||
|
||||
(defn build-image-messages
|
||||
[{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]}]]
|
||||
{:chat-id chat-id
|
||||
:album-id album-id
|
||||
:content-type constants/content-type-image
|
||||
:image-path (utils/safe-replace uri #"file://" "")
|
||||
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[utils.re-frame :as rf]
|
||||
[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
|
||||
[^js cursor]
|
||||
|
@ -101,6 +101,17 @@
|
|||
:on-success #(re-frame/dispatch
|
||||
[::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
|
||||
"Loads more messages for current chat"
|
||||
{:events [::messages-loaded]}
|
||||
|
@ -131,8 +142,8 @@
|
|||
current-clock-value (get-in db
|
||||
[:pagination-info chat-id
|
||||
:cursor-clock-value])
|
||||
clock-value (when cursor
|
||||
(cursor->clock-value cursor))]
|
||||
clock-value (when cursor (cursor->clock-value cursor))
|
||||
new-messages (map mark-album new-messages)]
|
||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||
:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
from
|
||||
outgoing
|
||||
whisper-timestamp
|
||||
deleted-for-me?]}]
|
||||
deleted-for-me?
|
||||
albumize?]}]
|
||||
(-> {:whisper-timestamp whisper-timestamp
|
||||
:from from
|
||||
:one-to-one? (= constants/message-type-one-to-one message-type)
|
||||
|
@ -32,7 +33,8 @@
|
|||
:clock-value clock-value
|
||||
:type :message
|
||||
:message-id message-id
|
||||
:outgoing (boolean outgoing)}
|
||||
:outgoing (boolean outgoing)
|
||||
:albumize? albumize?}
|
||||
add-datemark
|
||||
add-timestamp))
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
:audioDurationMs :audio-duration-ms
|
||||
:deleted :deleted?
|
||||
:deletedForMe :deleted-for-me?
|
||||
:albumId :album-id
|
||||
:new :new?})
|
||||
|
||||
(update :quoted-message
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
(defn build-message
|
||||
[{:keys [chat-id
|
||||
album-id
|
||||
text
|
||||
response-to
|
||||
ens-name
|
||||
|
@ -15,6 +16,7 @@
|
|||
sticker
|
||||
content-type]}]
|
||||
{:chatId chat-id
|
||||
:albumId album-id
|
||||
:text text
|
||||
:responseTo response-to
|
||||
:ensName ens-name
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
:dy 0 ;used for gesture
|
||||
:pdy 0 ;used for gesture
|
||||
:state :min ;:min, :custom-chat-available,
|
||||
;:custom-chat-unavailable, :max
|
||||
;:custom-chat-unavailable, :max
|
||||
:clear false
|
||||
:minimized-from-handlebar? false})
|
||||
keyboard-was-shown? (atom false)
|
||||
|
@ -188,19 +188,19 @@
|
|||
360)
|
||||
(:top insets)
|
||||
(:status-bar-height @navigation-const)) ; 360
|
||||
; -
|
||||
; default
|
||||
; height
|
||||
; -
|
||||
; default
|
||||
; height
|
||||
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56
|
||||
; -
|
||||
; top-bar
|
||||
; height
|
||||
; -
|
||||
; top-bar
|
||||
; height
|
||||
added-value (if (and (not (seq suggestions))
|
||||
(or edit reply))
|
||||
38
|
||||
0) ; increased height
|
||||
; of input box
|
||||
; needed when reply
|
||||
; of input box
|
||||
; needed when reply
|
||||
min-y (+ min-y (when (or edit reply) 38))
|
||||
bg-opacity (reanimated/use-shared-value 0)
|
||||
bg-bottom (reanimated/use-shared-value (-
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed
|
||||
(def ^:const content-type-gif 12)
|
||||
(def ^:const content-type-link 13)
|
||||
(def ^:const content-type-album 14)
|
||||
|
||||
(def ^:const contact-request-state-none 0)
|
||||
(def ^:const contact-request-state-mutual 1)
|
||||
|
@ -200,3 +201,20 @@
|
|||
|
||||
(def ^:const delete-message-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.status.view :as status]
|
||||
[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]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.ui2.screens.chat.messages.message :as old-message]
|
||||
|
@ -94,6 +95,8 @@
|
|||
constants/content-type-audio [not-implemented/not-implemented
|
||||
[old-message/audio message-data]]
|
||||
|
||||
constants/content-type-album [album/album-message message-data]
|
||||
|
||||
[not-implemented/not-implemented [content.unknown/unknown-content message-data]])
|
||||
[status/status message-data]]]]]))
|
||||
|
||||
|
|
|
@ -147,9 +147,10 @@
|
|||
|
||||
(re-frame/reg-sub
|
||||
:chats/sending-image
|
||||
:<- [:chats/current-chat-inputs]
|
||||
(fn [{:keys [metadata]}]
|
||||
(:sending-image metadata)))
|
||||
:<- [:chats/current-chat-id]
|
||||
:<- [:chat/inputs]
|
||||
(fn [[chat-id inputs]]
|
||||
(get-in inputs [chat-id :metadata :sending-image])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/timeline-chat-input-text
|
||||
|
|
|
@ -102,6 +102,25 @@
|
|||
(fn [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
|
||||
:chats/raw-chat-messages-stream
|
||||
(fn [[_ chat-id] _]
|
||||
|
@ -126,7 +145,8 @@
|
|||
(datetime/timestamp)
|
||||
chat-type
|
||||
joined
|
||||
loading-messages?))))))
|
||||
loading-messages?)
|
||||
(albumize-messages))))))
|
||||
|
||||
;;we want to keep data unchanged so react doesn't change component when we leave screen
|
||||
(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