New composer - add audio comp (#15790)

* feat: composer - add audio comp
This commit is contained in:
Omar Basem 2023-05-03 09:54:23 +04:00 committed by GitHub
parent 03aac0e4ce
commit a973976123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 133 additions and 42 deletions

View File

@ -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}

View File

@ -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}]

View File

@ -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})

View File

@ -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]])

View File

@ -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]))

View File

@ -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

View File

@ -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?])

View File

@ -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

View File

@ -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?]

View File

@ -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]

View File

@ -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]