feat: audio component
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
0226a92c07
commit
e5913cc3ea
Binary file not shown.
After Width: | Height: | Size: 271 B |
Binary file not shown.
After Width: | Height: | Size: 367 B |
Binary file not shown.
After Width: | Height: | Size: 363 B |
Binary file not shown.
After Width: | Height: | Size: 524 B |
|
@ -522,7 +522,7 @@
|
||||||
seeking-audio?]
|
seeking-audio?]
|
||||||
[:f> soundtrack/f-soundtrack
|
[:f> soundtrack/f-soundtrack
|
||||||
{:audio-current-time-ms audio-current-time-ms
|
{:audio-current-time-ms audio-current-time-ms
|
||||||
:player-ref player-ref
|
:player-ref @player-ref
|
||||||
:seeking-audio? seeking-audio?}]])
|
:seeking-audio? seeking-audio?}]])
|
||||||
(when (or @recording? @reviewing-audio?)
|
(when (or @recording? @reviewing-audio?)
|
||||||
[:f> f-time-counter @recording? @recording-length-ms @ready-to-delete? @reviewing-audio?
|
[:f> f-time-counter @recording? @recording-length-ms @ready-to-delete? @reviewing-audio?
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
(let [player-ref (reagent/atom {})
|
(let [player-ref (reagent/atom {})
|
||||||
audio-current-time-ms (reagent/atom 0)]
|
audio-current-time-ms (reagent/atom 0)]
|
||||||
(h/render [:f> soundtrack/f-soundtrack
|
(h/render [:f> soundtrack/f-soundtrack
|
||||||
{:player-ref player-ref
|
{:player-ref @player-ref
|
||||||
:audio-current-time-ms audio-current-time-ms}])
|
:audio-current-time-ms audio-current-time-ms}])
|
||||||
(-> (h/expect (h/get-by-test-id "soundtrack"))
|
(-> (h/expect (h/get-by-test-id "soundtrack"))
|
||||||
(.toBeTruthy)))))
|
(.toBeTruthy)))))
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
audio-current-time-ms (reagent/atom 0)]
|
audio-current-time-ms (reagent/atom 0)]
|
||||||
(h/render [:f> soundtrack/f-soundtrack
|
(h/render [:f> soundtrack/f-soundtrack
|
||||||
{:seeking-audio? seeking-audio?
|
{:seeking-audio? seeking-audio?
|
||||||
:player-ref player-ref
|
:player-ref @player-ref
|
||||||
:audio-current-time-ms audio-current-time-ms}])
|
:audio-current-time-ms audio-current-time-ms}])
|
||||||
(h/fire-event
|
(h/fire-event
|
||||||
:on-sliding-start
|
:on-sliding-start
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
audio-current-time-ms (reagent/atom 0)]
|
audio-current-time-ms (reagent/atom 0)]
|
||||||
(h/render [:f> soundtrack/f-soundtrack
|
(h/render [:f> soundtrack/f-soundtrack
|
||||||
{:seeking-audio? seeking-audio?
|
{:seeking-audio? seeking-audio?
|
||||||
:player-ref player-ref
|
:player-ref @player-ref
|
||||||
:audio-current-time-ms audio-current-time-ms}])
|
:audio-current-time-ms audio-current-time-ms}])
|
||||||
(h/fire-event
|
(h/fire-event
|
||||||
:on-sliding-start
|
:on-sliding-start
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
audio-current-time-ms (reagent/atom 0)]
|
audio-current-time-ms (reagent/atom 0)]
|
||||||
(h/render [:f> soundtrack/f-soundtrack
|
(h/render [:f> soundtrack/f-soundtrack
|
||||||
{:seeking-audio? seeking-audio?
|
{:seeking-audio? seeking-audio?
|
||||||
:player-ref player-ref
|
:player-ref @player-ref
|
||||||
:audio-current-time-ms audio-current-time-ms}])
|
:audio-current-time-ms audio-current-time-ms}])
|
||||||
(h/fire-event
|
(h/fire-event
|
||||||
:on-sliding-start
|
:on-sliding-start
|
||||||
|
|
|
@ -10,12 +10,14 @@
|
||||||
(def ^:private thumb-dark (js/require "../resources/images/icons2/12x12/thumb-dark.png"))
|
(def ^:private thumb-dark (js/require "../resources/images/icons2/12x12/thumb-dark.png"))
|
||||||
|
|
||||||
(defn f-soundtrack
|
(defn f-soundtrack
|
||||||
[{:keys [audio-current-time-ms player-ref seeking-audio?]}]
|
[{:keys [audio-current-time-ms player-ref style seeking-audio?]}]
|
||||||
(let [audio-duration-ms (audio/get-player-duration @player-ref)]
|
(let [audio-duration-ms (audio/get-player-duration player-ref)]
|
||||||
[:<>
|
[:<>
|
||||||
[slider/slider
|
[slider/slider
|
||||||
{:test-ID "soundtrack"
|
{:test-ID "soundtrack"
|
||||||
:style (style/player-slider-container)
|
:style (merge
|
||||||
|
(style/player-slider-container)
|
||||||
|
(or style {}))
|
||||||
:minimum-value 0
|
:minimum-value 0
|
||||||
:maximum-value audio-duration-ms
|
:maximum-value audio-duration-ms
|
||||||
:value @audio-current-time-ms
|
:value @audio-current-time-ms
|
||||||
|
@ -23,7 +25,7 @@
|
||||||
:on-sliding-complete (fn [seek-time]
|
:on-sliding-complete (fn [seek-time]
|
||||||
(reset! seeking-audio? false)
|
(reset! seeking-audio? false)
|
||||||
(audio/seek-player
|
(audio/seek-player
|
||||||
@player-ref
|
player-ref
|
||||||
seek-time
|
seek-time
|
||||||
#(log/debug "[record-audio] on seek - seek time: " seek-time)
|
#(log/debug "[record-audio] on seek - seek time: " seek-time)
|
||||||
#(log/error "[record-audio] on seek - error: " %)))
|
#(log/error "[record-audio] on seek - error: " %)))
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
quo2.components.profile.select-profile.view
|
quo2.components.profile.select-profile.view
|
||||||
quo2.components.reactions.reaction
|
quo2.components.reactions.reaction
|
||||||
quo2.components.record-audio.record-audio.view
|
quo2.components.record-audio.record-audio.view
|
||||||
|
quo2.components.record-audio.soundtrack.view
|
||||||
quo2.components.selectors.disclaimer.view
|
quo2.components.selectors.disclaimer.view
|
||||||
quo2.components.selectors.filter.view
|
quo2.components.selectors.filter.view
|
||||||
quo2.components.selectors.selectors.view
|
quo2.components.selectors.selectors.view
|
||||||
|
@ -186,6 +187,7 @@
|
||||||
|
|
||||||
;;;; RECORD AUDIO
|
;;;; RECORD AUDIO
|
||||||
(def record-audio quo2.components.record-audio.record-audio.view/record-audio)
|
(def record-audio quo2.components.record-audio.record-audio.view/record-audio)
|
||||||
|
(def soundtrack quo2.components.record-audio.soundtrack.view/f-soundtrack)
|
||||||
|
|
||||||
;;;; SETTINGS
|
;;;; SETTINGS
|
||||||
(def privacy-option quo2.components.settings.privacy-option/card)
|
(def privacy-option quo2.components.settings.privacy-option/card)
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
(ns status-im2.contexts.chat.messages.content.audio.component-spec
|
||||||
|
(:require [status-im2.contexts.chat.messages.content.audio.view :as audio-message]
|
||||||
|
[test-helpers.component :as h]
|
||||||
|
[react-native.audio-toolkit :as audio]
|
||||||
|
[re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(def message
|
||||||
|
{:audio-duration-ms 5000
|
||||||
|
:message-id "message-id"})
|
||||||
|
|
||||||
|
(def context
|
||||||
|
{:in-pinned-view? false})
|
||||||
|
|
||||||
|
(defn setup-subs
|
||||||
|
[subs]
|
||||||
|
(doseq [keyval subs]
|
||||||
|
(re-frame/reg-sub
|
||||||
|
(key keyval)
|
||||||
|
(fn [_] (val keyval)))))
|
||||||
|
|
||||||
|
(h/describe "audio message"
|
||||||
|
(h/before-each
|
||||||
|
#(setup-subs {:mediaserver/port 1000}))
|
||||||
|
|
||||||
|
(h/test "renders correctly"
|
||||||
|
(h/render [audio-message/audio-message message context])
|
||||||
|
(h/is-truthy (h/get-by-label-text :audio-message-container)))
|
||||||
|
|
||||||
|
(h/test "press play calls audio/toggle-playpause-player"
|
||||||
|
(with-redefs [audio/toggle-playpause-player (js/jest.fn)
|
||||||
|
audio/new-player (fn [_ _ _] {})
|
||||||
|
audio/destroy-player #()
|
||||||
|
audio/prepare-player (fn [_ on-success _] (on-success))
|
||||||
|
audio-message/download-audio-http (fn [_ on-success] (on-success "audio-uri"))]
|
||||||
|
(h/render [audio-message/audio-message message context])
|
||||||
|
(h/fire-event
|
||||||
|
:on-press
|
||||||
|
(h/get-by-label-text :play-pause-audio-message-button))
|
||||||
|
(-> (h/expect audio/toggle-playpause-player)
|
||||||
|
(.toHaveBeenCalledTimes 1))))
|
||||||
|
|
||||||
|
(h/test "press play renders error"
|
||||||
|
(h/render [audio-message/audio-message message context])
|
||||||
|
(with-redefs [audio/toggle-playpause-player (fn [_ _ _ on-error] (on-error))
|
||||||
|
audio/new-player (fn [_ _ _] {})
|
||||||
|
audio/destroy-player #()
|
||||||
|
audio/prepare-player (fn [_ on-success _] (on-success))
|
||||||
|
audio-message/download-audio-http (fn [_ on-success] (on-success "audio-uri"))]
|
||||||
|
(h/fire-event
|
||||||
|
:on-press
|
||||||
|
(h/get-by-label-text :play-pause-audio-message-button))
|
||||||
|
(h/wait-for #(h/is-truthy (h/get-by-label-text :audio-error-label))))))
|
|
@ -0,0 +1,41 @@
|
||||||
|
(ns status-im2.contexts.chat.messages.content.audio.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]
|
||||||
|
[quo2.theme :as theme]))
|
||||||
|
|
||||||
|
(defn container
|
||||||
|
[]
|
||||||
|
{:width 295
|
||||||
|
:height 56
|
||||||
|
:border-radius 12
|
||||||
|
:border-width 1
|
||||||
|
:padding 12
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :space-between
|
||||||
|
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80)
|
||||||
|
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80-opa-40)})
|
||||||
|
|
||||||
|
(def play-pause-slider-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(def slider-container
|
||||||
|
{:position :absolute
|
||||||
|
:left 60
|
||||||
|
:right 71
|
||||||
|
:bottom nil})
|
||||||
|
|
||||||
|
(defn play-pause-container
|
||||||
|
[]
|
||||||
|
{:background-color (get-in colors/customization [:blue (if (theme/dark?) 60 50)])
|
||||||
|
:width 32
|
||||||
|
:height 32
|
||||||
|
:border-radius 16
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(def timestamp
|
||||||
|
{:margin-left 4})
|
||||||
|
|
||||||
|
(def error-label
|
||||||
|
{:margin-bottom 16})
|
|
@ -0,0 +1,204 @@
|
||||||
|
(ns status-im2.contexts.chat.messages.content.audio.view
|
||||||
|
(:require ["react-native-blob-util" :default ReactNativeBlobUtil]
|
||||||
|
[goog.string :as gstring]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[react-native.audio-toolkit :as audio]
|
||||||
|
[status-im2.contexts.chat.messages.content.audio.style :as style]
|
||||||
|
[react-native.platform :as platform]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(def ^:const media-server-uri-prefix "https://localhost:")
|
||||||
|
(def ^:const audio-path "/messages/audio")
|
||||||
|
(def ^:const uri-param "?messageId=")
|
||||||
|
|
||||||
|
(defonce active-players (atom {}))
|
||||||
|
(defonce audio-uris (atom {}))
|
||||||
|
(defonce progress-timer (atom nil))
|
||||||
|
(defonce current-player-key (reagent/atom nil))
|
||||||
|
|
||||||
|
(defn get-player-key
|
||||||
|
[message-id in-pinned-view?]
|
||||||
|
(str in-pinned-view? message-id))
|
||||||
|
|
||||||
|
(defn destroy-player
|
||||||
|
[player-key]
|
||||||
|
(when-let [player (@active-players player-key)]
|
||||||
|
(audio/destroy-player player)
|
||||||
|
(swap! active-players dissoc player-key)))
|
||||||
|
|
||||||
|
(defn update-state
|
||||||
|
[state new-state]
|
||||||
|
(when-not (= @state new-state)
|
||||||
|
(reset! state new-state)))
|
||||||
|
|
||||||
|
(defn seek-player
|
||||||
|
[player-key player-state value on-success]
|
||||||
|
(when-let [player (@active-players player-key)]
|
||||||
|
(audio/seek-player
|
||||||
|
player
|
||||||
|
value
|
||||||
|
#(when on-success (on-success))
|
||||||
|
#(update-state player-state :error))
|
||||||
|
(update-state player-state :seeking)))
|
||||||
|
|
||||||
|
(defn download-audio-http
|
||||||
|
[base64-uri on-success]
|
||||||
|
(-> (.config ReactNativeBlobUtil (clj->js {:trusty platform/ios?}))
|
||||||
|
(.fetch "GET" (str base64-uri))
|
||||||
|
(.then #(on-success (.base64 ^js %)))
|
||||||
|
(.catch #(log/error "could not fetch audio " base64-uri))))
|
||||||
|
|
||||||
|
(defn create-player
|
||||||
|
[{:keys [progress player-state player-key]} audio-url on-success]
|
||||||
|
(download-audio-http
|
||||||
|
audio-url
|
||||||
|
(fn [base64-data]
|
||||||
|
(let [player (audio/new-player
|
||||||
|
(str "data:audio/acc;base64," base64-data)
|
||||||
|
{:autoDestroy false
|
||||||
|
:continuesToPlayInBackground false}
|
||||||
|
(fn []
|
||||||
|
(update-state player-state :ready-to-play)
|
||||||
|
(reset! progress 0)
|
||||||
|
(when (and @progress-timer (= @current-player-key player-key))
|
||||||
|
(js/clearInterval @progress-timer)
|
||||||
|
(reset! progress-timer nil))))]
|
||||||
|
(swap! active-players assoc player-key player)
|
||||||
|
(audio/prepare-player
|
||||||
|
player
|
||||||
|
#(when on-success (on-success))
|
||||||
|
#(update-state player-state :error)))))
|
||||||
|
(update-state player-state :preparing))
|
||||||
|
|
||||||
|
(defn play-pause-player
|
||||||
|
[{:keys [player-key player-state progress message-id audio-duration-ms seeking-audio?
|
||||||
|
user-interaction?]
|
||||||
|
:as params}]
|
||||||
|
(let [mediaserver-port (rf/sub [:mediaserver/port])
|
||||||
|
audio-uri (str media-server-uri-prefix
|
||||||
|
mediaserver-port
|
||||||
|
audio-path
|
||||||
|
uri-param
|
||||||
|
message-id)
|
||||||
|
player (@active-players player-key)
|
||||||
|
playing? (= @player-state :playing)]
|
||||||
|
(when-not playing?
|
||||||
|
(reset! current-player-key player-key))
|
||||||
|
(if (and player
|
||||||
|
(= (@audio-uris player-key) audio-uri))
|
||||||
|
(audio/toggle-playpause-player
|
||||||
|
player
|
||||||
|
(fn []
|
||||||
|
(update-state player-state :playing)
|
||||||
|
(when @progress-timer
|
||||||
|
(js/clearInterval @progress-timer))
|
||||||
|
(reset! progress-timer
|
||||||
|
(js/setInterval
|
||||||
|
(fn []
|
||||||
|
(let [player (@active-players player-key)
|
||||||
|
current-time (audio/get-player-current-time player)
|
||||||
|
playing? (= @player-state :playing)]
|
||||||
|
(when (and playing? (not @seeking-audio?) (> current-time 0))
|
||||||
|
(reset! progress current-time))))
|
||||||
|
100)))
|
||||||
|
(fn []
|
||||||
|
(update-state player-state :ready-to-play)
|
||||||
|
(when (and @progress-timer user-interaction?)
|
||||||
|
(js/clearInterval @progress-timer)
|
||||||
|
(reset! progress-timer nil)))
|
||||||
|
#(update-state player-state :error))
|
||||||
|
(do
|
||||||
|
(swap! audio-uris assoc player-key audio-uri)
|
||||||
|
(destroy-player player-key)
|
||||||
|
(create-player params
|
||||||
|
audio-uri
|
||||||
|
(fn []
|
||||||
|
(reset! seeking-audio? false)
|
||||||
|
(if (> @progress 0)
|
||||||
|
(let [seek-time (* audio-duration-ms @progress)
|
||||||
|
checked-seek-time (min audio-duration-ms seek-time)]
|
||||||
|
(seek-player
|
||||||
|
player-key
|
||||||
|
player-state
|
||||||
|
checked-seek-time
|
||||||
|
#(play-pause-player params)))
|
||||||
|
(play-pause-player params))))))))
|
||||||
|
|
||||||
|
(defn f-audio-message
|
||||||
|
[player-state progress seeking-audio? {:keys [audio-duration-ms message-id]}
|
||||||
|
{:keys [in-pinned-view?]}]
|
||||||
|
(let [player-key (get-player-key message-id in-pinned-view?)
|
||||||
|
player (@active-players player-key)
|
||||||
|
duration (if (and player (not (#{:preparing :not-loaded :error} @player-state)))
|
||||||
|
(audio/get-player-duration player)
|
||||||
|
audio-duration-ms)
|
||||||
|
time-secs (quot
|
||||||
|
(if (or @seeking-audio? (#{:playing :seeking} @player-state))
|
||||||
|
(if (<= @progress 1) (* duration @progress) @progress)
|
||||||
|
duration)
|
||||||
|
1000)]
|
||||||
|
(rn/use-effect (fn [] #(destroy-player player-key)))
|
||||||
|
(rn/use-effect
|
||||||
|
(fn []
|
||||||
|
(when (and (some? @current-player-key)
|
||||||
|
(not= @current-player-key player-key)
|
||||||
|
(= @player-state :playing))
|
||||||
|
(play-pause-player {:player-key player-key
|
||||||
|
:player-state player-state
|
||||||
|
:progress progress
|
||||||
|
:message-id message-id
|
||||||
|
:audio-duration-ms duration
|
||||||
|
:seeking-audio? seeking-audio?
|
||||||
|
:user-interaction? false})))
|
||||||
|
[@current-player-key])
|
||||||
|
(if (= @player-state :error)
|
||||||
|
[quo/text
|
||||||
|
{:style style/error-label
|
||||||
|
:accessibility-label :audio-error-label
|
||||||
|
:weight :medium
|
||||||
|
:size :paragraph-2}
|
||||||
|
(i18n/label :error-loading-audio)]
|
||||||
|
[rn/view
|
||||||
|
{:accessibility-label :audio-message-container
|
||||||
|
:style (style/container)}
|
||||||
|
[rn/touchable-opacity
|
||||||
|
{:accessibility-label :play-pause-audio-message-button
|
||||||
|
:on-press #(play-pause-player {:player-key player-key
|
||||||
|
:player-state player-state
|
||||||
|
:progress progress
|
||||||
|
:message-id message-id
|
||||||
|
:audio-duration-ms duration
|
||||||
|
:seeking-audio? seeking-audio?
|
||||||
|
:user-interaction? true})
|
||||||
|
:style (style/play-pause-container)}
|
||||||
|
[quo/icon
|
||||||
|
(case @player-state
|
||||||
|
:preparing :i/loading
|
||||||
|
:playing :i/pause-audio
|
||||||
|
:i/play-audio)
|
||||||
|
{:size 20
|
||||||
|
:color colors/white}]]
|
||||||
|
[:f> quo/soundtrack
|
||||||
|
{:style style/slider-container
|
||||||
|
:audio-current-time-ms progress
|
||||||
|
:player-ref (@active-players player-key)
|
||||||
|
:seeking-audio? seeking-audio?}]
|
||||||
|
[quo/text
|
||||||
|
{:style style/timestamp
|
||||||
|
:accessibility-label :audio-duration-label
|
||||||
|
:weight :medium
|
||||||
|
:size :paragraph-2}
|
||||||
|
(gstring/format "%02d:%02d" (quot time-secs 60) (mod time-secs 60))]])))
|
||||||
|
|
||||||
|
(defn audio-message
|
||||||
|
[message context]
|
||||||
|
(let [player-state (reagent/atom :not-loaded)
|
||||||
|
progress (reagent/atom 0)
|
||||||
|
seeking-audio? (reagent/atom false)]
|
||||||
|
(fn []
|
||||||
|
[:f> f-audio-message player-state progress seeking-audio? message context])))
|
|
@ -14,6 +14,7 @@
|
||||||
[status-im2.contexts.chat.messages.content.album.view :as album]
|
[status-im2.contexts.chat.messages.content.album.view :as album]
|
||||||
[status-im2.contexts.chat.messages.avatar.view :as avatar]
|
[status-im2.contexts.chat.messages.avatar.view :as avatar]
|
||||||
[status-im2.contexts.chat.messages.content.image.view :as image]
|
[status-im2.contexts.chat.messages.content.image.view :as image]
|
||||||
|
[status-im2.contexts.chat.messages.content.audio.view :as audio]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[status-im.ui2.screens.chat.messages.message :as old-message]
|
[status-im.ui2.screens.chat.messages.message :as old-message]
|
||||||
|
@ -128,7 +129,7 @@
|
||||||
[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
|
||||||
[not-implemented/not-implemented [old-message/audio message-data]]
|
[audio/audio-message message-data context]
|
||||||
|
|
||||||
constants/content-type-image
|
constants/content-type-image
|
||||||
[image/image-message 0 message-data context on-long-press]
|
[image/image-message 0 message-data context on-long-press]
|
||||||
|
|
|
@ -2,19 +2,28 @@
|
||||||
(:require [quo2.core :as quo]
|
(:require [quo2.core :as quo]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]))
|
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]
|
||||||
|
[status-im2.constants :as constants]))
|
||||||
|
|
||||||
|
(defn message-text
|
||||||
|
[{:keys [content-type] :as message}]
|
||||||
|
(cond (= content-type constants/content-type-audio)
|
||||||
|
(i18n/label :audio-message)
|
||||||
|
:else
|
||||||
|
(get-in message [:content :parsed-text])))
|
||||||
|
|
||||||
(defn banner
|
(defn banner
|
||||||
[chat-id]
|
[chat-id]
|
||||||
(let [pinned-message (rf/sub [:chats/last-pinned-message chat-id])
|
(let [pinned-message (rf/sub [:chats/last-pinned-message chat-id])
|
||||||
latest-pin-text (get-in pinned-message [:content :parsed-text])
|
latest-pin-text (message-text pinned-message)
|
||||||
{:keys [deleted? deleted-for-me?]} pinned-message
|
{:keys [deleted? deleted-for-me?]} pinned-message
|
||||||
pins-count (rf/sub [:chats/pin-messages-count chat-id])
|
pins-count (rf/sub [:chats/pin-messages-count chat-id])
|
||||||
|
content-type-text? (= (:content-type pinned-message) constants/content-type-text)
|
||||||
latest-pin-text
|
latest-pin-text
|
||||||
(cond deleted? (i18n/label :t/message-deleted-for-everyone)
|
(cond deleted? (i18n/label :t/message-deleted-for-everyone)
|
||||||
deleted-for-me? (i18n/label :t/message-deleted-for-you)
|
deleted-for-me? (i18n/label :t/message-deleted-for-you)
|
||||||
:else (resolver/resolve-message latest-pin-text))]
|
content-type-text? (resolver/resolve-message latest-pin-text)
|
||||||
|
:else latest-pin-text)]
|
||||||
[quo/banner
|
[quo/banner
|
||||||
{:latest-pin-text latest-pin-text
|
{:latest-pin-text latest-pin-text
|
||||||
:pins-count pins-count
|
:pins-count pins-count
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
(ns status-im2.core-spec
|
(ns status-im2.core-spec
|
||||||
(:require
|
(:require
|
||||||
[status-im2.contexts.communities.actions.community-options.component-spec]))
|
[status-im2.contexts.communities.actions.community-options.component-spec]
|
||||||
|
[status-im2.contexts.chat.messages.content.audio.component-spec]))
|
||||||
|
|
|
@ -63,6 +63,11 @@
|
||||||
|
|
||||||
(def within rtl/within)
|
(def within rtl/within)
|
||||||
|
|
||||||
|
(defn wait-for
|
||||||
|
([condition] (wait-for condition {}))
|
||||||
|
([condition options]
|
||||||
|
(rtl/waitFor condition (clj->js options))))
|
||||||
|
|
||||||
(defn fire-event
|
(defn fire-event
|
||||||
([event-name node]
|
([event-name node]
|
||||||
(fire-event event-name node nil))
|
(fire-event event-name node nil))
|
||||||
|
|
|
@ -70,6 +70,14 @@ jest.mock("i18n-js", () => ({
|
||||||
t: (label) => `tx:${label}`
|
t: (label) => `tx:${label}`
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock("react-native-blob-util", () => ({
|
||||||
|
default: {
|
||||||
|
config: jest.fn().mockReturnValue({
|
||||||
|
fetch: jest.fn()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
NativeModules.ReactLocalization = {
|
NativeModules.ReactLocalization = {
|
||||||
language: 'en',
|
language: 'en',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
|
|
|
@ -2087,5 +2087,6 @@
|
||||||
"community-request-pending": "Request pending",
|
"community-request-pending": "Request pending",
|
||||||
"community-request-pending-body-text": "You requested to join",
|
"community-request-pending-body-text": "You requested to join",
|
||||||
"community-kicked-heading": "Kicked from community",
|
"community-kicked-heading": "Kicked from community",
|
||||||
"community-kicked-body": "You were kicked from"
|
"community-kicked-body": "You were kicked from",
|
||||||
|
"error-loading-audio": "Error while loading audio"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue