Fix pinned messages & replies

e8ceed11...213dc463

Both replies and pinned messages relied on subscribing their data from messages.

This worked only as long as we loaded the message in the database, so it would break say if another user replied to a message that wasn't in the current user view.

It also changes the way pinned messages are handled, before the notification was actually sent over the wire, but that's unnecessary, since it can be generated locally on both parts.
This is a bit of a breaking change with the previous version, since if you pin a message with this version, older version will not see a system message. this can be easily fixed by restoring the previous behavior of sending the message, but not sure it's worth it.

It also adds the ability to Delete message for everyone that have Deleted for me (discussed with John) and the ability of unpin messages that have been deleted for me.
This commit is contained in:
Andrea Maria Piana 2023-04-19 17:11:43 +01:00
parent fd7797322f
commit 2438af4e00
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
23 changed files with 311 additions and 262 deletions

View File

@ -239,10 +239,7 @@
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result])
(when pinned-message
(re-frame/dispatch [:pin-message/load-pin-messages
chat-id])))}]}
result]))}]}
(cancel-message-edit))))
(rf/defn send-current-message

View File

@ -32,16 +32,30 @@
;; TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
(message-list/rebuild-message-list {:db (update-in db [:messages chat-id] dissoc message-id)} chat-id))
(defn add-pinned-message
[acc chat-id message-id message]
(let [{:keys [pinned-by pinned-at] :as pinned-message}
(get-in acc [:db :pin-messages chat-id message-id])]
(if pinned-message
(assoc-in acc
[:db :pin-messages chat-id message-id]
(assoc
message
:pinned-by pinned-by
:pinned-at pinned-at))
acc)))
(defn add-message
[{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
(let [{:keys [replace from clock-value] :as message}
(data-store.messages/<-rpc (types/js->clj message-js))]
(data-store.messages/<-rpc (types/js->clj message-js))
acc-with-pinned-message (add-pinned-message acc chat-id message-id message)]
(if (message-loaded? db chat-id message-id)
;; If the message is already loaded, it means it's an update, that
;; happens when a message that was missing a reply had the reply
;; coming through, in which case we just insert the new message
(assoc-in acc [:db :messages chat-id message-id] message)
(cond-> acc
(assoc-in acc-with-pinned-message [:db :messages chat-id message-id] message)
(cond-> acc-with-pinned-message
;;add new message to db
:always
(update-in [:db :messages chat-id] assoc message-id message)

View File

@ -46,7 +46,10 @@
(update :quoted-message
set/rename-keys
{:parsedText :parsed-text :communityId :community-id})
{:parsedText :parsed-text
:deleted :deleted?
:deletedForMe :deleted-for-me?
:communityId :community-id})
(update :outgoing-status keyword)
(update :command-parameters
set/rename-keys

View File

@ -29,7 +29,8 @@
(rf/defn send-pin-message
[cofx pin-message]
{:json-rpc/call [{:method "wakuext_sendPinMessage"
:params [(messages/->rpc pin-message)]
:on-success #(log/debug "successfully pinned message" pin-message)
:on-error #(log/error "failed to pin message" % pin-message)}]})
{:json-rpc/call [{:method "wakuext_sendPinMessage"
:params [(messages/->rpc pin-message)]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to pin message" %)}]})

View File

@ -11,7 +11,6 @@
[status-im.data-store.activities :as data-store.activities]
[status-im.data-store.chats :as data-store.chats]
[status-im.data-store.invitations :as data-store.invitations]
[status-im.data-store.messages :as data-store.messages]
[status-im.data-store.reactions :as data-store.reactions]
[status-im.group-chats.core :as models.group]
[status-im.multiaccounts.login.core :as multiaccounts.login]
@ -44,7 +43,7 @@
^js removed-chats (.-removedChats response-js)
^js activity-notifications (.-activityCenterNotifications response-js)
^js activity-center-state (.-activityCenterState response-js)
^js pin-messages (.-pinMessages response-js)
^js pin-messages-js (.-pinMessages response-js)
^js removed-messages (.-removedMessages response-js)
^js visibility-status-updates (.-statusUpdates response-js)
^js current-visibility-status (.-currentStatus response-js)
@ -109,12 +108,12 @@
(process-next response-js sync-handler)
(browser/handle-bookmarks bookmarks-clj)))
(seq pin-messages)
(let [pin-messages (types/js->clj pin-messages)]
(seq pin-messages-js)
(do
(js-delete response-js "pinMessages")
(rf/merge cofx
(process-next response-js sync-handler)
(messages.pin/receive-signal (map data-store.messages/<-rpc pin-messages))))
(messages.pin/receive-signal pin-messages-js)))
(seq removed-chats)
(let [removed-chats-clj (types/js->clj removed-chats)]

View File

@ -258,8 +258,9 @@
(merge
(when in-popover? {:number-of-lines 2})
(cond
(= content-type constants/content-type-system-text) (system-text-style)
:else (default-text-style))))
(= content-type constants/content-type-system-text) (system-text-style)
(= content-type constants/content-type-system-pinned-message) (system-text-style)
:else (default-text-style))))
(defn emph-text-style
[]

View File

@ -9,7 +9,7 @@
[status-im2.constants :as constants]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.chat.photos :as photos]
[status-im2.contexts.chat.messages.avatar.view :as avatar]
[utils.re-frame :as rf]
[status-im.ui2.screens.chat.components.reply.style :as style]
[react-native.linear-gradient :as linear-gradient]))
@ -65,9 +65,9 @@
(i18n/label :t/message-deleted)]])
(defn reply-from
[{:keys [from identicon contact-name current-public-key]}]
[{:keys [from contact-name current-public-key]}]
[rn/view {:style style/reply-from}
[photos/member-photo from identicon 16]
[avatar/avatar from :xxxs]
[quo2.text/text
{:weight :semi-bold
:size :paragraph-2

View File

@ -31,7 +31,9 @@
(defn system-text?
[content-type]
(= content-type constants/content-type-system-text))
(or
(= content-type constants/content-type-system-text)
(= content-type constants/content-type-system-pinned-message)))
(defn mention-element
[from]
@ -142,11 +144,9 @@
(:parsed-text content))))
(defn quoted-message
[{:keys [message-id chat-id]} pin?]
(let [quoted-message (get @(re-frame/subscribe [:chats/chat-messages chat-id])
message-id)]
[rn/view {:style (when-not pin? (style/quoted-message-container))}
[components.reply/reply-message quoted-message false pin?]]))
[quoted-message pin?]
[rn/view {:style (when-not pin? (style/quoted-message-container))}
[components.reply/reply-message quoted-message false pin?]])
(defn message-not-sent-text
[chat-id message-id]

View File

@ -13,9 +13,13 @@
(def ^:const content-type-community 9)
(def ^:const content-type-gap 10)
(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 content-type-system-pinned-message 14)
;; Not implemented in status-go, only used for testing/ui work
(def ^:const content-type-gif 100)
(def ^:const content-type-link 101)
(def ^:const content-type-album 102)
(def ^:const contact-request-state-none 0)
(def ^:const contact-request-state-mutual 1)

View File

@ -23,11 +23,17 @@
(defn- get-message-content
[{:keys [content-type] :as message}]
(case content-type
constants/content-type-text (get-in message [:content :text])
constants/content-type-text [quo/text {:style style/tag-text}
(get-in message [:content :text])]
constants/content-type-image [old-message/message-content-image message]
constants/content-type-image [old-message/message-content-image message]
constants/content-type-sticker [old-message/sticker message]
constants/content-type-sticker [old-message/sticker message]
constants/content-type-system-pinned-message
[not-implemented/not-implemented
[quo/text {:style style/tag-text}
(get-in message [:content :text])]]
;; NOTE: The following type (system-text) doesn't have a design yet.
;; https://github.com/status-im/status-mobile/issues/14915

View File

@ -17,7 +17,7 @@
;; TODO (flexsurfer) probably we don't want reactions here
(if (or deleted? deleted-for-me?)
[content.deleted/deleted-message message context]
[message/message-with-reactions message context false]))
[message/message-with-reactions message context]))
(defn pinned-messages
[chat-id]

View File

@ -0,0 +1,19 @@
(ns status-im2.contexts.chat.messages.avatar.view
(:require [utils.re-frame :as rf]
[react-native.core :as rn]
[quo2.core :as quo]))
(defn avatar
[public-key size]
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
contact (rf/sub [:contacts/contact-by-address public-key])
photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path public-key]))
online? (rf/sub [:visibility-status-updates/online? public-key])]
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:chat.ui/show-profile public-key])}
[rn/view {:padding-top 2}
[quo/user-avatar
{:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size size}]]]))

