diff --git a/src/quo2/components/record_audio/record_audio/view.cljs b/src/quo2/components/record_audio/record_audio/view.cljs index 755f4315b7..a487af8e17 100644 --- a/src/quo2/components/record_audio/record_audio/view.cljs +++ b/src/quo2/components/record_audio/record_audio/view.cljs @@ -154,12 +154,12 @@ ready-to-send? (reagent/atom false) ready-to-lock? (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) recording-length-ms (reagent/atom 0) audio-current-time-ms (reagent/atom 0) seeking-audio? (reagent/atom false) - force-show-controls? (reagent/atom false) + force-show-controls? (reagent/atom (some? audio-file)) clear-timeout (atom nil) record-button-at-initial-position? (atom true) record-button-is-animating? (atom false) @@ -169,7 +169,7 @@ touch-active? (atom false) recording-timer (atom nil) playing-timer (atom nil) - output-file (atom nil) + output-file (atom audio-file) reached-max-duration? (atom false) touch-timestamp (atom nil) disabled? (atom false) @@ -512,10 +512,7 @@ (on-init reset-recorder)) (when audio-file (let [filename (last (string/split audio-file "/"))] - (reload-player filename) - (reset! output-file audio-file) - (reset! reviewing-audio? true) - (reset! force-show-controls? true))))) + (reload-player filename))))) [rn/view {:style style/bar-container :pointer-events :box-none} diff --git a/src/status_im/chat/models/input.cljs b/src/status_im/chat/models/input.cljs index 8c5c4dc438..8b47a2e787 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im/chat/models/input.cljs @@ -57,6 +57,12 @@ (let [current-chat-id (or chat-id (:current-chat-id db))] {: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 {:events [:chat.ui/select-mention]} [{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}] diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/actions/style.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/actions/style.cljs index 177bccff46..3c0698fcd3 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/actions/style.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/actions/style.cljs @@ -18,4 +18,17 @@ {:position :absolute :right 0 :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}) diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/actions/view.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/actions/view.cljs index af5445052c..d065638d9c 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/actions/view.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/actions/view.cljs @@ -64,13 +64,58 @@ :i/arrow-up]])]))]) (defn audio-button - [] - [quo/button - {:on-press #(js/alert "to be added") - :icon true - :type :outline - :size 32} - :i/audio]) + [{:keys [record-permission? record-reset-fn]} + {:keys [recording? gesture-enabled?]} + {:keys [container-opacity]}] + (let [audio (rf/sub [:chats/sending-audio])] + [rn/view + {:style (style/record-audio-container) + :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 [] @@ -129,12 +174,14 @@ :i/format]) (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 {:flex-direction :row}} + [rn/view + {:style {:flex-direction :row + :display (if @(:recording? state) :none :flex)}} [camera-button] [image-button props animations insets] [reaction-button] [format-button]] [send-button state animations window-height images?] - [audio-button]]) + [audio-button props state animations audio]]) diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/effects.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/effects.cljs index 3bcd36ca84..ec982b6ef8 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/effects.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/effects.cljs @@ -78,12 +78,23 @@ (when-not edit-text (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 [{:keys [text-value maximized? focused?]} {:keys [container-opacity]} images? - reply?] - (when (and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?)) + reply? + 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))) (defn component-will-unmount @@ -94,7 +105,7 @@ (defn initialize [props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply? - edit] + edit audio] (rn/use-effect (fn [] (maximized-effect state animations dimensions chat-input) @@ -104,7 +115,8 @@ (background-effect state animations dimensions chat-input) (images-or-reply-effect animations props images? reply?) (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) #(component-will-unmount props)) [max-height])) diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/handlers.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/handlers.cljs index 310638c7bb..35b2c1ce58 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/handlers.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/handlers.cljs @@ -46,7 +46,7 @@ (reanimated/set-shared-value saved-height min-height) (reanimated/animate opacity 0) (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 gradient-opacity 0) (reset! lock-selection? true) @@ -95,13 +95,16 @@ (defn change-text [text - {:keys [input-ref]} - {:keys [text-value cursor-position]}] + {:keys [input-ref record-reset-fn]} + {:keys [text-value cursor-position recording?]}] (reset! text-value text) (reagent/next-tick #(when @input-ref (.setNativeProps ^js @input-ref (clj->js {:selection {:start @cursor-position :end @cursor-position}})))) + (when @recording? + (@record-reset-fn) + (reset! recording? false)) (rf/dispatch [:chat.ui/set-chat-input-text text])) (defn selection-change diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/reply/view.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/reply/view.cljs index 2beee6e1df..afca72f86d 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/reply/view.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/reply/view.cljs @@ -143,13 +143,13 @@ :style style/gradient}])])) (defn- f-view - [] + [recording?] (let [reply (rf/sub [:chats/reply-message]) 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]) [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 - [] - [:f> f-view]) + [{:keys [recording?]}] + [:f> f-view @recording?]) diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/style.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/style.cljs index 73cd8a26be..e5f06f305a 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/style.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/style.cljs @@ -55,18 +55,19 @@ :overflow :hidden})) (defn input - [focused? saved-keyboard-height] + [{:keys [saved-emoji-kb-extra-height]} + {:keys [focused? recording?]}] (merge typography/paragraph-1 {:min-height constants/input-height :color (colors/theme-colors :black :white) :text-align-vertical :top :flex 1 :z-index 1 - :position (if saved-keyboard-height :relative :absolute) + :position (if @saved-emoji-kb-extra-height :relative :absolute) :top 0 :left 0 - :right (when (or focused? platform/ios?) 0)})) - + :right (when (or focused? platform/ios?) 0) + :display (if @recording? :none :flex)})) (defn background [opacity background-y window-height] (reanimated/apply-animations-to-style diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/utils.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/utils.cljs index 9dc35e2f7c..8459745df4 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/utils.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/utils.cljs @@ -74,8 +74,8 @@ max-height)) (defn empty-input? - [text images reply?] - (and (empty? text) (empty? images) (not reply?))) + [text images reply? audio?] + (and (empty? text) (empty? images) (not reply?) (not audio?))) (defn android-elevation? [lines images reply? edit?] diff --git a/src/status_im2/contexts/chat/bottom_sheet_composer/view.cljs b/src/status_im2/contexts/chat/bottom_sheet_composer/view.cljs index 2819ca8475..cd73f64f57 100644 --- a/src/status_im2/contexts/chat/bottom_sheet_composer/view.cljs +++ b/src/status_im2/contexts/chat/bottom_sheet_composer/view.cljs @@ -34,7 +34,9 @@ :saved-emoji-kb-extra-height (atom nil) :replying? (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 "") :cursor-position (reagent/atom 0) :saved-cursor-position (reagent/atom 0) @@ -44,10 +46,12 @@ :lock-selection? (reagent/atom true) :focused? (reagent/atom false) :lock-layout? (reagent/atom false) - :maximized? (reagent/atom false)}] + :maximized? (reagent/atom false) + :recording? (reagent/atom false)}] [:f> (fn [] (let [images (rf/sub [:chats/sending-image]) + audio (rf/sub [:chats/sending-audio]) reply (rf/sub [:chats/reply-message]) edit (rf/sub [:chats/edit-message]) {:keys [input-text input-content-height] @@ -74,7 +78,8 @@ (if (utils/empty-input? input-text images - reply) + reply + audio) 0.7 1)) :height (reanimated/use-shared-value @@ -102,14 +107,15 @@ keyboard-height (seq images) reply - edit) + edit + audio) [gesture/gesture-detector {:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)} [reanimated/view {:style (style/sheet-container insets state animations) :on-layout #(handler/layout % state blur-height)} [sub-view/bar] - [reply/view reply] + [reply/view state] [edit/view edit #(utils/cancel-edit-message state animations)] [reanimated/touchable-opacity {:active-opacity 1 @@ -134,8 +140,7 @@ :multiline true :placeholder (i18n/label :t/type-something) :placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50) - :style (style/input @(:focused? state) - @(:saved-emoji-kb-extra-height props)) + :style (style/input props state) :accessibility-label :chat-message-input}] [gradients/view props state animations show-bottom-gradient?]] [images/images-list] diff --git a/src/status_im2/subs/chat/chats.cljs b/src/status_im2/subs/chat/chats.cljs index 047a85af1c..06428dd4fd 100644 --- a/src/status_im2/subs/chat/chats.cljs +++ b/src/status_im2/subs/chat/chats.cljs @@ -324,6 +324,13 @@ (fn [{:keys [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 :chats/timeline-sending-image :<- [:chats/timeline-chat-input]