New composer - add audio comp (#15790)
* feat: composer - add audio comp
This commit is contained in:
parent
03aac0e4ce
commit
a973976123
|
@ -154,12 +154,12 @@
|
||||||
ready-to-send? (reagent/atom false)
|
ready-to-send? (reagent/atom false)
|
||||||
ready-to-lock? (reagent/atom false)
|
ready-to-lock? (reagent/atom false)
|
||||||
ready-to-delete? (reagent/atom false)
|
ready-to-delete? (reagent/atom false)
|
||||||
reviewing-audio? (reagent/atom false)
|
reviewing-audio? (reagent/atom (some? audio-file))
|
||||||
playing-audio? (reagent/atom false)
|
playing-audio? (reagent/atom false)
|
||||||
recording-length-ms (reagent/atom 0)
|
recording-length-ms (reagent/atom 0)
|
||||||
audio-current-time-ms (reagent/atom 0)
|
audio-current-time-ms (reagent/atom 0)
|
||||||
seeking-audio? (reagent/atom false)
|
seeking-audio? (reagent/atom false)
|
||||||
force-show-controls? (reagent/atom false)
|
force-show-controls? (reagent/atom (some? audio-file))
|
||||||
clear-timeout (atom nil)
|
clear-timeout (atom nil)
|
||||||
record-button-at-initial-position? (atom true)
|
record-button-at-initial-position? (atom true)
|
||||||
record-button-is-animating? (atom false)
|
record-button-is-animating? (atom false)
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
touch-active? (atom false)
|
touch-active? (atom false)
|
||||||
recording-timer (atom nil)
|
recording-timer (atom nil)
|
||||||
playing-timer (atom nil)
|
playing-timer (atom nil)
|
||||||
output-file (atom nil)
|
output-file (atom audio-file)
|
||||||
reached-max-duration? (atom false)
|
reached-max-duration? (atom false)
|
||||||
touch-timestamp (atom nil)
|
touch-timestamp (atom nil)
|
||||||
disabled? (atom false)
|
disabled? (atom false)
|
||||||
|
@ -512,10 +512,7 @@
|
||||||
(on-init reset-recorder))
|
(on-init reset-recorder))
|
||||||
(when audio-file
|
(when audio-file
|
||||||
(let [filename (last (string/split audio-file "/"))]
|
(let [filename (last (string/split audio-file "/"))]
|
||||||
(reload-player filename)
|
(reload-player filename)))))
|
||||||
(reset! output-file audio-file)
|
|
||||||
(reset! reviewing-audio? true)
|
|
||||||
(reset! force-show-controls? true)))))
|
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style style/bar-container
|
{:style style/bar-container
|
||||||
:pointer-events :box-none}
|
:pointer-events :box-none}
|
||||||
|
|
|
@ -57,6 +57,12 @@
|
||||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||||
{:db (assoc-in db [:chat/inputs current-chat-id :focused?] focused?)}))
|
{:db (assoc-in db [:chat/inputs current-chat-id :focused?] focused?)}))
|
||||||
|
|
||||||
|
(rf/defn set-input-audio
|
||||||
|
{:events [:chat.ui/set-input-audio]}
|
||||||
|
[{db :db} audio chat-id]
|
||||||
|
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||||
|
{:db (assoc-in db [:chat/inputs current-chat-id :audio] audio)}))
|
||||||
|
|
||||||
(rf/defn select-mention
|
(rf/defn select-mention
|
||||||
{:events [:chat.ui/select-mention]}
|
{:events [:chat.ui/select-mention]}
|
||||||
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]
|
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]
|
||||||
|
|
|
@ -18,4 +18,17 @@
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:right 0
|
:right 0
|
||||||
:z-index z-index
|
:z-index z-index
|
||||||
:background-color (colors/theme-colors colors/white colors/neutral-95)}))
|
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||||
|
:padding-vertical 3
|
||||||
|
:padding-left 2}))
|
||||||
|
|
||||||
|
(defn record-audio-container
|
||||||
|
[]
|
||||||
|
{:align-items :center
|
||||||
|
:background-color :transparent
|
||||||
|
:flex-direction :row
|
||||||
|
:position :absolute
|
||||||
|
:left -20
|
||||||
|
:right -20
|
||||||
|
:bottom 0
|
||||||
|
:height constants/composer-default-height})
|
||||||
|
|
|
@ -64,13 +64,58 @@
|
||||||
:i/arrow-up]])]))])
|
:i/arrow-up]])]))])
|
||||||
|
|
||||||
(defn audio-button
|
(defn audio-button
|
||||||
[]
|
[{:keys [record-permission? record-reset-fn]}
|
||||||
[quo/button
|
{:keys [recording? gesture-enabled?]}
|
||||||
{:on-press #(js/alert "to be added")
|
{:keys [container-opacity]}]
|
||||||
:icon true
|
(let [audio (rf/sub [:chats/sending-audio])]
|
||||||
:type :outline
|
[rn/view
|
||||||
:size 32}
|
{:style (style/record-audio-container)
|
||||||
:i/audio])
|
:pointer-events :box-none}
|
||||||
|
[quo/record-audio
|
||||||
|
{:record-audio-permission-granted record-permission?
|
||||||
|
:on-init (fn [reset-fn]
|
||||||
|
(reset! record-reset-fn reset-fn))
|
||||||
|
:on-start-recording (fn []
|
||||||
|
(reset! recording? true)
|
||||||
|
(reset! gesture-enabled? false)
|
||||||
|
(reanimated/animate container-opacity 1))
|
||||||
|
:audio-file audio
|
||||||
|
:on-reviewing-audio (fn [file]
|
||||||
|
(rf/dispatch [:chat.ui/set-input-audio file]))
|
||||||
|
:on-send (fn [{:keys [file-path duration]}]
|
||||||
|
(reset! recording? false)
|
||||||
|
(reset! gesture-enabled? true)
|
||||||
|
(rf/dispatch [:chat/send-audio file-path duration])
|
||||||
|
(reanimated/animate container-opacity
|
||||||
|
constants/empty-opacity)
|
||||||
|
(rf/dispatch [:chat.ui/set-input-audio nil]))
|
||||||
|
:on-cancel (fn []
|
||||||
|
(when @recording?
|
||||||
|
(reset! recording? false)
|
||||||
|
(reset! gesture-enabled? true)
|
||||||
|
(reanimated/animate container-opacity
|
||||||
|
constants/empty-opacity)
|
||||||
|
(rf/dispatch [:chat.ui/set-input-audio nil])))
|
||||||
|
:on-check-audio-permissions (fn []
|
||||||
|
(permissions/permission-granted?
|
||||||
|
:record-audio
|
||||||
|
#(reset! record-permission? %)
|
||||||
|
#(reset! record-permission? false)))
|
||||||
|
:on-request-record-audio-permission (fn []
|
||||||
|
(rf/dispatch
|
||||||
|
[:request-permissions
|
||||||
|
{:permissions [:record-audio]
|
||||||
|
:on-allowed
|
||||||
|
#(reset! record-permission? true)
|
||||||
|
:on-denied
|
||||||
|
#(js/setTimeout
|
||||||
|
(fn []
|
||||||
|
(alert/show-popup
|
||||||
|
(i18n/label :t/audio-recorder-error)
|
||||||
|
(i18n/label
|
||||||
|
:t/audio-recorder-permissions-error)))
|
||||||
|
50)}]))}]]))
|
||||||
|
|
||||||
|
|
||||||
(defn camera-button
|
(defn camera-button
|
||||||
[]
|
[]
|
||||||
|
@ -129,12 +174,14 @@
|
||||||
:i/format])
|
:i/format])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[props state animations window-height insets images?]
|
[props state animations window-height insets images? audio]
|
||||||
[rn/view {:style style/actions-container}
|
[rn/view {:style style/actions-container}
|
||||||
[rn/view {:style {:flex-direction :row}}
|
[rn/view
|
||||||
|
{:style {:flex-direction :row
|
||||||
|
:display (if @(:recording? state) :none :flex)}}
|
||||||
[camera-button]
|
[camera-button]
|
||||||
[image-button props animations insets]
|
[image-button props animations insets]
|
||||||
[reaction-button]
|
[reaction-button]
|
||||||
[format-button]]
|
[format-button]]
|
||||||
[send-button state animations window-height images?]
|
[send-button state animations window-height images?]
|
||||||
[audio-button]])
|
[audio-button props state animations audio]])
|
||||||
|
|
|
@ -78,12 +78,23 @@
|
||||||
(when-not edit-text
|
(when-not edit-text
|
||||||
(reset! editing? false))))
|
(reset! editing? false))))
|
||||||
|
|
||||||
|
(defn audio-effect
|
||||||
|
[{:keys [recording? gesture-enabled?]}
|
||||||
|
{:keys [container-opacity]}
|
||||||
|
audio]
|
||||||
|
(when (and audio (not @recording?))
|
||||||
|
(reset! recording? true)
|
||||||
|
(reset! gesture-enabled? false)
|
||||||
|
(reanimated/animate container-opacity 1)))
|
||||||
|
|
||||||
(defn empty-effect
|
(defn empty-effect
|
||||||
[{:keys [text-value maximized? focused?]}
|
[{:keys [text-value maximized? focused?]}
|
||||||
{:keys [container-opacity]}
|
{:keys [container-opacity]}
|
||||||
images?
|
images?
|
||||||
reply?]
|
reply?
|
||||||
(when (and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?))
|
audio]
|
||||||
|
(when
|
||||||
|
(and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?) (not audio))
|
||||||
(reanimated/animate-delay container-opacity constants/empty-opacity 200)))
|
(reanimated/animate-delay container-opacity constants/empty-opacity 200)))
|
||||||
|
|
||||||
(defn component-will-unmount
|
(defn component-will-unmount
|
||||||
|
@ -94,7 +105,7 @@
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply?
|
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply?
|
||||||
edit]
|
edit audio]
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(maximized-effect state animations dimensions chat-input)
|
(maximized-effect state animations dimensions chat-input)
|
||||||
|
@ -104,7 +115,8 @@
|
||||||
(background-effect state animations dimensions chat-input)
|
(background-effect state animations dimensions chat-input)
|
||||||
(images-or-reply-effect animations props images? reply?)
|
(images-or-reply-effect animations props images? reply?)
|
||||||
(edit-effect state props edit)
|
(edit-effect state props edit)
|
||||||
(empty-effect state animations images? reply?)
|
(audio-effect state animations audio)
|
||||||
|
(empty-effect state animations images? reply? audio)
|
||||||
(kb/add-kb-listeners props state animations dimensions keyboard-height)
|
(kb/add-kb-listeners props state animations dimensions keyboard-height)
|
||||||
#(component-will-unmount props))
|
#(component-will-unmount props))
|
||||||
[max-height]))
|
[max-height]))
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
(reanimated/set-shared-value saved-height min-height)
|
(reanimated/set-shared-value saved-height min-height)
|
||||||
(reanimated/animate opacity 0)
|
(reanimated/animate opacity 0)
|
||||||
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)
|
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)
|
||||||
(when (utils/empty-input? @text-value images reply)
|
(when (utils/empty-input? @text-value images reply nil)
|
||||||
(reanimated/animate container-opacity constants/empty-opacity))
|
(reanimated/animate container-opacity constants/empty-opacity))
|
||||||
(reanimated/animate gradient-opacity 0)
|
(reanimated/animate gradient-opacity 0)
|
||||||
(reset! lock-selection? true)
|
(reset! lock-selection? true)
|
||||||
|
@ -95,13 +95,16 @@
|
||||||
|
|
||||||
(defn change-text
|
(defn change-text
|
||||||
[text
|
[text
|
||||||
{:keys [input-ref]}
|
{:keys [input-ref record-reset-fn]}
|
||||||
{:keys [text-value cursor-position]}]
|
{:keys [text-value cursor-position recording?]}]
|
||||||
(reset! text-value text)
|
(reset! text-value text)
|
||||||
(reagent/next-tick #(when @input-ref
|
(reagent/next-tick #(when @input-ref
|
||||||
(.setNativeProps ^js @input-ref
|
(.setNativeProps ^js @input-ref
|
||||||
(clj->js {:selection {:start @cursor-position
|
(clj->js {:selection {:start @cursor-position
|
||||||
:end @cursor-position}}))))
|
:end @cursor-position}}))))
|
||||||
|
(when @recording?
|
||||||
|
(@record-reset-fn)
|
||||||
|
(reset! recording? false))
|
||||||
(rf/dispatch [:chat.ui/set-chat-input-text text]))
|
(rf/dispatch [:chat.ui/set-chat-input-text text]))
|
||||||
|
|
||||||
(defn selection-change
|
(defn selection-change
|
||||||
|
|
|
@ -143,13 +143,13 @@
|
||||||
:style style/gradient}])]))
|
:style style/gradient}])]))
|
||||||
|
|
||||||
(defn- f-view
|
(defn- f-view
|
||||||
[]
|
[recording?]
|
||||||
(let [reply (rf/sub [:chats/reply-message])
|
(let [reply (rf/sub [:chats/reply-message])
|
||||||
height (reanimated/use-shared-value (if reply constants/reply-container-height 0))]
|
height (reanimated/use-shared-value (if reply constants/reply-container-height 0))]
|
||||||
(rn/use-effect #(reanimated/animate height (if reply constants/reply-container-height 0)) [reply])
|
(rn/use-effect #(reanimated/animate height (if reply constants/reply-container-height 0)) [reply])
|
||||||
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
|
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
|
||||||
(when reply [reply-message reply true false false])]))
|
(when reply [reply-message reply true false recording?])]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[{:keys [recording?]}]
|
||||||
[:f> f-view])
|
[:f> f-view @recording?])
|
||||||
|
|
|
@ -55,18 +55,19 @@
|
||||||
:overflow :hidden}))
|
:overflow :hidden}))
|
||||||
|
|
||||||
(defn input
|
(defn input
|
||||||
[focused? saved-keyboard-height]
|
[{:keys [saved-emoji-kb-extra-height]}
|
||||||
|
{:keys [focused? recording?]}]
|
||||||
(merge typography/paragraph-1
|
(merge typography/paragraph-1
|
||||||
{:min-height constants/input-height
|
{:min-height constants/input-height
|
||||||
:color (colors/theme-colors :black :white)
|
:color (colors/theme-colors :black :white)
|
||||||
:text-align-vertical :top
|
:text-align-vertical :top
|
||||||
:flex 1
|
:flex 1
|
||||||
:z-index 1
|
:z-index 1
|
||||||
:position (if saved-keyboard-height :relative :absolute)
|
:position (if @saved-emoji-kb-extra-height :relative :absolute)
|
||||||
:top 0
|
:top 0
|
||||||
:left 0
|
:left 0
|
||||||
:right (when (or focused? platform/ios?) 0)}))
|
:right (when (or focused? platform/ios?) 0)
|
||||||
|
:display (if @recording? :none :flex)}))
|
||||||
(defn background
|
(defn background
|
||||||
[opacity background-y window-height]
|
[opacity background-y window-height]
|
||||||
(reanimated/apply-animations-to-style
|
(reanimated/apply-animations-to-style
|
||||||
|
|
|
@ -74,8 +74,8 @@
|
||||||
max-height))
|
max-height))
|
||||||
|
|
||||||
(defn empty-input?
|
(defn empty-input?
|
||||||
[text images reply?]
|
[text images reply? audio?]
|
||||||
(and (empty? text) (empty? images) (not reply?)))
|
(and (empty? text) (empty? images) (not reply?) (not audio?)))
|
||||||
|
|
||||||
(defn android-elevation?
|
(defn android-elevation?
|
||||||
[lines images reply? edit?]
|
[lines images reply? edit?]
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
:saved-emoji-kb-extra-height (atom nil)
|
:saved-emoji-kb-extra-height (atom nil)
|
||||||
:replying? (atom nil)
|
:replying? (atom nil)
|
||||||
:sending-images? (atom nil)
|
:sending-images? (atom nil)
|
||||||
:editing? (atom nil)}
|
:editing? (atom nil)
|
||||||
|
:record-permission? (atom nil)
|
||||||
|
:record-reset-fn (atom nil)}
|
||||||
state {:text-value (reagent/atom "")
|
state {:text-value (reagent/atom "")
|
||||||
:cursor-position (reagent/atom 0)
|
:cursor-position (reagent/atom 0)
|
||||||
:saved-cursor-position (reagent/atom 0)
|
:saved-cursor-position (reagent/atom 0)
|
||||||
|
@ -44,10 +46,12 @@
|
||||||
:lock-selection? (reagent/atom true)
|
:lock-selection? (reagent/atom true)
|
||||||
:focused? (reagent/atom false)
|
:focused? (reagent/atom false)
|
||||||
:lock-layout? (reagent/atom false)
|
:lock-layout? (reagent/atom false)
|
||||||
:maximized? (reagent/atom false)}]
|
:maximized? (reagent/atom false)
|
||||||
|
:recording? (reagent/atom false)}]
|
||||||
[:f>
|
[:f>
|
||||||
(fn []
|
(fn []
|
||||||
(let [images (rf/sub [:chats/sending-image])
|
(let [images (rf/sub [:chats/sending-image])
|
||||||
|
audio (rf/sub [:chats/sending-audio])
|
||||||
reply (rf/sub [:chats/reply-message])
|
reply (rf/sub [:chats/reply-message])
|
||||||
edit (rf/sub [:chats/edit-message])
|
edit (rf/sub [:chats/edit-message])
|
||||||
{:keys [input-text input-content-height]
|
{:keys [input-text input-content-height]
|
||||||
|
@ -74,7 +78,8 @@
|
||||||
(if (utils/empty-input?
|
(if (utils/empty-input?
|
||||||
input-text
|
input-text
|
||||||
images
|
images
|
||||||
reply)
|
reply
|
||||||
|
audio)
|
||||||
0.7
|
0.7
|
||||||
1))
|
1))
|
||||||
:height (reanimated/use-shared-value
|
:height (reanimated/use-shared-value
|
||||||
|
@ -102,14 +107,15 @@
|
||||||
keyboard-height
|
keyboard-height
|
||||||
(seq images)
|
(seq images)
|
||||||
reply
|
reply
|
||||||
edit)
|
edit
|
||||||
|
audio)
|
||||||
[gesture/gesture-detector
|
[gesture/gesture-detector
|
||||||
{:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
|
{:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (style/sheet-container insets state animations)
|
{:style (style/sheet-container insets state animations)
|
||||||
:on-layout #(handler/layout % state blur-height)}
|
:on-layout #(handler/layout % state blur-height)}
|
||||||
[sub-view/bar]
|
[sub-view/bar]
|
||||||
[reply/view reply]
|
[reply/view state]
|
||||||
[edit/view edit #(utils/cancel-edit-message state animations)]
|
[edit/view edit #(utils/cancel-edit-message state animations)]
|
||||||
[reanimated/touchable-opacity
|
[reanimated/touchable-opacity
|
||||||
{:active-opacity 1
|
{:active-opacity 1
|
||||||
|
@ -134,8 +140,7 @@
|
||||||
:multiline true
|
:multiline true
|
||||||
:placeholder (i18n/label :t/type-something)
|
:placeholder (i18n/label :t/type-something)
|
||||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||||
:style (style/input @(:focused? state)
|
:style (style/input props state)
|
||||||
@(:saved-emoji-kb-extra-height props))
|
|
||||||
:accessibility-label :chat-message-input}]
|
:accessibility-label :chat-message-input}]
|
||||||
[gradients/view props state animations show-bottom-gradient?]]
|
[gradients/view props state animations show-bottom-gradient?]]
|
||||||
[images/images-list]
|
[images/images-list]
|
||||||
|
|
|
@ -324,6 +324,13 @@
|
||||||
(fn [{:keys [metadata]}]
|
(fn [{:keys [metadata]}]
|
||||||
(:editing-message metadata)))
|
(:editing-message metadata)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:chats/sending-audio
|
||||||
|
:<- [:chats/current-chat-id]
|
||||||
|
:<- [:chat/inputs]
|
||||||
|
(fn [[chat-id inputs]]
|
||||||
|
(get-in inputs [chat-id :audio])))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/timeline-sending-image
|
:chats/timeline-sending-image
|
||||||
:<- [:chats/timeline-chat-input]
|
:<- [:chats/timeline-chat-input]
|
||||||
|
|
Loading…
Reference in New Issue