[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
:accessibility-label :emoji-reaction-add
:style (style/add-reaction)}
[icons/icon :i/add
[icons/icon :i/add-reaction
{:size 20
:color (if dark?
colors/white
@ -21,10 +21,11 @@
(defn reaction
"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)]
[rn/touchable-opacity
{:on-press on-press
:on-long-press on-long-press
:accessibility-label accessibility-label
:style (style/reaction neutral?)}
[icons/icon emoji

View File

@ -6,7 +6,8 @@
[react-native.masked-view :as masked-view]
[reagent.core :as reagent]
[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 unread-count-offset 3)
@ -131,7 +132,8 @@
style
size
blur?
override-theme]
override-theme
in-scroll-view?]
:or {fade-end-percentage fade-end-percentage
fade-end? false
scrollable? false
@ -142,7 +144,9 @@
[rn/view {:style {:margin-top (- (dec unread-count-offset))}}
[masked-view-wrapper
{: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
(dissoc props
:default-active

View File

@ -4,7 +4,8 @@
[status-im.data-store.reactions :as data-store.reactions]
[status-im.transport.message.protocol :as message.protocol]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
(defn update-reaction
[acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
@ -94,3 +95,42 @@
acc))
[]
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]}
[{:keys [db]} identity ens-name]
(let [my-public-key (get-in db [:multiaccount :public-key])]
(when (not= my-public-key identity)
(if (not= my-public-key identity)
{:db (-> db
(assoc :contacts/identity identity)
(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})
(defn sheet
[{:keys [top bottom]} window-height override-theme shell?]
[{:keys [top bottom]} window-height override-theme padding-bottom-override shell?]
{:position :absolute
:max-height (- window-height top 20)
:z-index 1
@ -22,9 +22,9 @@
:right 0
:border-top-left-radius 20
:border-top-right-radius 20
:overflow :hidden
:overflow (when shell? :hidden)
:flex 1
:padding-bottom (max 20 bottom)
:padding-bottom (or padding-bottom-override (max 20 bottom))
:background-color (if shell?
:transparent
(colors/theme-colors colors/white colors/neutral-90 override-theme))})

View File

@ -13,7 +13,9 @@
(def timing-options #js {:duration duration})
(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
;; so we have to use timeout, also we add 50ms for safety
(js/setTimeout #(rf/dispatch [:bottom-sheet-hidden]) (+ duration 50))
@ -29,7 +31,7 @@
(def gesture-values (atom {}))
(defn get-sheet-gesture
[translate-y bg-opacity window-height]
[translate-y bg-opacity window-height on-close]
(-> (gesture/gesture-pan)
(gesture/on-start
(fn [_]
@ -47,17 +49,22 @@
(fn [_]
(if (< (:dy @gesture-values) 0)
(show translate-y bg-opacity)
(hide translate-y bg-opacity window-height))))))
(hide translate-y bg-opacity window-height on-close))))))
(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)
bg-opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value window-height)
sheet-gesture (get-sheet-gesture translate-y bg-opacity window-height)]
(rn/use-effect #(if hide? (hide translate-y bg-opacity window-height) (show translate-y bg-opacity))
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 on-close) (show translate-y bg-opacity))
[hide?])
(hooks/use-back-handler #(do (rf/dispatch [:hide-bottom-sheet]) true))
(hooks/use-back-handler #(do (when (fn? on-close)
(on-close))
(rf/dispatch [:hide-bottom-sheet])
true))
[rn/view {:flex 1}
;; backdrop
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:hide-bottom-sheet])}
@ -70,7 +77,7 @@
[reanimated/view
{:style (reanimated/apply-animations-to-style
{: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?
[blur/ios-view

View File

@ -5,26 +5,61 @@
[utils.re-frame :as rf]
[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
[chat-id message-id]
[{:keys [message-id chat-id]} user-message-content]
(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]
^{:key (str emoji-reaction)}
[rn/view
{:style {:margin-left 52
:margin-bottom 12
:flex-direction :row}}
(for [{:keys [own emoji-id quantity emoji-reaction-id]
:as emoji-reaction} reactions]
^{:key emoji-reaction}
[rn/view {:style {:margin-right 6}}
[quo/reaction
{:emoji (get constants/reactions emoji-id)
:neutral? own
:clicks quantity
:on-press (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}]))
:on-press #(on-press own message-id emoji-id emoji-reaction-id)
:on-long-press (fn []
(on-long-press message-id
emoji-id)
(show-authors-sheet user-message-content
reactions))
:accessibility-label (str "emoji-reaction-" emoji-id)}]])
[quo/add-reaction
{:on-press (fn []
@ -32,4 +67,7 @@
(rf/dispatch
[:show-bottom-sheet
{:content (fn [] [drawers/reactions
{:chat-id chat-id :message-id message-id}])}]))}]])))
{: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]
[utils.datetime :as datetime]
[reagent.core :as reagent]
[utils.address :as address]))
[utils.address :as address]
[react-native.gesture :as gesture]))
(def delivery-state-showing-time-ms 3000)
(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))
quoted-message)
last-in-group?
pinned-by)
pinned-by
message-reaction-view?)
[avatar/avatar from :small]
[rn/view {:padding-top 2 :width 32}]))
@ -43,8 +45,9 @@
pinned-by
quoted-message
from
timestamp]}]
(when (or (and (seq response-to) quoted-message) last-in-group? pinned-by)
timestamp]}
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])
{:keys [ens-verified added?]} (rf/sub [:contacts/contact-by-address from])]
[quo/author
@ -82,7 +85,8 @@
(let [show-delivery-state? (reagent/atom false)]
(fn [{:keys [content-type quoted-message content outgoing outgoing-status] :as message-data}
context
keyboard-shown]
keyboard-shown
message-reaction-view?]
(let [first-image (first (:album message-data))
outgoing-status (if (= content-type constants/content-type-album)
(:outgoing-status first-image)
@ -91,7 +95,8 @@
(:outgoing first-image)
outgoing)
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
{:accessibility-label (if (and outgoing (= outgoing-status :sending))
:message-sending
@ -115,14 +120,18 @@
[rn/view
{:style {:padding-horizontal 12
:flex-direction :row}}
[avatar-container message-data]
[rn/view
{:style {:margin-left 8
:flex 1}}
[author message-data]
[avatar-container message-data message-reaction-view?]
(into
(if message-reaction-view?
[gesture/scroll-view]
[rn/view])
[{: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
[not-implemented/not-implemented [old-message/emoji message-data]]
@ -134,18 +143,18 @@
[audio/audio-message message-data context]
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
[album/album-message message-data context on-long-press]
[not-implemented/not-implemented [content.unknown/unknown-content message-data]])
(when @show-delivery-state?
[status/status outgoing-status])]]]]))))
[status/status outgoing-status])])]]]))))
(defn message-with-reactions
[{:keys [pinned-by mentioned in-pinned-view? content-type last-in-group? message-id] :as message-data}
{:keys [chat-id] :as context}
[{:keys [pinned-by mentioned in-pinned-view? content-type last-in-group?] :as message-data}
context
keyboard-shown]
[rn/view
{:style (style/message-container in-pinned-view? pinned-by mentioned last-in-group?)
@ -153,9 +162,10 @@
(when pinned-by
[pin/pinned-by-view pinned-by])
(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)
[system-message-content message-data]
[user-message-content message-data context keyboard-shown])
[reactions/message-reactions-row chat-id message-id]])
[user-message-content message-data context keyboard-shown false])
[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.constants :as constants]
[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
[{: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 :chats-home-list :chats-home-list)
(reg-root-key-sub :chats/recording? :chats/recording?)
(reg-root-key-sub :chat/reactions-authors :chat/reactions-authors)
;;lightbox
(reg-root-key-sub :lightbox/exit-signal :lightbox/exit-signal)