View File

@ -26,10 +26,10 @@
(i18n/label :t/deleted-this-message)]])
(defn- compute-on-long-press-fn
[{:keys [deleted? pinned deleted-for-me?] :as message}
{:keys [message-pin-enabled] :as context}]
[{:keys [deleted?] :as message}
context]
;; only show drawer for user who has the permission to unpin messages
(when (and pinned (or deleted? deleted-for-me?) message-pin-enabled)
(when-not deleted?
(fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:show-bottom-sheet

View File

@ -1,6 +1,9 @@
(ns status-im2.contexts.chat.messages.content.pin.style
(:require [quo2.foundations.colors :as colors]))
(def system-message-default-size 36)
(def system-message-radius (/ system-message-default-size 2))
(def pin-indicator-container
{:margin-top 4
:margin-left 54
@ -16,3 +19,22 @@
(defn pinned-message-text
[]
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(def system-message-container
{:flex-direction :row :margin-vertical 8})
(def system-message-inner-container
{:width system-message-default-size
:height system-message-default-size
:margin-right system-message-radius
:border-radius system-message-default-size
:justify-content :center
:align-items :center
:background-color colors/primary-50-opa-10})
(def system-message-author-container
{:flex-direction :row :align-items :center})
(def system-message-timestamp-container
{:padding-left 5
:margin-top 2})

View File

@ -24,42 +24,33 @@
author-name]]))
(defn system-message
[{:keys [from in-popover? timestamp-str chat-id] :as message}]
(let [response-to (:response-to (:content message))
default-size 36]
[rn/touchable-opacity
{:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))
:active-opacity 1
:style (merge {:flex-direction :row :margin-vertical 8}
(old-style/message-wrapper message))}
[rn/view
{:style {:width default-size
:height default-size
:margin-right 16
:border-radius default-size
:justify-content :center
:align-items :center
:background-color colors/primary-50-opa-10}
:accessibility-label :content-type-pin-icon}
[quo/icon :i/pin {:color colors/primary-50 :size 16}]]
[rn/view
[rn/view {:style {:flex-direction :row :align-items :center}}
[rn/touchable-opacity
{:style old-style/message-author-touchable
:disabled in-popover?
:on-press #(rf/dispatch [:chat.ui/show-profile from])}
[old-message/message-author-name from {} 20]]
[quo/text
{:size :label
:style (style/pinned-message-text)}
(str " " (i18n/label :t/pinned-a-message))]
[rn/text
{:style (merge
{:padding-left 5
:margin-top 2}
(old-style/message-timestamp-text))
:accessibility-label :message-timestamp}
timestamp-str]]
[old-message/quoted-message {:message-id response-to :chat-id chat-id} true]]]))
[{:keys [from in-popover? quoted-message timestamp-str chat-id] :as message}]
[rn/touchable-opacity
{:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))
:active-opacity 1
:style (merge style/system-message-container
(old-style/message-wrapper message))}
[rn/view
{:style style/system-message-inner-container
:accessibility-label :content-type-pin-icon}
[quo/icon :i/pin {:color colors/primary-50 :size 16}]]
[rn/view
[rn/view {:style style/system-message-author-container}
[rn/touchable-opacity
{:style old-style/message-author-touchable
:disabled in-popover?
:on-press #(rf/dispatch [:chat.ui/show-profile from])}
[old-message/message-author-name from {} 20]]
[quo/text
{:size :label
:style (style/pinned-message-text)}
(str " " (i18n/label :t/pinned-a-message))]
[rn/text
{:style (merge
style/system-message-timestamp-container
(old-style/message-timestamp-text))
:accessibility-label :message-timestamp}
timestamp-str]]
[old-message/quoted-message quoted-message true]]])

