diff --git a/src/status_im2/contexts/chat/messages/content/album/view.cljs b/src/status_im2/contexts/chat/messages/content/album/view.cljs index 0704debc95..56302b73a5 100644 --- a/src/status_im2/contexts/chat/messages/content/album/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/album/view.cljs @@ -5,6 +5,8 @@ [react-native.fast-image :as fast-image] [status-im2.contexts.chat.messages.content.album.style :as style] [status-im2.constants :as constants] + [status-im2.contexts.chat.messages.content.image.view :as image] + [status-im2.contexts.chat.messages.content.text.view :as text] [utils.re-frame :as rf])) (def rectangular-style-count 3) @@ -16,7 +18,7 @@ {:width (second size-arr) :height (first size-arr) :album-style album-style})) (defn album-message - [message] + [{:keys [albumize?] :as message} context on-long-press] (let [shared-element-id (rf/sub [:shared-element-id]) first-image (first (:album message)) album-style (if (> (:image-width first-image) (:image-height first-image)) @@ -27,42 +29,48 @@ ;; (portrait or landscape) portrait? (and (= images-count rectangular-style-count) (= album-style :portrait)) text (:text (:content first-image))] - [:<> - ;; This text comp is temporary. Should later use - ;; `status-im2.contexts.chat.messages.content.text.view` - (when (not= text "placeholder") [quo/text {:style {:margin-bottom 10}} text]) - [rn/view - {:style (style/album-container portrait?)} - (map-indexed - (fn [index item] - (let [images-size-key (if (< images-count constants/max-album-photos) images-count :default) - size (get-in constants/album-image-sizes [images-size-key index]) - dimensions (if (not= images-count rectangular-style-count) - {:width size :height size} - (find-size size album-style))] - [rn/touchable-opacity - {:key (:message-id item) - :active-opacity 1 - ;; issue: https://github.com/status-im/status-mobile/issues/14995 - :on-long-press #(js/alert "Action drawer for albums is not supported yet") - :on-press (fn [] - (rf/dispatch [:chat.ui/update-shared-element-id (:message-id item)]) - (js/setTimeout #(rf/dispatch [:navigate-to :lightbox - {:messages (:album message) :index index}]) - 100))} - [fast-image/fast-image - {:style (style/image dimensions index portrait? images-count) - :source {:uri (:image (:content item))} - :native-ID (when (and (= shared-element-id (:message-id item)) - (< index constants/max-album-photos)) - :shared-element)}] - (when (and (> images-count constants/max-album-photos) - (= index (- constants/max-album-photos 1))) - [rn/view - {:style style/overlay} - [quo/text - {:weight :bold - :size :heading-2 - :style {:color colors/white}} - (str "+" (- images-count (dec constants/max-album-photos)))]])])) - (:album message))]])) + (if (and albumize? (> images-count 1)) + [:<> + (when (not= text "placeholder") + [rn/view {:style {:margin-bottom 10}} [text/text-content first-image context]]) + [rn/view + {:style (style/album-container portrait?)} + (map-indexed + (fn [index item] + (let [images-size-key (if (< images-count constants/max-album-photos) images-count :default) + size (get-in constants/album-image-sizes [images-size-key index]) + dimensions (if (not= images-count rectangular-style-count) + {:width size :height size} + (find-size size album-style))] + [rn/touchable-opacity + {:key (:message-id item) + :active-opacity 1 + ;; issue: https://github.com/status-im/status-mobile/issues/14995 + :on-long-press #(on-long-press message context) + :on-press (fn [] + (rf/dispatch [:chat.ui/update-shared-element-id (:message-id item)]) + (js/setTimeout #(rf/dispatch [:navigate-to :lightbox + {:messages (:album message) + :index index}]) + 100))} + [fast-image/fast-image + {:style (style/image dimensions index portrait? images-count) + :source {:uri (:image (:content item))} + :native-ID (when (and (= shared-element-id (:message-id item)) + (< index constants/max-album-photos)) + :shared-element)}] + (when (and (> images-count constants/max-album-photos) + (= index (- constants/max-album-photos 1))) + [rn/view + {:style style/overlay} + [quo/text + {:weight :bold + :size :heading-2 + :style {:color colors/white}} + (str "+" (- images-count (dec constants/max-album-photos)))]])])) + (:album message))]] + [:<> + (map-indexed + (fn [index item] + [image/image-message index item context #(on-long-press message context)]) + (:album message))]))) diff --git a/src/status_im2/contexts/chat/messages/content/image/view.cljs b/src/status_im2/contexts/chat/messages/content/image/view.cljs index dcecd9da04..2a27bb46b8 100644 --- a/src/status_im2/contexts/chat/messages/content/image/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/image/view.cljs @@ -1,25 +1,19 @@ (ns status-im2.contexts.chat.messages.content.image.view (:require - [quo2.core :as quo] [react-native.core :as rn] [react-native.fast-image :as fast-image] [status-im2.constants :as constants] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [status-im2.contexts.chat.messages.content.text.view :as text])) (defn calculate-dimensions [width height] (let [max-width (if (> width height) (* 2 constants/image-size) (* 1.5 constants/image-size)) max-height (if (> width height) (* 1.5 constants/image-size) (* 2 constants/image-size))] - (if (> height width) - (let [calculated-height (* (min height max-height) (/ (max width max-width) width)) - calculated-width (* (max width max-width) (/ (min height max-height) height))] - {:width calculated-width :height calculated-height}) - (let [calculated-height (* (max height max-height) (/ (min width max-width) width)) - calculated-width (* (min width max-width) (/ (max height max-height) height))] - {:width calculated-width :height calculated-height})))) + {:width (min width max-width) :height (min height max-height)})) (defn image-message - [_ {:keys [content image-width image-height message-id] :as message} context on-long-press] + [index {:keys [content image-width image-height message-id] :as message} context on-long-press] (let [dimensions (calculate-dimensions (or image-width 1000) (or image-height 1000)) text (:text content)] (fn [] @@ -27,15 +21,15 @@ [rn/touchable-opacity {:active-opacity 1 :key message-id - :on-long-press #(on-long-press message context) + :style {:margin-top (when (> index 0) 20)} + :on-long-press on-long-press :on-press (fn [] (rf/dispatch [:chat.ui/update-shared-element-id message-id]) (js/setTimeout #(rf/dispatch [:navigate-to :lightbox {:messages [message] :index 0}]) 100))} - ;; This text comp is temporary. Should later use - ;; `status-im2.contexts.chat.messages.content.text.view` - (when (not= text "placeholder") [quo/text {:style {:margin-bottom 10}} text]) + (when (and (not= text "placeholder") (= index 0)) + [rn/view {:style {:margin-bottom 10}} [text/text-content message context]]) [fast-image/fast-image {:source {:uri (:image content)} :style (merge dimensions {:border-radius 12}) diff --git a/src/status_im2/contexts/chat/messages/content/reactions/view.cljs b/src/status_im2/contexts/chat/messages/content/reactions/view.cljs index c008ae55c0..d5c6193a8e 100644 --- a/src/status_im2/contexts/chat/messages/content/reactions/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/reactions/view.cljs @@ -6,10 +6,8 @@ [status-im2.contexts.chat.messages.drawers.view :as drawers])) (defn message-reactions-row - [chat-id message-id messages-ids] - (let [reactions (if messages-ids - (mapcat #(rf/sub [:chats/message-reactions % chat-id]) messages-ids) - (rf/sub [:chats/message-reactions message-id chat-id]))] + [chat-id message-id] + (let [reactions (rf/sub [:chats/message-reactions message-id chat-id])] (when (seq reactions) [rn/view {:margin-left 52 :margin-bottom 12 :flex-direction :row} (for [{:keys [own emoji-id quantity emoji-reaction-id] :as emoji-reaction} reactions] @@ -30,12 +28,8 @@ :accessibility-label (str "emoji-reaction-" emoji-id)}]]) [quo/add-reaction {:on-press (fn [] - ;; issue: https://github.com/status-im/status-mobile/issues/14995 - (if messages-ids - (js/alert "Reactions for albums is not yet supported") - (do - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch - [:bottom-sheet/show-sheet - {:content (fn [] [drawers/reactions - {:chat-id chat-id :message-id message-id}])}]))))}]]))) + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch + [:bottom-sheet/show-sheet + {:content (fn [] [drawers/reactions + {:chat-id chat-id :message-id message-id}])}]))}]]))) diff --git a/src/status_im2/contexts/chat/messages/content/view.cljs b/src/status_im2/contexts/chat/messages/content/view.cljs index 3be6a2c478..9e6585fde1 100644 --- a/src/status_im2/contexts/chat/messages/content/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/view.cljs @@ -76,12 +76,6 @@ constants/content-type-contact-request [not-implemented/not-implemented [old-message/system-contact-request message-data]]))) -(defn message-on-long-press - [message-data context] - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:bottom-sheet/show-sheet - {:content (drawers/reactions-and-actions message-data context)}])) - (defn on-long-press [message-data context] (rf/dispatch [:dismiss-keyboard]) @@ -102,7 +96,7 @@ outgoing (if (= content-type constants/content-type-album) (:outgoing first-image) outgoing) - context (assoc context :on-long-press #(message-on-long-press message-data context)) + context (assoc context :on-long-press #(on-long-press message-data context)) response-to (:response-to content)] [rn/touchable-highlight {:accessibility-label (if (and outgoing (= outgoing-status :sending)) @@ -154,9 +148,7 @@ [status/status outgoing-status])]]]])))]) (defn message-with-reactions - [{:keys [pinned-by mentioned in-pinned-view? content-type - last-in-group? message-id messages-ids] - :as message-data} + [{:keys [pinned-by mentioned in-pinned-view? content-type last-in-group? message-id] :as message-data} {:keys [chat-id] :as context}] [rn/view {:style (style/message-container in-pinned-view? pinned-by mentioned last-in-group?) @@ -168,4 +160,4 @@ content-type) [system-message-content message-data] [user-message-content message-data context]) - [reactions/message-reactions-row chat-id message-id messages-ids]]) + [reactions/message-reactions-row chat-id message-id]]) diff --git a/src/status_im2/contexts/chat/messages/drawers/view.cljs b/src/status_im2/contexts/chat/messages/drawers/view.cljs index 52a2631c4d..37855956d6 100644 --- a/src/status_im2/contexts/chat/messages/drawers/view.cljs +++ b/src/status_im2/contexts/chat/messages/drawers/view.cljs @@ -20,7 +20,8 @@ (assoc message-data :pinned message-not-pinned?)])))) (defn get-actions - [{:keys [outgoing content pinned outgoing-status deleted? deleted-for-me?] :as message-data} + [{:keys [outgoing content pinned outgoing-status deleted? deleted-for-me? content-type] + :as message-data} {:keys [edit-enabled show-input? community? can-delete-message-for-everyone? message-pin-enabled group-chat group-admin?]}] (concat @@ -36,7 +37,7 @@ :label (i18n/label :t/message-reply) :icon :i/reply :id :reply}]) - (when-not (or deleted? deleted-for-me?) + (when (and (not (or deleted? deleted-for-me?)) (not= (get content :text) "placeholder")) [{:type :main :on-press #(react/copy-to-clipboard (components.reply/get-quoted-text-with-mentions @@ -44,7 +45,8 @@ :label (i18n/label :t/copy-text) :icon :i/copy :id :copy}]) - (when message-pin-enabled + ;; pinning images are temporarily disabled + (when (and message-pin-enabled (not= content-type constants/content-type-image)) [{:type :main :on-press #(pin-message message-data) :label (i18n/label (if pinned @@ -126,18 +128,22 @@ icon]])))])) (defn reactions-and-actions - [{:keys [message-id outgoing-status deleted? deleted-for-me?] :as message-data} + [message-data {:keys [chat-id] :as context}] (fn [] - (let [actions (get-actions message-data context) - main-actions (filter #(= (:type %) :main) actions) - danger-actions (filter #(= (:type %) :danger) actions) - admin-actions (filter #(= (:type %) :admin) actions)] + (let [data (if (contains? message-data :album-id) + (first (:album message-data)) + message-data) + {:keys [message-id deleted? deleted-for-me?]} data + outgoing-status (:outgoing-status data) + actions (get-actions data context) + main-actions (filter #(= (:type %) :main) actions) + danger-actions (filter #(= (:type %) :danger) actions) + admin-actions (filter #(= (:type %) :admin) actions)] [:<> ;; REACTIONS (when (and (not= outgoing-status :sending) (not (or deleted? deleted-for-me?))) [reactions {:chat-id chat-id :message-id message-id}]) - ;; MAIN ACTIONS [rn/view {:style {:padding-horizontal 8}} (for [action main-actions] diff --git a/src/status_im2/subs/chat/messages.cljs b/src/status_im2/subs/chat/messages.cljs index e671c50e21..a84d9d9ce0 100644 --- a/src/status_im2/subs/chat/messages.cljs +++ b/src/status_im2/subs/chat/messages.cljs @@ -19,7 +19,7 @@ so we bucket both in 1999-12-31" [{:keys [acc last-timestamp last-datemark]} {:keys [whisper-timestamp datemark] :as msg}] (cond - (empty? acc) ; initial element + (empty? acc) ; initial element {:last-timestamp whisper-timestamp :last-datemark datemark :acc (conj acc msg)} @@ -112,39 +112,27 @@ (defn albumize-messages [messages] (get - (reduce - (fn [{:keys [messages albums]} message] - (let [album-id (:album-id message) - ;; check if this image is the first image in an album (which is not albumized yet) - add-text? (when (and album-id (not (:albumize? message)) (> (count (get albums album-id)) 0)) - (not (some #(= false %) - (mapv #(< (:timestamp message) (:timestamp %)) - (get albums album-id))))) - albums (cond-> albums album-id (update album-id conj message)) - ;; keep text of the first album image only - message (if (or add-text? (<= (count (get albums album-id)) 1)) - message - (assoc-in message [:content :text] nil)) - messages (if (and (> (count (get albums album-id)) 1) (:albumize? message)) - (conj (filterv #(not= album-id (:album-id %)) messages) - {:album (get albums album-id) - :album-id album-id - :albumize? (:albumize? message) - :messages-ids (mapv :message-id (get albums album-id)) - :message-id album-id - :content-type constants/content-type-album}) - ;; remove text of other images in an album - (if add-text? - (conj (mapv #(when (= (:album-id %) album-id) - (assoc-in % [:content :text] nil)) - messages) - message) - (conj messages message)))] - {:messages messages - :albums albums})) - {:messages [] - :albums {}} - messages) + (reduce (fn [{:keys [messages albums]} message] + (let [album-id (:album-id message) + albums (cond-> albums album-id (update album-id conj message)) + messages (if album-id + (conj (filterv #(not= album-id (:album-id %)) messages) + {:album (get albums album-id) + :album-id album-id + :albumize? (:albumize? message) + :message-id (:message-id message) + :deleted? (:deleted? message) + :deleted-for-me? (:deleted-for-me? message) + :deleted-by (:deleted-by message) + :from (:from message) + :timestamp-str (:timestamp-str message) + :content-type constants/content-type-album}) + (conj messages message))] + {:messages messages + :albums albums})) + {:messages [] + :albums {}} + messages) :messages)) (re-frame/reg-sub diff --git a/src/status_im2/subs/chat/messages_test.cljs b/src/status_im2/subs/chat/messages_test.cljs index 374c224169..e468c8e3f3 100644 --- a/src/status_im2/subs/chat/messages_test.cljs +++ b/src/status_im2/subs/chat/messages_test.cljs @@ -7,25 +7,25 @@ [utils.re-frame :as rf])) (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 "edf" :timestamp 10 :content {:text "Wassup!"}} - {:message-id "0x666" :album-id "edf" :timestamp 20 :content {:text "Wassup!"}}]) + [{:message-id "0x111" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x222" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x333" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x444" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"}]) (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" - :albumize? true - :message-id "abc" - :messages-ids ["0x444" "0x333" "0x222" "0x111"] - :content-type constants/content-type-album} - {:message-id "0x555" :album-id "edf" :timestamp 10 :content {:text "Wassup!"}} - {:message-id "0x666" :album-id "edf" :timestamp 20 :content {:text nil}}]) + [{:album [{:message-id "0x444" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x333" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x222" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"} + {:message-id "0x111" :album-id "abc" :albumize? true :from :xyz :timestamp-str "14:00"}] + :album-id "abc" + :albumize? true + :message-id "0x444" + :deleted? nil + :deleted-for-me? nil + :deleted-by nil + :from :xyz + :timestamp-str "14:00" + :content-type constants/content-type-album}]) (deftest albumize-messages (testing "Finding albums in the messages list"