diff --git a/src/status_im2/contexts/chat/messages/composer_new/style.cljs b/src/status_im2/contexts/chat/messages/composer_new/style.cljs index 780faf8d1f..26728d70d8 100644 --- a/src/status_im2/contexts/chat/messages/composer_new/style.cljs +++ b/src/status_im2/contexts/chat/messages/composer_new/style.cljs @@ -20,13 +20,15 @@ :bottom 0 :left 0 :right 0 + :background-color (colors/theme-colors colors/white colors/neutral-90) ;:background-color (colors/theme-colors colors/white colors/neutral-90) - ;:background-color (colors/theme-colors colors/white colors/neutral-90) - :background-color "rgba(255,255,255,1)" + ;:background-color "rgba(255,255,255,1)" ;:background-color :black :opacity (if (or focused? has-text?) 1 (if platform/ios? 0.7 0.5)) :z-index 3 - :padding-bottom (:bottom insets)} + :padding-bottom (:bottom insets) + ;:padding-bottom 0 + } (if platform/ios? {:shadow-radius 20 :shadow-opacity 0.1 @@ -54,7 +56,7 @@ :background-color (colors/theme-colors colors/neutral-100-opa-5 colors/white-opa-10)}) (defn input - [focused? expanded?] + [focused? expanded? saved-keyboard-height] (merge typography/paragraph-1 {:min-height (if platform/ios? 32 44) :text-align-vertical :top @@ -62,11 +64,11 @@ ;:position (if (and platform/android? (or (<= (reanimated/get-shared-value value) input-height) animating)) :absolute :relative) ;:position (if platform/android? :absolute :relative) - :position :absolute + :position (if saved-keyboard-height :relative :absolute) :top 0 :left 0 :right (when (or (not focused?) expanded? platform/ios?) 0) ; to inc gesture detection area on Android - ;:right 0 ; to inc gesture detection area on Android + ;:overflow :hidden ;:padding-vertical 10 ;:min-height input-height diff --git a/src/status_im2/contexts/chat/messages/composer_new/view.cljs b/src/status_im2/contexts/chat/messages/composer_new/view.cljs index 6aeaa26990..14905116bb 100644 --- a/src/status_im2/contexts/chat/messages/composer_new/view.cljs +++ b/src/status_im2/contexts/chat/messages/composer_new/view.cljs @@ -21,7 +21,7 @@ [status-im2.contexts.chat.messages.composer-new.style :as style] [utils.re-frame :as rf])) -(def ^:const drag-threshold 80) +(def ^:const drag-threshold 30) (def input-height (if platform/ios? 32 44)) @@ -50,36 +50,38 @@ :i/image]) (defn drag-gesture - [height saved-height opacity bg-bottom window-height keyboard-shown max-height input-ref lines add-keyboard-height emojis-open] + [height saved-height opacity bg-bottom window-height keyboard-shown max-height input-ref lines add-keyboard-height saved-keyboard-height emojis-open] (let [expanding? (atom true)] (-> (gesture/gesture-pan) (gesture/on-start (fn [e] (reanimated/set-shared-value bg-bottom 0) (reset! expanding? (neg? (oops/oget e "velocityY"))))) (gesture/on-update (fn [e] - (let [translation (oops/oget e "translationY") - new-height (Math/max input-height (Math/min (+ (- (/ translation 1)) (reanimated/get-shared-value saved-height)) max-height)) - remaining-height (if @expanding? (- max-height (reanimated/get-shared-value saved-height)) (reanimated/get-shared-value saved-height)) - progress (/ translation remaining-height) - progress (if (= new-height input-height) 1 progress)] + (let [translation (oops/oget e "translationY") + new-height (Math/max input-height (Math/min (+ (- (/ translation 1)) (reanimated/get-shared-value saved-height)) max-height)) + remaining-height (if @expanding? (- max-height (reanimated/get-shared-value saved-height)) (reanimated/get-shared-value saved-height)) + progress (/ translation remaining-height) + progress (if (= new-height input-height) 1 progress) + currently-expanding? (neg? (oops/oget e "velocityY")) + maximum-opacity? (and currently-expanding? (= (reanimated/get-shared-value opacity) 1))] (if keyboard-shown - (do - (if (>= translation 0) - (do - (reanimated/set-shared-value height new-height) - (when (and (pos? progress) (not= (reanimated/get-shared-value opacity) 0)) - (reanimated/set-shared-value opacity (- 1 progress)))) - (do - (reanimated/set-shared-value height new-height) - (when @expanding? - (reanimated/set-shared-value opacity (Math/abs progress)))))) - (do - (.focus ^js @input-ref)))))) + (if (>= translation 0) + (do + (reanimated/set-shared-value height new-height) + (when (and (pos? progress) (not= (reanimated/get-shared-value opacity) 0)) + (reanimated/set-shared-value opacity (- 1 progress)))) + (do + (reanimated/set-shared-value height new-height) + (when (and @expanding? (not maximum-opacity?)) + (reanimated/set-shared-value opacity (Math/abs progress))))) + (.focus ^js @input-ref))))) (gesture/on-end (fn [e] - (let [diff (- (reanimated/get-shared-value height) (reanimated/get-shared-value saved-height)) - collapsing? (pos? (oops/oget e "velocityY"))] + (let [collapsing? (pos? (oops/oget e "velocityY")) + diff (- (reanimated/get-shared-value height) (reanimated/get-shared-value saved-height)) + remaining (if (not collapsing?) (- max-height (reanimated/get-shared-value height)) (reanimated/get-shared-value height)) + threshold (if (> remaining drag-threshold) drag-threshold 10)] (if (>= diff 0) - (if (> diff drag-threshold) + (if (and (> diff threshold) (not collapsing?)) (do (reanimated/animate height max-height) (reanimated/set-shared-value saved-height max-height) @@ -90,7 +92,7 @@ (when (or (and collapsing? (not= (reanimated/get-shared-value saved-height) max-height)) (= (reanimated/get-shared-value saved-height) input-height)) (reanimated/animate opacity 0) (reanimated/animate-delay bg-bottom (- window-height) 300)))) - (if (and (> diff (- drag-threshold)) (not collapsing?)) + (if (or (< (Math/abs diff) threshold) (and (not collapsing?) (> (Math/abs diff) threshold))) (do (reanimated/animate height max-height) (reanimated/set-shared-value saved-height max-height) @@ -99,9 +101,8 @@ (let [target-height (if (> lines 1) (+ input-height 18) input-height)] (when @add-keyboard-height - (reanimated/set-shared-value height (+ (reanimated/get-shared-value height) @add-keyboard-height)) - (reanimated/set-shared-value saved-height (+ (reanimated/get-shared-value saved-height) @add-keyboard-height)) (reset! emojis-open false) + (reset! saved-keyboard-height @add-keyboard-height) (reset! add-keyboard-height nil)) (.blur ^js @input-ref) @@ -156,6 +157,7 @@ lock-layout? (reagent/atom false) keyboard-show-listener (reagent/atom nil) add-keyboard-height (atom nil) + saved-keyboard-height (atom nil) margin-top (if platform/ios? (:top insets) (+ (:top insets) 10)) emojis-open (reagent/atom false)] (rn/use-effect @@ -178,7 +180,8 @@ (reanimated/set-shared-value height (+ (reanimated/get-shared-value height) @add-keyboard-height)) (reanimated/set-shared-value saved-height (+ (reanimated/get-shared-value saved-height) @add-keyboard-height)) (reset! emojis-open false) - (reset! add-keyboard-height nil))))))) + (reset! add-keyboard-height nil))) + )))) (fn [] (.remove ^js @keyboard-show-listener)))) [:f> (fn [] @@ -191,94 +194,98 @@ expanded? (= (reanimated/get-shared-value height) max-height)] [:<> [reanimated/view {:style (style/background opacity bg-bottom window-height height)}] - [gesture/gesture-detector {:gesture (drag-gesture height saved-height opacity bg-bottom window-height keyboard-shown max-height input-ref lines add-keyboard-height emojis-open)} - [rn/keyboard-avoiding-view {:style (style/container insets @focused? (not-empty @text-value)) - :behavior (if platform/ios? "padding" nil) - :keyboard-vertical-offset ios-extra-offset - :on-layout (fn [e] - (when-not @lock-layout? - (reanimated/set-shared-value layout-height (oops/oget e "nativeEvent.layout.height"))))} - [rn/view {:style {:padding-bottom (:bottom insets) - :z-index 2}} - [handle] - [reanimated/view {:style (style/input-container height max-height @emojis-open)} - [reanimated/linear-gradient - {:colors ["rgba(255,255,255,0)" "rgba(255,255,255,1)"] - :start {:x 0 :y 1} - :end {:x 0 :y 0} - :style (style/text-top-overlay overlay-opacity @overlay-z-index)}] - [rn/text-input - {:ref #(reset! input-ref %) - :default-value @text-value - :on-change-text (fn [text] - (reset! text-value text) - (js/setTimeout #(.setNativeProps ^js @input-ref (clj->js {:selection (clj->js @cursor-position)})) 20) - (rf/dispatch [:chat.ui/set-chat-input-text text])) - :on-selection-change (fn [e] - (when-not @lock-selection - (reset! cursor-position {:start (oops/oget e "nativeEvent.selection.end") :end (oops/oget e "nativeEvent.selection.end")}))) - :on-focus (fn [] - (reset! focused? true) - (reset! lock-layout? true) - (js/setTimeout #(reset! lock-selection false) 300) - (when (not-empty @text-value) - (.setNativeProps ^js @input-ref (clj->js {:selection @saved-cursor-position}))) - (reanimated/animate height (reanimated/get-shared-value last-height)) - (reanimated/set-shared-value saved-height (reanimated/get-shared-value last-height)) - (when (> (reanimated/get-shared-value last-height) (* 0.75 max-height)) - (reanimated/animate opacity 1) - (reanimated/set-shared-value bg-bottom 0)) - (reanimated/set-shared-value blur-opacity 0)) - :on-blur (fn [] - (let [target-height (if (> lines 1) (+ input-height 18) input-height)] - (reset! saved-cursor-position @cursor-position) - (reanimated/set-shared-value last-height (if (empty? @text-value) target-height (Math/min (+ @content-height (if platform/ios? 5 0)) - (reanimated/get-shared-value saved-height)))) - (reanimated/set-shared-value blur-opacity 1) - (reanimated/animate height target-height) - (reanimated/set-shared-value saved-height target-height) - (reset! focused? false) - (reset! lock-selection true) - (js/setTimeout #(reset! lock-layout? false) 500) - (reanimated/animate overlay-opacity 0) - (reset! overlay-z-index 0))) - :style (style/input @focused? expanded?) - :on-scroll (fn [e] (let [y (oops/oget e "nativeEvent.contentOffset.y")] - (when (and (> y line-height) (>= lines max-lines) (= @overlay-z-index 0) @focused?) - (reset! overlay-z-index 1) - (js/setTimeout #(reanimated/animate overlay-opacity 1) 0)) - (when (and (<= y line-height) (= @overlay-z-index 1)) - (reanimated/animate overlay-opacity 0) - (js/setTimeout #(reset! overlay-z-index 0) 300)))) - :on-content-size-change (fn [e] - (when @focused? - (let [extra-offset (if platform/ios? (if @emojis-open ios-extra-offset 5) 0) - x (+ (oops/oget e "nativeEvent.contentSize.height") extra-offset) - diff (Math/abs (- x (reanimated/get-shared-value height)))] - (reset! content-height (oops/oget e "nativeEvent.contentSize.height")) - (when (and (> diff 10) (not-empty @text-value) (<= x (+ max-height line-height)) (not= (reanimated/get-shared-value height) max-height)) - (reanimated/animate height (Math/min x max-height)) - (reanimated/set-shared-value saved-height (Math/min x max-height))) - (if (> (reanimated/get-shared-value saved-height) (* 0.75 max-height)) - (do - (reanimated/set-shared-value bg-bottom 0) - (reanimated/animate opacity 1)) - (do - (reanimated/animate opacity 0) - (reanimated/animate-delay bg-bottom (- window-height) 300)))))) - :max-height max-height - :multiline true - :placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-60) - :placeholder (i18n/label :t/type-something)}] - (when (and (not-empty @text-value) (not @focused?) (> lines 1)) - [rn/touchable-without-feedback - {:on-press #(.focus ^js @input-ref)} - [linear-gradient/linear-gradient - {:colors ["rgba(255,255,255,1)" "rgba(255,255,255,0)"] - :start {:x 0 :y 1} - :end {:x 0 :y 0} - :style (style/text-overlay)}]])] - [actions input-ref text-value]]]]]))]))]) + [gesture/gesture-detector {:gesture (drag-gesture height saved-height opacity bg-bottom window-height keyboard-shown max-height input-ref lines add-keyboard-height saved-keyboard-height emojis-open)} + [rn/view {:style (style/container insets @focused? (not-empty @text-value)) + :on-layout (fn [e] + (when-not @lock-layout? + (reanimated/set-shared-value layout-height (oops/oget e "nativeEvent.layout.height"))))} + [handle] + [reanimated/view {:style (style/input-container height max-height @emojis-open)} + [reanimated/linear-gradient + {:colors ["rgba(255,255,255,0)" "rgba(255,255,255,1)"] + :start {:x 0 :y 1} + :end {:x 0 :y 0} + :style (style/text-top-overlay overlay-opacity @overlay-z-index)}] + [rn/text-input + {:ref #(reset! input-ref %) + :default-value @text-value + :on-change-text (fn [text] + (reset! text-value text) + (js/setTimeout #(.setNativeProps ^js @input-ref (clj->js {:selection (clj->js @cursor-position)})) 20) + (rf/dispatch [:chat.ui/set-chat-input-text text])) + :on-selection-change (fn [e] + (when-not @lock-selection + (reset! cursor-position {:start (oops/oget e "nativeEvent.selection.end") :end (oops/oget e "nativeEvent.selection.end")}))) + :on-focus (fn [] + (reset! focused? true) + (reset! lock-layout? true) + (js/setTimeout #(reset! lock-selection false) 300) + (when (not-empty @text-value) + (.setNativeProps ^js @input-ref (clj->js {:selection @saved-cursor-position}))) + (reanimated/animate height (reanimated/get-shared-value last-height)) + (reanimated/set-shared-value saved-height (reanimated/get-shared-value last-height)) + (when @saved-keyboard-height + (js/setTimeout (fn [] + (when (> lines max-lines) + (reanimated/animate height (+ (reanimated/get-shared-value last-height) @saved-keyboard-height)) + (reanimated/set-shared-value saved-height (+ (reanimated/get-shared-value last-height) @saved-keyboard-height))) + (reset! saved-keyboard-height nil)) 600)) + (when (> (reanimated/get-shared-value last-height) (* 0.75 max-height)) + (reanimated/animate opacity 1) + (reanimated/set-shared-value bg-bottom 0)) + (reanimated/set-shared-value blur-opacity 0)) + :on-blur (fn [] + (let [target-height (if (> lines 1) (+ input-height 18) input-height)] + (reset! saved-cursor-position @cursor-position) + (reanimated/set-shared-value last-height (if (empty? @text-value) target-height (Math/min (+ @content-height (if platform/ios? 5 0)) + (reanimated/get-shared-value saved-height)))) + (reanimated/set-shared-value blur-opacity 1) + (reanimated/animate height target-height) + (reanimated/set-shared-value saved-height target-height) + (reset! focused? false) + (reset! lock-selection true) + (js/setTimeout #(reset! lock-layout? false) 500) + (reanimated/animate overlay-opacity 0) + (reset! overlay-z-index 0))) + :style (style/input @focused? expanded? @saved-keyboard-height) + :on-scroll (fn [e] (let [y (oops/oget e "nativeEvent.contentOffset.y")] + (when (and (> y line-height) (>= lines max-lines) (= @overlay-z-index 0) @focused?) + (reset! overlay-z-index 1) + (js/setTimeout #(reanimated/animate overlay-opacity 1) 0)) + (when (and (<= y line-height) (= @overlay-z-index 1)) + (reanimated/animate overlay-opacity 0) + (js/setTimeout #(reset! overlay-z-index 0) 300)))) + :on-content-size-change (fn [e] + ;(when @focused? + (let [extra-offset (if platform/ios? (if @emojis-open ios-extra-offset 5) 0) + x (+ (oops/oget e "nativeEvent.contentSize.height") extra-offset) + diff (Math/abs (- x (reanimated/get-shared-value height)))] + (reset! content-height (oops/oget e "nativeEvent.contentSize.height")) + (when (and (> diff 10) (not-empty @text-value) (<= x (+ max-height line-height)) (not= (reanimated/get-shared-value height) max-height)) + (reanimated/animate height (Math/min x max-height)) + (reanimated/set-shared-value saved-height (Math/min x max-height))) + (if (> (reanimated/get-shared-value saved-height) (* 0.75 max-height)) + (do + (reanimated/set-shared-value bg-bottom 0) + (reanimated/animate opacity 1)) + (do + (reanimated/animate opacity 0) + (reanimated/animate-delay bg-bottom (- window-height) 300)))) + ;) + ) + :max-height max-height + :multiline true + :placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-60) + :placeholder (i18n/label :t/type-something)}] + (when (and (not-empty @text-value) (not @focused?) (> lines 1)) + [rn/touchable-without-feedback + {:on-press #(.focus ^js @input-ref)} + [linear-gradient/linear-gradient + {:colors ["rgba(255,255,255,1)" "rgba(255,255,255,0)"] + :start {:x 0 :y 1} + :end {:x 0 :y 0} + :style (style/text-overlay)}]])] + [actions input-ref text-value]]]]))]))]) (defn blur-view [insets blur-opacity layout-height] @@ -301,3 +308,4 @@ [rn/view [blur-view insets blur-opacity layout-height] [sheet insets blur-opacity layout-height]]))]) +