View File

@ -12,6 +12,7 @@
[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]
[status-im2.contexts.chat.messages.avatar.view :as avatar]
[status-im2.contexts.chat.messages.content.image.view :as image]
[quo2.core :as quo]
[utils.re-frame :as rf]
@ -23,35 +24,24 @@
(def delivery-state-showing-time-ms 3000)
(defn avatar
[{:keys [content last-in-group? pinned quoted-message from]}]
(defn avatar-container
[{:keys [content last-in-group? pinned-by quoted-message from]}]
(if (or (and (seq (:response-to content))
quoted-message)
last-in-group?
pinned)
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
contact (rf/sub [:contacts/contact-by-address from])
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))
online? (rf/sub [:visibility-status-updates/online? from])]
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:chat.ui/show-profile from])}
[rn/view {:padding-top 2 :width 32}
[quo/user-avatar
{:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small}]]])
pinned-by)
[avatar/avatar from :small]
[rn/view {:padding-top 2 :width 32}]))
(defn author
[{:keys [response-to
compressed-key
last-in-group?
pinned
pinned-by
quoted-message
from
timestamp]}]
(when (or (and (seq response-to) quoted-message) last-in-group? pinned)
(when (or (and (seq response-to) quoted-message) last-in-group? pinned-by)
(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
@ -65,17 +55,18 @@
(defn system-message-content
[{:keys [content-type quoted-message] :as message-data}]
(if quoted-message
[not-implemented/not-implemented [pin/system-message message-data]]
[pin/system-message message-data]
(case content-type
constants/content-type-system-text [not-implemented/not-implemented
[system.text/text-content message-data]]
constants/content-type-system-text [system.text/text-content message-data]
constants/content-type-community [not-implemented/not-implemented
[old-message/community message-data]]
constants/content-type-system-pinned-message [system.text/text-content message-data]
constants/content-type-contact-request [not-implemented/not-implemented
[old-message/system-contact-request message-data]])))
constants/content-type-community [not-implemented/not-implemented
[old-message/community message-data]]
constants/content-type-contact-request [not-implemented/not-implemented
[old-message/system-contact-request message-data]])))
(defn on-long-press
[message-data context]
@ -87,7 +78,7 @@
[]
(let [show-delivery-state? (reagent/atom false)]
(fn [{:keys [content-type quoted-message content outgoing outgoing-status] :as message-data}
{:keys [chat-id] :as context}
context
keyboard-shown]
(let [first-image (first (:album message-data))
outgoing-status (if (= content-type constants/content-type-album)
@ -117,11 +108,11 @@
:on-long-press #(on-long-press message-data context)}
[rn/view {:style {:padding-vertical 8}}
(when (and (seq response-to) quoted-message)
[old-message/quoted-message {:message-id response-to :chat-id chat-id}])
[old-message/quoted-message quoted-message])
[rn/view
{:style {:padding-horizontal 12
:flex-direction :row}}
[avatar message-data]
[avatar-container message-data]
[rn/view
{:style {:margin-left 8
:flex 1}}
@ -159,6 +150,7 @@
(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}
content-type)
[system-message-content message-data]

View File

@ -20,7 +20,7 @@
(assoc message-data :pinned message-not-pinned?)]))))
(defn get-actions
[{:keys [outgoing content pinned outgoing-status deleted? deleted-for-me? content-type]
[{:keys [outgoing content pinned-by outgoing-status deleted? deleted-for-me? content-type]
:as message-data}
{:keys [able-to-send-message? community? can-delete-message-for-everyone?
message-pin-enabled group-chat group-admin?]}]
@ -54,15 +54,17 @@
:icon :i/copy
:id :copy}])
;; pinning images are temporarily disabled
(when (and message-pin-enabled (not= content-type constants/content-type-image))
(when (and message-pin-enabled
(not (or deleted? deleted-for-me?))
(not= content-type constants/content-type-image))
[{:type :main
:on-press #(pin-message message-data)
:label (i18n/label (if pinned
:label (i18n/label (if pinned-by
(if community? :t/unpin-from-channel :t/unpin-from-chat)
(if community? :t/pin-to-channel :t/pin-to-chat)))
:icon :i/pin
:id (if pinned :unpin :pin)}])
(when-not (or pinned deleted? deleted-for-me?)
:id (if pinned-by :unpin :pin)}])
(when-not (or deleted? deleted-for-me?)
[{:type :danger
:on-press (fn []
(rf/dispatch
@ -74,12 +76,11 @@
:icon :i/delete
:id :delete-for-me}])
(when (cond
deleted? false
deleted-for-me? false
outgoing true
community? can-delete-message-for-everyone?
group-chat group-admin?
:else false)
deleted? false
outgoing true
community? can-delete-message-for-everyone?
group-chat group-admin?
:else false)
[{:type :danger
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])

View File

@ -27,12 +27,10 @@
(defn banner
[chat-id]
(let [pinned-messages (rf/sub [:chats/pinned-sorted-list chat-id])
latest-pinned-message-id (-> pinned-messages last :message-id)
latest-pinned-message (get (rf/sub [:chats/chat-messages chat-id]) latest-pinned-message-id)
latest-pin-text (get-in latest-pinned-message [:content :parsed-text])
{:keys [deleted? deleted-for-me?]} latest-pinned-message
pins-count (count pinned-messages)
(let [pinned-message (rf/sub [:chats/last-pinned-message chat-id])
latest-pin-text (get-in pinned-message [:content :parsed-text])
{:keys [deleted? deleted-for-me?]} pinned-message
pins-count (rf/sub [:chats/pin-messages-count chat-id])
latest-pin-text
(cond deleted? (i18n/label :t/message-deleted-for-everyone)

View File

@ -2,7 +2,7 @@
(:require [quo2.foundations.colors :as colors]
[re-frame.core :as re-frame]
[status-im.data-store.pin-messages :as data-store.pin-messages]
[status-im.transport.message.protocol :as protocol]
[status-im.data-store.messages :as data-store.messages]
[status-im2.common.toasts.events :as toasts]
[status-im2.constants :as constants]
[status-im2.contexts.chat.messages.list.events :as message-list]
@ -33,34 +33,48 @@
(assoc-in [:pagination-info chat-id :all-pin-loaded?]
(empty? cursor)))}))
(defn remove-pinned-message
[db pinned-message]
(update-in db
[:pin-messages (aget pinned-message "localChatId")]
dissoc
(aget pinned-message "message_id")))
(defn add-pinned-message
[db pinned-message]
(let [message (aget pinned-message "pinnedMessage")]
(if (and message
(aget message "message"))
(assoc-in db
[:pin-messages
(aget pinned-message "localChatId")
(aget pinned-message "message_id")]
(-> (aget message "message")
(js->clj :keywordize-keys true)
data-store.messages/<-rpc
(assoc :pinned-by (aget message "pinnedBy")
:pinned-at (aget message "pinnedAt"))))
db)))
(rf/defn receive-signal
[{:keys [db]} pin-messages]
(let [{:keys [chat-id]} (first pin-messages)]
(when (= chat-id (db :current-chat-id))
(let [{:keys [chat-id]} (first pin-messages)
already-loaded-pin-messages (get-in db [:pin-messages chat-id] {})
already-loaded-messages (get-in db [:messages chat-id] {})
all-messages (reduce (fn [acc {:keys [message_id pinned from]}]
;; Add to or remove from pinned message list, and
;; normalizing pinned-by property
(let [current-message (get already-loaded-messages
message_id)
current-message-pin (merge current-message
{:pinned pinned
:pinned-by from})]
(cond-> acc
(nil? pinned)
(dissoc message_id)
(and (some? pinned) (some? current-message))
(assoc message_id current-message-pin))))
already-loaded-pin-messages
pin-messages)]
{:db (-> db
(assoc-in [:pin-messages chat-id] all-messages)
(assoc-in [:pin-message-lists chat-id]
(message-list/add-many nil (vals all-messages))))}))))
(let [current-chat-id (db :current-chat-id)
db (reduce (fn [db pin-message]
(let [pinned? (aget pin-message "pinned")
chat-id (aget pin-message "localChatId")]
(cond
(not= chat-id current-chat-id)
db
pinned?
(add-pinned-message db pin-message)
:else
(remove-pinned-message db pin-message))))
db
pin-messages)]
{:db
(assoc-in db
[:pin-message-lists current-chat-id]
(message-list/add-many nil (vals (get-in db [:pin-messages current-chat-id]))))}))
(rf/defn send-pin-message-locally
"Pin message, rebuild pinned messages list locally"
@ -84,20 +98,11 @@
"Pin message, rebuild pinned messages list"
{:events [:pin-message/send-pin-message]}
[{:keys [db] :as cofx} {:keys [chat-id message-id pinned remote-only?] :as pin-message}]
(let [current-public-key (get-in db [:multiaccount :public-key])
message (merge pin-message {:pinned-by current-public-key})
preferred-name (get-in db [:multiaccount :preferred-name])]
(rf/merge cofx
(when-not remote-only? (send-pin-message-locally pin-message))
(data-store.pin-messages/send-pin-message {:chat-id (pin-message :chat-id)
:message_id (pin-message :message-id)
:pinned (pin-message :pinned)})
(when pinned
(protocol/send-chat-messages [{:chat-id (pin-message :chat-id)
:content-type constants/content-type-system-text
:text "pinned a message"
:response-to (pin-message :message-id)
:ens-name preferred-name}])))))
(rf/merge cofx
(when-not remote-only? (send-pin-message-locally pin-message))
(data-store.pin-messages/send-pin-message {:chat-id (pin-message :chat-id)
:message_id (pin-message :message-id)
:pinned (pin-message :pinned)})))
(rf/defn load-pin-messages
{:events [:pin-message/load-pin-messages]}

View File

@ -0,0 +1,36 @@
(ns status-im2.contexts.chat.messages.pin.events-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im2.contexts.chat.messages.pin.events :as events]))
(deftest receive-signal-test
(let [chat-id "chat-id"
message-id-1 "0x1"
message-id-2 "0x2"
message-id-3 "0x3"
message-1 {:id message-id-1 :whisperTimestamp 1 :timestamp 1 :clock 2}
message-3 {:id message-id-3 :whisperTimestamp 1 :timestamp 1 :clock 2}
db {:current-chat-id chat-id
:pin-messages {chat-id {message-id-1 {}
message-id-2 {}}}}]
(testing "receiving a pinned messages update"
(let [pinned-messages-signal (clj->js [{:pinned true
:localChatId chat-id
:message_id message-id-1
:pinnedMessage {:pinnedAt 1
:pinnedBy "0x1"
:message message-1}}
{:pinned false
:localChatId chat-id
:message_id message-id-2}
{:pinned true
:localChatId chat-id
:message_id message-id-3
:pinnedMessage {:pinnedAt 1
:pinnedBy "0x1"
:message message-3}}])
actual (events/receive-signal {:db db}
pinned-messages-signal)
]
(is (not (get-in actual [:db :pin-messages chat-id message-id-2])))
(is (get-in actual [:db :pin-messages chat-id message-id-1 :message-id]))
(is (get-in actual [:db :pin-messages chat-id message-id-3 :message-id]))))))

View File

@ -146,22 +146,9 @@
(re-frame/reg-sub
:chats/pinned
(fn [[_ chat-id] _]
[(re-frame/subscribe [:messages/pin-messages])
(re-frame/subscribe [:chats/chat-messages chat-id])])
(fn [[pin-messages messages] [_ chat-id]]
(let [pinned-messages (get pin-messages chat-id {})]
(reduce-kv
(fn [pinned-messages pinned-message-id pinned-message]
(let [{:keys [deleted? deleted-for-me? deleted-by]} (get messages pinned-message-id)
pinned-message (assoc pinned-message
:deleted? deleted?
:deleted-for-me? deleted-for-me?
:deleted-by deleted-by
:pinned true)]
(assoc pinned-messages pinned-message-id pinned-message)))
pinned-messages
pinned-messages))))
:<- [:messages/pin-messages]
(fn [pinned-messages [_ chat-id] _]
(get pinned-messages chat-id)))
;; local messages will not have a :pinned-at key until user navigates away and to
;; chat screen. For this reason we want to retain order of local messages with :pinned-at nil
@ -180,9 +167,22 @@
(re-frame/subscribe [:chats/pinned chat-id]))
(fn [pin-messages _]
(let [pin-messages-vals (vals pin-messages)]
(sort-by :pinned-at sort-pinned pin-messages-vals))))
(re-frame/reg-sub
:chats/last-pinned-message
(fn [[_ chat-id]]
(re-frame/subscribe [:chats/pinned-sorted-list chat-id]))
(fn [pin-messages _]
(last pin-messages)))
(re-frame/reg-sub
:chats/pin-messages-count
(fn [[_ chat-id]]
(re-frame/subscribe [:chats/pinned chat-id]))
(fn [pinned-messages _]
(count pinned-messages)))
(re-frame/reg-sub
:chats/pin-modal
:<- [:messages/pin-modal]

View File

@ -109,92 +109,52 @@
(testing "It sorts three messages with pinned-at property"
(swap! rf-db/app-db assoc :pin-messages pinned-messages-state)
(is
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 1000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 2000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x3
:pinned-at 3000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}]
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 1000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 2000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x3
:pinned-at 3000
:pinned-by :test-user}]
(rf/sub [sub-name :0xChat]))))
(testing "It sorts messages from backend with pinned-at property and 1 new local pinned message"
(swap! rf-db/app-db assoc :pin-messages pinned-messages-state-with-1-new-local-message)
(is
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 2000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 3000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x3
:pinned-at nil
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}]
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 2000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 3000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x3
:pinned-at nil
:pinned-by :test-user}]
(rf/sub [sub-name :0xChat]))))
(testing "It sorts messages from backend with pinned-at property and 2 new local pinned messages"
(swap! rf-db/app-db assoc :pin-messages pinned-messages-state-with-2-new-local-messages)
(is
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 2000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 3000
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x3
:pinned-at nil
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}
{:chat-id :0xChat
:message-id :0x4
:pinned-at nil
:pinned-by :test-user
:pinned true
:deleted? nil
:deleted-for-me? nil
:deleted-by nil}]
(= [{:chat-id :0xChat
:message-id :0x1
:pinned-at 2000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x2
:pinned-at 3000
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x3
:pinned-at nil
:pinned-by :test-user}
{:chat-id :0xChat
:message-id :0x4
:pinned-at nil
:pinned-by :test-user}]
(rf/sub [sub-name :0xChat])))))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.146.4",
"commit-sha1": "e8ceed11125dfd470c0e0caac0755313fb85cba6",
"src-sha256": "1flwq5sfy1cfdl40fiip0q555rdcq5f5l2lpb4az8j5bwmwmi31x"
"version": "v0.147.1",
"commit-sha1": "213dc463bcc1ae449bc78b6cf7c598c4f68830c5",
"src-sha256": "1q00agdsqc4p16l8d5cv88gwfnpnl7bb61mayc3520c82hw93q3r"
}