[15660] Show who sent message reaction (#15677)

This commit is contained in:
Ibrahem Khalil 2023-06-01 11:21:33 +04:00 committed by GitHub
parent 0dd3cb51fd
commit 56dbb77ee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 271 additions and 80 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1011 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -13,7 +13,7 @@
{:on-press on-press {:on-press on-press
:accessibility-label :emoji-reaction-add :accessibility-label :emoji-reaction-add
:style (style/add-reaction)} :style (style/add-reaction)}
[icons/icon :i/add [icons/icon :i/add-reaction
{:size 20 {:size 20
:color (if dark? :color (if dark?
colors/white colors/white
@ -21,10 +21,11 @@
(defn reaction (defn reaction
"Add your emoji as a param here" "Add your emoji as a param here"
[{:keys [emoji clicks neutral? on-press accessibility-label]}] [{:keys [emoji clicks neutral? on-press accessibility-label on-long-press]}]
(let [numeric-value (int clicks)] (let [numeric-value (int clicks)]
[rn/touchable-opacity [rn/touchable-opacity
{:on-press on-press {:on-press on-press
:on-long-press on-long-press
:accessibility-label accessibility-label :accessibility-label accessibility-label
:style (style/reaction neutral?)} :style (style/reaction neutral?)}
[icons/icon emoji [icons/icon emoji

View File

@ -6,7 +6,8 @@
[react-native.masked-view :as masked-view] [react-native.masked-view :as masked-view]
[reagent.core :as reagent] [reagent.core :as reagent]
[utils.collection :as utils.collection] [utils.collection :as utils.collection]
[utils.number :as utils.number])) [utils.number :as utils.number]
[react-native.gesture :as gesture]))
(def default-tab-size 32) (def default-tab-size 32)
(def unread-count-offset 3) (def unread-count-offset 3)
@ -131,7 +132,8 @@
style style
size size
blur? blur?
override-theme] override-theme
in-scroll-view?]
:or {fade-end-percentage fade-end-percentage :or {fade-end-percentage fade-end-percentage
fade-end? false fade-end? false
scrollable? false scrollable? false
@ -142,7 +144,9 @@
[rn/view {:style {:margin-top (- (dec unread-count-offset))}} [rn/view {:style {:margin-top (- (dec unread-count-offset))}}
[masked-view-wrapper [masked-view-wrapper
{:fade-end-percentage (get @fading :fade-end-percentage) :fade-end? fade-end?} {:fade-end-percentage (get @fading :fade-end-percentage) :fade-end? fade-end?}
[rn/flat-list [(if in-scroll-view?
gesture/flat-list
rn/flat-list)
(merge (merge
(dissoc props (dissoc props
:default-active :default-active

View File

@ -4,7 +4,8 @@
[status-im.data-store.reactions :as data-store.reactions] [status-im.data-store.reactions :as data-store.reactions]
[status-im.transport.message.protocol :as message.protocol] [status-im.transport.message.protocol :as message.protocol]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[utils.transforms :as transforms]))
(defn update-reaction (defn update-reaction
[acc retracted chat-id message-id emoji-id emoji-reaction-id reaction] [acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
@ -94,3 +95,42 @@
acc)) acc))
[] []
reactions)) reactions))
(defn- <-rpc
[{compressed-key :compressedKey
emoji-id :emojiId
:keys [from]}]
{:compressed-key compressed-key
:emoji-id emoji-id
:from from})
(defn- format-response
[response]
(->> (transforms/js->clj response)
(map <-rpc)
(group-by :emoji-id)))
(rf/defn save-emoji-reaction-details
{:events [:chat/save-emoji-reaction-details]}
[{:keys [db]} message-reactions long-pressed-emoji]
{:db (assoc db
:chat/reactions-authors
{:reaction-authors-list message-reactions
:selected-reaction long-pressed-emoji})})
(rf/defn clear-emoji-reaction-details
{:events [:chat/clear-emoji-reaction-author-details]}
[{:keys [db]} message-reactions]
{:db (update db dissoc :chat/reactions-authors)})
(rf/defn emoji-reactions-by-message-id
{:events [:chat.ui/emoji-reactions-by-message-id]}
[{:keys [db]} {:keys [message-id long-pressed-emoji]}]
{:json-rpc/call [{:method "wakuext_emojiReactionsByChatIDMessageID"
:params [(:current-chat-id db) message-id]
:js-response true
:on-error #(log/error "failed to fetch emoji reaction by message-id: "
{:message-id message-id :error %})
:on-success #(rf/dispatch [:chat/save-emoji-reaction-details
(format-response %) long-pressed-emoji])}]})

View File

@ -89,8 +89,9 @@
{:events [:chat.ui/show-profile]} {:events [:chat.ui/show-profile]}
[{:keys [db]} identity ens-name] [{:keys [db]} identity ens-name]
(let [my-public-key (get-in db [:multiaccount :public-key])] (let [my-public-key (get-in db [:multiaccount :public-key])]
(when (not= my-public-key identity) (if (not= my-public-key identity)
{:db (-> db {:db (-> db
(assoc :contacts/identity identity) (assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name)) (assoc :contacts/ens-name ens-name))
:dispatch [:contacts/build-contact identity ens-name true]}))) :dispatch [:contacts/build-contact identity ens-name true]}
{:dispatch [:navigate-to :my-profile]})))

View File

@ -13,7 +13,7 @@
:margin-vertical 8}) :margin-vertical 8})
(defn sheet (defn sheet
[{:keys [top bottom]} window-height override-theme shell?] [{:keys [top bottom]} window-height override-theme padding-bottom-override shell?]
{:position :absolute {:position :absolute
:max-height (- window-height top 20) :max-height (- window-height top 20)
:z-index 1 :z-index 1
@ -22,9 +22,9 @@
:right 0 :right 0
:border-top-left-radius 20 :border-top-left-radius 20
:border-top-right-radius 20 :border-top-right-radius 20
:overflow :hidden :overflow (when shell? :hidden)
:flex 1 :flex 1
:padding-bottom (max 20 bottom) :padding-bottom (or padding-bottom-override (max 20 bottom))
:background-color (if shell? :background-color (if shell?
:transparent :transparent
(colors/theme-colors colors/white colors/neutral-90 override-theme))}) (colors/theme-colors colors/white colors/neutral-90 override-theme))})

View File

@ -13,7 +13,9 @@
(def timing-options #js {:duration duration}) (def timing-options #js {:duration duration})
(defn hide (defn hide
[translate-y bg-opacity window-height] [translate-y bg-opacity window-height on-close]
(when (fn? on-close)
(on-close))
;; it will be better to use animation callback, but it doesn't work ;; it will be better to use animation callback, but it doesn't work
;; so we have to use timeout, also we add 50ms for safety ;; so we have to use timeout, also we add 50ms for safety
(js/setTimeout #(rf/dispatch [:bottom-sheet-hidden]) (+ duration 50)) (js/setTimeout #(rf/dispatch [:bottom-sheet-hidden]) (+ duration 50))
@ -29,7 +31,7 @@
(def gesture-values (atom {})) (def gesture-values (atom {}))
(defn get-sheet-gesture (defn get-sheet-gesture
[translate-y bg-opacity window-height] [translate-y bg-opacity window-height on-close]
(-> (gesture/gesture-pan) (-> (gesture/gesture-pan)
(gesture/on-start (gesture/on-start
(fn [_] (fn [_]
@ -47,17 +49,22 @@
(fn [_] (fn [_]
(if (< (:dy @gesture-values) 0) (if (< (:dy @gesture-values) 0)
(show translate-y bg-opacity) (show translate-y bg-opacity)
(hide translate-y bg-opacity window-height)))))) (hide translate-y bg-opacity window-height on-close))))))
(defn view (defn view
[{:keys [hide? insets]} {:keys [content override-theme selected-item shell?]}] [{:keys [hide? insets]}
{:keys [content override-theme selected-item padding-bottom-override on-close shell?]}]
(let [{window-height :height} (rn/get-window) (let [{window-height :height} (rn/get-window)
bg-opacity (reanimated/use-shared-value 0) bg-opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value window-height) translate-y (reanimated/use-shared-value window-height)
sheet-gesture (get-sheet-gesture translate-y bg-opacity window-height)] sheet-gesture (get-sheet-gesture translate-y bg-opacity window-height on-close)]
(rn/use-effect #(if hide? (hide translate-y bg-opacity window-height) (show translate-y bg-opacity)) (rn/use-effect
[hide?]) #(if hide? (hide translate-y bg-opacity window-height on-close) (show translate-y bg-opacity))
(hooks/use-back-handler #(do (rf/dispatch [:hide-bottom-sheet]) true)) [hide?])
(hooks/use-back-handler #(do (when (fn? on-close)
(on-close))
(rf/dispatch [:hide-bottom-sheet])
true))
[rn/view {:flex 1} [rn/view {:flex 1}
;; backdrop ;; backdrop
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:hide-bottom-sheet])} [rn/touchable-without-feedback {:on-press #(rf/dispatch [:hide-bottom-sheet])}
@ -70,7 +77,7 @@
[reanimated/view [reanimated/view
{:style (reanimated/apply-animations-to-style {:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]} {:transform [{:translateY translate-y}]}
(styles/sheet insets window-height override-theme shell?))} (styles/sheet insets window-height override-theme padding-bottom-override shell?))}
(when shell? (when shell?
[blur/ios-view [blur/ios-view

View File

@ -5,31 +5,69 @@
[utils.re-frame :as rf] [utils.re-frame :as rf]
[status-im2.contexts.chat.messages.drawers.view :as drawers])) [status-im2.contexts.chat.messages.drawers.view :as drawers]))
(defn- on-press
[own message-id emoji-id emoji-reaction-id]
(if own
(rf/dispatch [:models.reactions/send-emoji-reaction-retraction
{:message-id message-id
:emoji-id emoji-id
:emoji-reaction-id emoji-reaction-id}])
(rf/dispatch [:models.reactions/send-emoji-reaction
{:message-id message-id
:emoji-id emoji-id}])))
(defn- on-long-press
[message-id emoji-id]
(rf/dispatch [:chat.ui/emoji-reactions-by-message-id
{:message-id message-id
:long-pressed-emoji emoji-id}]))
(defn show-authors-sheet
[user-message-content reactions]
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch
[:show-bottom-sheet
{:on-close (fn []
(rf/dispatch
[:chat/clear-emoji-reaction-author-details]))
:content (fn []
[drawers/reaction-authors
(map :emoji-id reactions)])
:selected-item (fn []
user-message-content)
:padding-bottom-override 0}]))
(defn message-reactions-row (defn message-reactions-row
[chat-id message-id] [{:keys [message-id chat-id]} user-message-content]
(let [reactions (rf/sub [:chats/message-reactions message-id chat-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} (when (seq reactions)
(for [{:keys [own emoji-id quantity emoji-reaction-id] :as emoji-reaction} reactions] [rn/view
^{:key (str emoji-reaction)} {:style {:margin-left 52
[rn/view {:style {:margin-right 6}} :margin-bottom 12
[quo/reaction :flex-direction :row}}
{:emoji (get constants/reactions emoji-id) (for [{:keys [own emoji-id quantity emoji-reaction-id]
:neutral? own :as emoji-reaction} reactions]
:clicks quantity ^{:key emoji-reaction}
:on-press (if own [rn/view {:style {:margin-right 6}}
#(rf/dispatch [:models.reactions/send-emoji-reaction-retraction [quo/reaction
{:message-id message-id {:emoji (get constants/reactions emoji-id)
:emoji-id emoji-id :neutral? own
:emoji-reaction-id emoji-reaction-id}]) :clicks quantity
#(rf/dispatch [:models.reactions/send-emoji-reaction :on-press #(on-press own message-id emoji-id emoji-reaction-id)
{:message-id message-id :on-long-press (fn []
:emoji-id emoji-id}])) (on-long-press message-id
:accessibility-label (str "emoji-reaction-" emoji-id)}]]) emoji-id)
[quo/add-reaction (show-authors-sheet user-message-content
{:on-press (fn [] reactions))
(rf/dispatch [:dismiss-keyboard]) :accessibility-label (str "emoji-reaction-" emoji-id)}]])
(rf/dispatch [quo/add-reaction
[:show-bottom-sheet {:on-press (fn []
{:content (fn [] [drawers/reactions (rf/dispatch [:dismiss-keyboard])
{:chat-id chat-id :message-id message-id}])}]))}]]))) (rf/dispatch
[:show-bottom-sheet
{:content (fn [] [drawers/reactions
{:chat-id chat-id
:message-id message-id}])
:selected-item (fn []
user-message-content)}]))}]])]))

View File

@ -23,16 +23,18 @@
[status-im2.common.not-implemented :as not-implemented] [status-im2.common.not-implemented :as not-implemented]
[utils.datetime :as datetime] [utils.datetime :as datetime]
[reagent.core :as reagent] [reagent.core :as reagent]
[utils.address :as address])) [utils.address :as address]
[react-native.gesture :as gesture]))
(def delivery-state-showing-time-ms 3000) (def delivery-state-showing-time-ms 3000)
(defn avatar-container (defn avatar-container
[{:keys [content last-in-group? pinned-by quoted-message from]}] [{:keys [content last-in-group? pinned-by quoted-message from]} message-reaction-view?]
(if (or (and (seq (:response-to content)) (if (or (and (seq (:response-to content))
quoted-message) quoted-message)
last-in-group? last-in-group?
pinned-by) pinned-by
message-reaction-view?)
[avatar/avatar from :small] [avatar/avatar from :small]
[rn/view {:padding-top 2 :width 32}])) [rn/view {:padding-top 2 :width 32}]))
@ -43,8 +45,9 @@
pinned-by pinned-by
quoted-message quoted-message
from from
timestamp]}] timestamp]}
(when (or (and (seq response-to) quoted-message) last-in-group? pinned-by) message-reaction-view?]
(when (or (and (seq response-to) quoted-message) last-in-group? pinned-by message-reaction-view?)
(let [[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity from]) (let [[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity from])
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])] {:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
[quo/author [quo/author
@ -82,7 +85,8 @@
(let [show-delivery-state? (reagent/atom false)] (let [show-delivery-state? (reagent/atom false)]
(fn [{:keys [content-type quoted-message content outgoing outgoing-status] :as message-data} (fn [{:keys [content-type quoted-message content outgoing outgoing-status] :as message-data}
context context
keyboard-shown] keyboard-shown
message-reaction-view?]
(let [first-image (first (:album message-data)) (let [first-image (first (:album message-data))
outgoing-status (if (= content-type constants/content-type-album) outgoing-status (if (= content-type constants/content-type-album)
(:outgoing-status first-image) (:outgoing-status first-image)
@ -91,7 +95,8 @@
(:outgoing first-image) (:outgoing first-image)
outgoing) outgoing)
context (assoc context :on-long-press #(on-long-press message-data context)) context (assoc context :on-long-press #(on-long-press message-data context))
response-to (:response-to content)] response-to (:response-to content)
height (rf/sub [:dimensions/window-height])]
[rn/touchable-highlight [rn/touchable-highlight
{:accessibility-label (if (and outgoing (= outgoing-status :sending)) {:accessibility-label (if (and outgoing (= outgoing-status :sending))
:message-sending :message-sending
@ -115,37 +120,41 @@
[rn/view [rn/view
{:style {:padding-horizontal 12 {:style {:padding-horizontal 12
:flex-direction :row}} :flex-direction :row}}
[avatar-container message-data] [avatar-container message-data message-reaction-view?]
[rn/view (into
{:style {:margin-left 8 (if message-reaction-view?
:flex 1}} [gesture/scroll-view]
[author message-data] [rn/view])
(case content-type [{:style {:margin-left 8
:flex 1
:max-height (when message-reaction-view? (* 0.4 height))}}
[author message-data message-reaction-view?]
(case content-type
constants/content-type-text [content.text/text-content message-data] constants/content-type-text [content.text/text-content message-data context]
constants/content-type-emoji constants/content-type-emoji
[not-implemented/not-implemented [old-message/emoji message-data]] [not-implemented/not-implemented [old-message/emoji message-data]]
constants/content-type-sticker constants/content-type-sticker
[not-implemented/not-implemented [old-message/sticker message-data]] [not-implemented/not-implemented [old-message/sticker message-data]]
constants/content-type-audio constants/content-type-audio
[audio/audio-message message-data context] [audio/audio-message message-data context]
constants/content-type-image constants/content-type-image
[image/image-message 0 message-data on-long-press] [image/image-message 0 message-data context on-long-press]
constants/content-type-album constants/content-type-album
[album/album-message message-data context on-long-press] [album/album-message message-data context on-long-press]
[not-implemented/not-implemented [content.unknown/unknown-content message-data]]) [not-implemented/not-implemented [content.unknown/unknown-content message-data]])
(when @show-delivery-state? (when @show-delivery-state?
[status/status outgoing-status])]]]])))) [status/status outgoing-status])])]]]))))
(defn message-with-reactions (defn message-with-reactions
[{:keys [pinned-by mentioned in-pinned-view? content-type last-in-group? message-id] :as message-data} [{:keys [pinned-by mentioned in-pinned-view? content-type last-in-group?] :as message-data}
{:keys [chat-id] :as context} context
keyboard-shown] keyboard-shown]
[rn/view [rn/view
{:style (style/message-container in-pinned-view? pinned-by mentioned last-in-group?) {:style (style/message-container in-pinned-view? pinned-by mentioned last-in-group?)
@ -153,9 +162,10 @@
(when pinned-by (when pinned-by
[pin/pinned-by-view pinned-by]) [pin/pinned-by-view pinned-by])
(if (#{constants/content-type-system-text constants/content-type-community (if (#{constants/content-type-system-text constants/content-type-community
constants/content-type-system-pinned-message constants/content-type-contact-request
constants/content-type-contact-request} constants/content-type-system-pinned-message}
content-type) content-type)
[system-message-content message-data] [system-message-content message-data]
[user-message-content message-data context keyboard-shown]) [user-message-content message-data context keyboard-shown false])
[reactions/message-reactions-row chat-id message-id]]) [reactions/message-reactions-row message-data
[user-message-content message-data context keyboard-shown true]]])

View File

@ -0,0 +1,24 @@
(ns status-im2.contexts.chat.messages.drawers.style
(:require [quo2.foundations.colors :as colors]))
(def tab
{:flex-direction :row
:align-items :center
:justify-content :center})
(def tab-icon {:margin-right 4})
(defn tab-count
[active?]
{:color (if (or active? (colors/dark?)) colors/white colors/neutral-100)})
(def tabs-container
{:flex 1
:align-self :stretch
:padding-left 20
:padding-right 8
:margin-bottom 12})
(def authors-list
{:height 320
:flex 1})

View File

@ -6,7 +6,72 @@
[status-im2.common.not-implemented :as not-implemented] [status-im2.common.not-implemented :as not-implemented]
[status-im2.constants :as constants] [status-im2.constants :as constants]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]
[reagent.core :as reagent]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.contexts.chat.messages.drawers.style :as style]
[react-native.gesture :as gesture]))
(defn contact-list-item-fn
[{:keys [from compressed-key]}]
(let [[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity
from])
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
^{:key compressed-key}
[contact-list-item/contact-list-item
{:on-press #(rf/dispatch [:chat.ui/show-profile from])}
{:primary-name primary-name
:secondary-name secondary-name
:public-key from
:compressed-key compressed-key
:ens-verified ens-verified
:added? added?}]))
(defn get-tabs-data
[reaction-authors selected-tab reactions-order]
(map (fn [reaction-type-int]
(let [author-details (get reaction-authors reaction-type-int)]
{:id reaction-type-int
:accessibility-label (keyword (str "authors-for-reaction-" reaction-type-int))
:label [rn/view {:style style/tab}
[quo/icon
(get constants/reactions reaction-type-int)
{:no-color true
:container-style style/tab-icon}]
[quo/text
{:weight :medium
:size :paragraph-1
:style (style/tab-count (= selected-tab
reaction-type-int))}
(count author-details)]]}))
reactions-order))
(defn reaction-authors-comp
[selected-tab reaction-authors reactions-order]
[:<>
[rn/view style/tabs-container
[quo/tabs
{:size 32
:scrollable? true
:in-scroll-view? true
:on-change #(reset! selected-tab %)
:default-active @selected-tab
:data (get-tabs-data reaction-authors @selected-tab reactions-order)}]]
[gesture/flat-list
{:data (for [contact (get reaction-authors @selected-tab)]
contact)
:render-fn contact-list-item-fn
:key-fn :from
:style style/authors-list}]])
(defn reaction-authors
[reactions-order]
(let [{:keys [reaction-authors-list
selected-reaction]} (rf/sub [:chat/reactions-authors])
selected-tab (reagent/atom (or selected-reaction
(first (keys reaction-authors-list))))]
(fn []
[reaction-authors-comp selected-tab reaction-authors-list reactions-order])))
(defn pin-message (defn pin-message
[{:keys [chat-id pinned pinned-by] :as message-data}] [{:keys [chat-id pinned pinned-by] :as message-data}]

View File

@ -120,6 +120,7 @@
(reg-root-key-sub :chat/inputs-with-mentions :chat/inputs-with-mentions) (reg-root-key-sub :chat/inputs-with-mentions :chat/inputs-with-mentions)
(reg-root-key-sub :chats-home-list :chats-home-list) (reg-root-key-sub :chats-home-list :chats-home-list)
(reg-root-key-sub :chats/recording? :chats/recording?) (reg-root-key-sub :chats/recording? :chats/recording?)
(reg-root-key-sub :chat/reactions-authors :chat/reactions-authors)
;;lightbox ;;lightbox
(reg-root-key-sub :lightbox/exit-signal :lightbox/exit-signal) (reg-root-key-sub :lightbox/exit-signal :lightbox/exit-signal)