This commit is contained in:
Omar Basem
2023-04-12 23:07:35 +04:00
parent 5382d108e4
commit ddb65b7dbd
11 changed files with 1263 additions and 713 deletions
+11 -3
View File
@@ -234,7 +234,7 @@ PODS:
- React
- react-native-blob-util (0.13.18):
- React-Core
- react-native-blur (4.3.0):
- react-native-blur (4.3.2):
- React-Core
- react-native-camera-kit (8.0.4):
- React
@@ -695,6 +695,7 @@ SPEC CHECKSUMS:
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
>>>>>>> 1ae28d67c (updates)
@@ -707,6 +708,9 @@ SPEC CHECKSUMS:
=======
glog: 6934faae5afbec23475648c8aeb6047ce973af65
>>>>>>> d31ec1795 (updates)
=======
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
>>>>>>> 12ff0b995 (updates)
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
@@ -726,7 +730,7 @@ SPEC CHECKSUMS:
React-logger: 85f4ef06b9723714b2dfa5b0e5502b673b271b58
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
react-native-blur: 4db8c7556566df4e8714c1af5762a4ebc99175d5
react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f
react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2
react-native-config: 5330c8258265c1e5fdb8c009d2cabd6badd96727
@@ -785,6 +789,7 @@ SPEC CHECKSUMS:
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
PODFILE CHECKSUM: c29de3b14e3275299c51aa95520622f09d084bcb
=======
PODFILE CHECKSUM: a8a81808e948d1103fdd28ef7fe16d5f045fef62
@@ -798,5 +803,8 @@ PODFILE CHECKSUM: a8a81808e948d1103fdd28ef7fe16d5f045fef62
=======
PODFILE CHECKSUM: dd4d6510a5580d20adac6c8a8dad97a0bc7d6508
>>>>>>> d31ec1795 (updates)
=======
PODFILE CHECKSUM: a8a81808e948d1103fdd28ef7fe16d5f045fef62
>>>>>>> 12ff0b995 (updates)
COCOAPODS: 1.12.0
COCOAPODS: 1.11.3
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.actions.style
(:require [status-im2.contexts.chat.messages.bottom-sheet-composer.constants :as c]))
(defn actions-container
[]
{:height c/actions-container-height
:justify-content :space-between
:align-items :center
:z-index 2
:flex-direction :row})
@@ -0,0 +1,133 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.actions.view
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.background-timer :as background-timer]
[react-native.core :as rn]
[react-native.permissions :as permissions]
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im2.common.alert.events :as alert]
[status-im2.contexts.chat.messages.bottom-sheet-composer.constants :as c]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[status-im2.contexts.chat.messages.bottom-sheet-composer.actions.style :as style]))
;;; CONTROLS
(defn send-button
[input-ref text-value images? window-height
{:keys [height saved-height last-height opacity background-y container-opacity]}]
[:f>
(fn []
(let [btn-opacity (reanimated/use-shared-value 0)
z-index (reagent/atom 0)]
[:f>
(fn []
(rn/use-effect (fn []
(if (or (not-empty @text-value) images?)
(when-not (= @z-index 1)
(reset! z-index 1)
(js/setTimeout #(reanimated/animate btn-opacity 1) 50))
(when-not (= @z-index 0)
(reanimated/animate btn-opacity 0)
(js/setTimeout #(reset! z-index 0) 300))))
[@text-value])
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity btn-opacity}
{:position :absolute
:right 0
:z-index @z-index
:background-color (colors/theme-colors colors/white colors/neutral-95)})}
[quo/button
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press (fn []
(reanimated/animate height c/input-height)
(reanimated/set-shared-value saved-height c/input-height)
(reanimated/set-shared-value last-height c/input-height)
(reanimated/animate opacity 0)
(js/setTimeout #(reanimated/animate container-opacity 0.7) 300)
(js/setTimeout #(reanimated/set-shared-value background-y
(- window-height))
300)
(rf/dispatch [:chat.ui/send-current-message])
(rf/dispatch [:chat.ui/set-input-maximized false])
(rf/dispatch [:chat.ui/set-input-content-height c/input-height])
(reset! text-value "")
(.clear ^js @input-ref)
(messages.list/scroll-to-bottom))}
:i/arrow-up]])]))])
(defn audio-button
[]
[quo/button
{:on-press #(js/alert "to be added")
:icon true
:type :outline
:size 32}
:i/audio])
(defn camera-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/camera])
(defn image-button
[insets height]
[quo/button
{:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed (fn []
(rf/dispatch [:chat.ui/set-input-content-height
(reanimated/get-shared-value height)])
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
:on-denied (fn []
(background-timer/set-timeout
#(alert/show-popup (i18n/label :t/error)
(i18n/label
:t/external-storage-denied))
50))}))
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/image])
(defn reaction-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/reaction])
(defn format-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32}
:i/format])
(defn view
[input-ref text-value images? {:keys [height] :as animations}
window-height insets]
[rn/view {:style (style/actions-container)}
[rn/view {:style {:flex-direction :row}}
[camera-button]
[image-button insets height]
[reaction-button]
[format-button]]
[send-button input-ref text-value images? window-height animations]
[audio-button]])
@@ -5,7 +5,7 @@
(def ^:const handle-container-height 20)
(def ^:const input-height (if platform/ios? 32 32))
(def ^:const input-height (if platform/ios? 32 42))
(def ^:const actions-container-height 56)
@@ -0,0 +1,72 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.keyboard
(:require [oops.core :as oops]
[react-native.async-storage :as async-storage]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.messages.bottom-sheet-composer.utils :as utils]))
(defn get-kb-height
[curr-height default-height]
(if (and default-height (< curr-height default-height))
default-height
curr-height))
(defn store-kb-height
[{:keys [kb-default-height]} keyboard-height]
(when (and (not @kb-default-height) (pos? keyboard-height))
(async-storage/set-item :kb-default-height keyboard-height)))
(defn handle-emoji-kb-ios
[e
{:keys [emoji-kb-extra-height]}
{:keys [text-value]}
{:keys [height saved-height]}
{:keys [max-height]}]
(let [start-h (oops/oget e "startCoordinates.height")
end-h (oops/oget e "endCoordinates.height")
diff (- end-h start-h)
max (- max-height diff)
curr-text @text-value]
(if (> (reanimated/get-shared-value height) max)
(do
(reanimated/set-shared-value height (- (reanimated/get-shared-value height) diff))
(reanimated/set-shared-value saved-height (- (reanimated/get-shared-value saved-height) diff))
(reset! text-value (str @text-value " "))
(js/setTimeout #(reset! text-value curr-text) 0)
(reset! emoji-kb-extra-height diff))
(when @emoji-kb-extra-height
(reanimated/set-shared-value height
(+ (reanimated/get-shared-value height) @emoji-kb-extra-height))
(reanimated/set-shared-value saved-height
(+ (reanimated/get-shared-value saved-height)
@emoji-kb-extra-height))
(reset! emoji-kb-extra-height nil)))))
(defn handle-kb-hide-android
[{:keys [input-ref]}
{:keys [opacity height saved-height background-y]}
{:keys [window-height lines]}]
(when platform/android?
(let [min-height (utils/get-min-height lines)]
(.blur ^js @input-ref)
(reanimated/animate opacity 0)
(js/setTimeout (fn []
(reanimated/animate height min-height)
(reanimated/set-shared-value saved-height min-height)
(reanimated/set-shared-value background-y (- window-height)))
100))))
(defn add-kb-listeners
[{:keys [keyboard-show-listener keyboard-frame-listener keyboard-hide-listener] :as props}
state animations dimensions keyboard-height]
(reset! keyboard-show-listener (.addListener rn/keyboard
"keyboardDidShow"
#(store-kb-height state keyboard-height)))
(reset! keyboard-frame-listener (.addListener
rn/keyboard
"keyboardWillChangeFrame"
#(handle-emoji-kb-ios % props state animations dimensions)))
(reset! keyboard-hide-listener (.addListener rn/keyboard
"keyboardDidHide"
#(handle-kb-hide-android props animations dimensions))))
@@ -70,14 +70,6 @@
:overflow :hidden}))
(defn actions-container
[]
{:height c/actions-container-height
:justify-content :space-between
:align-items :center
:z-index 2
:flex-direction :row})
(defn background
[opacity background-y window-height]
(reanimated/apply-animations-to-style
@@ -0,0 +1,35 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.sub-view
(:require
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.messages.bottom-sheet-composer.style :as style]))
(defn bar
[]
[rn/view {:style (style/bar-container)}
[rn/view {:style (style/bar)}]])
(defn blur-view
[layout-height]
[:f>
(fn []
[reanimated/view {:style (style/blur-container layout-height)}
[blur/view style/blur-view]])])
(defn gradients
[{:keys [input-ref]}
{:keys [gradient-z-index text-value focused?]}
{:keys [gradient-opacity]}
{:keys [lines]}]
[:f>
(fn []
[:<>
[reanimated/linear-gradient (style/top-gradient gradient-opacity @gradient-z-index)]
(when (and (not-empty @text-value) (not @focused?) (> lines 2))
[rn/touchable-without-feedback
{:on-press #(.focus ^js @input-ref)}
[linear-gradient/linear-gradient (style/bottom-gradient)]])])])
@@ -1,2 +0,0 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.test)
@@ -0,0 +1,56 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.utils
(:require
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.messages.bottom-sheet-composer.constants :as c]))
(defn bounded-val
[f min max]
(Math/max min (Math/min f max)))
(defn get-min-height
[lines]
(if (> lines 1) c/multiline-minimized-height c/input-height))
(defn calc-reopen-height
[text-value min-height content-height saved-height]
(if (empty? @text-value)
min-height
(Math/min @content-height (reanimated/get-shared-value saved-height))))
(defn should-update-height
[content-size height max-height]
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff c/content-change-threshold))))
(defn should-show-top-gradient
[y lines max-lines gradient-opacity focused?]
(and
(> y c/line-height)
(>= lines max-lines)
(= (reanimated/get-shared-value gradient-opacity) 0)
@focused?))
(defn should-hide-top-gradient
[y gradient-opacity]
(and
(<= y c/line-height)
(= (reanimated/get-shared-value gradient-opacity) 1)))
(defn calc-lines
[height]
(let [lines (Math/round (/ height c/line-height))]
(if platform/ios? lines (dec lines))))
(defn calc-max-height
[window-height margin-top kb-height images]
(let [max-height
(- window-height margin-top kb-height c/handle-container-height c/actions-container-height)]
(if (seq images)
(- max-height c/images-container-height)
max-height)))
(defn empty-input?
[input-text images]
(and (nil? input-text) (not (seq images))))
@@ -1,157 +1,24 @@
(ns status-im2.contexts.chat.messages.bottom-sheet-composer.view
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.background-timer :as background-timer]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[react-native.hooks :as hooks]
[react-native.linear-gradient :as linear-gradient]
[react-native.permissions :as permissions]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[oops.core :as oops]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.common.alert.events :as alert]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[utils.i18n :as i18n]
[status-im2.contexts.chat.messages.bottom-sheet-composer.style :as style]
[status-im2.contexts.chat.messages.bottom-sheet-composer.images.view :as images]
[react-native.async-storage :as async-storage]
[utils.re-frame :as rf]
[status-im2.contexts.chat.messages.bottom-sheet-composer.constants :as c]))
;;; CONTROLS
(defn send-button
[input-ref text-value images? window-height
{:keys [height saved-height last-height opacity background-y container-opacity]}]
[:f>
(fn []
(let [btn-opacity (reanimated/use-shared-value 0)
z-index (reagent/atom 0)]
[:f>
(fn []
(rn/use-effect (fn []
(if (or (not-empty @text-value) images?)
(when-not (= @z-index 1)
(reset! z-index 1)
(js/setTimeout #(reanimated/animate btn-opacity 1) 50))
(when-not (= @z-index 0)
(reanimated/animate btn-opacity 0)
(js/setTimeout #(reset! z-index 0) 300))))
[@text-value])
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity btn-opacity}
{:position :absolute
:right 0
:z-index @z-index
:background-color (colors/theme-colors colors/white colors/neutral-90)})}
[quo/button
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press (fn []
(reanimated/animate height c/input-height)
(reanimated/set-shared-value saved-height c/input-height)
(reanimated/set-shared-value last-height c/input-height)
(reanimated/animate opacity 0)
(js/setTimeout #(reanimated/animate container-opacity 0.7) 300)
(js/setTimeout #(reanimated/set-shared-value background-y
(- window-height))
300)
(rf/dispatch [:chat.ui/send-current-message])
(rf/dispatch [:chat.ui/set-input-maximized false])
(reset! text-value "")
(.clear ^js @input-ref)
(messages.list/scroll-to-bottom))}
:i/arrow-up]])]))])
(defn audio-button
[]
[quo/button
{:on-press #(js/alert "to be added")
:icon true
:type :outline
:size 32}
:i/audio])
(defn camera-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/camera])
(defn image-button
[insets height]
[quo/button
{:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed (fn []
(rf/dispatch [:chat.ui/set-input-content-height
(reanimated/get-shared-value height)])
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
:on-denied (fn []
(background-timer/set-timeout
#(alert/show-popup (i18n/label :t/error)
(i18n/label
:t/external-storage-denied))
50))}))
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/image])
(defn reaction-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32
:style {:margin-right 12}}
:i/reaction])
(defn format-button
[]
[quo/button
{:on-press #(js/alert "to be implemented")
:icon true
:type :outline
:size 32}
:i/format])
(defn actions
[input-ref text-value images? {:keys [height saved-height opacity background-y] :as animations}
window-height insets]
[rn/view {:style (style/actions-container)}
[rn/view {:style {:flex-direction :row}}
[camera-button]
[image-button insets height]
[reaction-button]
[format-button]]
[send-button input-ref text-value images? window-height animations]
[audio-button]])
(defn bar
[]
[rn/view {:style (style/bar-container)}
[rn/view {:style (style/bar)}]])
(defn get-min-height
[lines]
(if (> lines 1) c/multiline-minimized-height c/input-height))
(defn bounded-val
[f min max]
(Math/max min (Math/min f max)))
[status-im2.contexts.chat.messages.bottom-sheet-composer.utils :as utils]
[status-im2.contexts.chat.messages.bottom-sheet-composer.constants :as c]
[status-im2.contexts.chat.messages.bottom-sheet-composer.actions.view :as actions]
[status-im2.contexts.chat.messages.bottom-sheet-composer.keyboard :as kb]
[status-im2.contexts.chat.messages.bottom-sheet-composer.sub-view :as sub-view]))
(defn set-opacity
[e opacity translation expanding? min-height max-height new-height saved-height]
@@ -200,7 +67,7 @@
(defn drag-gesture
[{:keys [input-ref] :as props}
{:keys [gesture-enabled?] :as state}
{:keys [height saved-height last-height opacity background-y] :as animations}
{:keys [height saved-height last-height opacity background-y container-opacity] :as animations}
{:keys [max-height lines] :as dimensions}
keyboard-shown]
(let [expanding? (atom true)
@@ -212,6 +79,7 @@
(if-not keyboard-shown
(do ; focus and end
(when (< (oops/oget e "velocityY") c/velocity-threshold)
(reanimated/animate container-opacity 1)
(reanimated/set-shared-value last-height max-height))
(.focus ^js @input-ref)
(reset! gesture-enabled? false))
@@ -220,10 +88,10 @@
(reset! expanding? (neg? (oops/oget e "velocityY")))))))
(gesture/on-update (fn [e]
(let [translation (oops/oget e "translationY")
min-height (get-min-height lines)
min-height (utils/get-min-height lines)
new-height (+ (- translation)
(reanimated/get-shared-value saved-height))
new-height (bounded-val new-height min-height max-height)]
new-height (utils/bounded-val new-height min-height max-height)]
(when keyboard-shown
(reanimated/set-shared-value height new-height)
(set-opacity e
@@ -284,11 +152,6 @@
(clj->js {:selection {:start @saved-cursor-position :end @saved-cursor-position}})))
(handle-refocus-emoji-kb-ios props animations dimensions))
(defn calc-reopen-height
[text-value min-height content-height saved-height]
(if (empty? @text-value)
min-height
(Math/min @content-height (reanimated/get-shared-value saved-height))))
(defn handle-blur
[{:keys [text-value focused? lock-selection? cursor-position saved-cursor-position gradient-z-index
@@ -296,8 +159,8 @@
{:keys [height saved-height last-height gradient-opacity container-opacity opacity background-y]}
{:keys [lines content-height max-height window-height]}
images]
(let [min-height (get-min-height lines)
reopen-height (calc-reopen-height text-value min-height content-height saved-height)]
(let [min-height (utils/get-min-height lines)
reopen-height (utils/calc-reopen-height text-value min-height content-height saved-height)]
(reset! focused? false)
(reanimated/set-shared-value last-height reopen-height)
(reanimated/animate height min-height)
@@ -313,12 +176,6 @@
(when (not= reopen-height max-height)
(reset! maximized? false))))
(defn should-update-height
[content-size height max-height]
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff c/content-change-threshold))))
(defn handle-content-size-change
[e
{:keys [maximized?]}
@@ -327,9 +184,9 @@
keyboard-shown]
(when keyboard-shown
(let [content-size (+ (oops/oget e "nativeEvent.contentSize.height") c/extra-content-offset)
new-height (bounded-val content-size c/input-height max-height)]
new-height (utils/bounded-val content-size c/input-height max-height)]
(reset! content-height content-size)
(when (should-update-height content-size height max-height)
(when (utils/should-update-height content-size height max-height)
(reanimated/animate height new-height)
(reanimated/set-shared-value saved-height new-height))
(when (= new-height max-height)
@@ -344,30 +201,16 @@
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)))
(rf/dispatch [:chat.ui/set-input-content-height new-height]))))
(defn should-show-top-gradient
[y lines max-lines gradient-opacity focused?]
(and
(> y c/line-height)
(>= lines max-lines)
(= (reanimated/get-shared-value gradient-opacity) 0)
@focused?))
(defn should-hide-top-gradient
[y gradient-opacity]
(and
(<= y c/line-height)
(= (reanimated/get-shared-value gradient-opacity) 1)))
(defn handle-scroll
[e
{:keys [gradient-z-index focused?]}
{:keys [gradient-opacity]}
{:keys [lines max-lines]}]
(let [y (oops/oget e "nativeEvent.contentOffset.y")]
(when (should-show-top-gradient y lines max-lines gradient-opacity focused?)
(when (utils/should-show-top-gradient y lines max-lines gradient-opacity focused?)
(reset! gradient-z-index 1)
(js/setTimeout #(reanimated/animate gradient-opacity 1) 0))
(when (should-hide-top-gradient y gradient-opacity)
(when (utils/should-hide-top-gradient y gradient-opacity)
(reanimated/animate gradient-opacity 0)
(js/setTimeout #(reset! gradient-z-index 0) 300))))
@@ -387,46 +230,6 @@
(when-not @lock-selection?
(reset! cursor-position (oops/oget e "nativeEvent.selection.end"))))
(defn handle-emoji-kb-ios
[e
{:keys [emoji-kb-extra-height]}
{:keys [text-value]}
{:keys [height saved-height]}
{:keys [max-height]}]
(let [start-h (oops/oget e "startCoordinates.height")
end-h (oops/oget e "endCoordinates.height")
diff (- end-h start-h)
max (- max-height diff)
curr-text @text-value]
(if (> (reanimated/get-shared-value height) max)
(do
(reanimated/set-shared-value height (- (reanimated/get-shared-value height) diff))
(reanimated/set-shared-value saved-height (- (reanimated/get-shared-value saved-height) diff))
(reset! text-value (str @text-value " "))
(js/setTimeout #(reset! text-value curr-text) 0)
(reset! emoji-kb-extra-height diff))
(when @emoji-kb-extra-height
(reanimated/set-shared-value height
(+ (reanimated/get-shared-value height) @emoji-kb-extra-height))
(reanimated/set-shared-value saved-height
(+ (reanimated/get-shared-value saved-height)
@emoji-kb-extra-height))
(reset! emoji-kb-extra-height nil)))))
(defn handle-kb-hide-android
[{:keys [input-ref]}
{:keys [opacity height saved-height background-y]}
{:keys [window-height lines]}]
(when platform/android?
(let [min-height (get-min-height lines)]
(.blur ^js @input-ref)
(reanimated/animate opacity 0)
(js/setTimeout (fn []
(reanimated/animate height min-height)
(reanimated/set-shared-value saved-height min-height)
(reanimated/set-shared-value background-y (- window-height)))
100))))
(defn handle-layout
[e
{:keys [lock-layout?]}
@@ -445,50 +248,18 @@
(when input-maximized?
(reset! maximized? true)))
(defn store-kb-height
[{:keys [kb-default-height]} keyboard-height]
(when (and (not @kb-default-height) (pos? keyboard-height))
(async-storage/set-item :kb-default-height keyboard-height)))
(defn add-kb-listeners
[{:keys [keyboard-show-listener keyboard-frame-listener keyboard-hide-listener] :as props}
state animations dimensions keyboard-height]
(reset! keyboard-show-listener (.addListener rn/keyboard
"keyboardDidShow"
#(store-kb-height state keyboard-height)))
(reset! keyboard-frame-listener (.addListener
rn/keyboard
"keyboardWillChangeFrame"
#(handle-emoji-kb-ios % props state animations dimensions)))
(reset! keyboard-hide-listener (.addListener rn/keyboard
"keyboardDidHide"
#(handle-kb-hide-android props animations dimensions))))
(defn component-will-unmount
[{:keys [keyboard-show-listener keyboard-hide-listener keyboard-frame-listener]}]
(.remove ^js @keyboard-show-listener)
(.remove ^js @keyboard-hide-listener)
(.remove ^js @keyboard-frame-listener))
(defn gradient-components
[{:keys [input-ref]}
{:keys [gradient-z-index text-value focused?]}
{:keys [gradient-opacity]}
{:keys [lines]}]
[:f>
(fn []
[:<>
[reanimated/linear-gradient (style/top-gradient gradient-opacity @gradient-z-index)]
(when (and (not-empty @text-value) (not @focused?) (> lines 2))
[rn/touchable-without-feedback
{:on-press #(.focus ^js @input-ref)}
[linear-gradient/linear-gradient (style/bottom-gradient)]])])])
(defn use-effect
[props
{:keys [lock-layout? kb-default-height maximized? text-value] :as state}
{:keys [height saved-height container-opacity opacity background-y] :as animations}
{:keys [max-height] :as dimensions}
{:keys [input-content-height input-text] :as chat-input}
{:keys [input-content-height] :as chat-input}
keyboard-height images?]
(rn/use-effect
(fn []
@@ -496,7 +267,7 @@
(reanimated/animate height max-height)
(reanimated/set-shared-value saved-height max-height))
(handle-reenter-screen state dimensions chat-input)
(when (nil? input-text)
(when-not @lock-layout?
(js/setTimeout #(reset! lock-layout? true) 500))
(when-not @kb-default-height
(async-storage/get-item :kb-default-height
@@ -508,32 +279,12 @@
(reanimated/animate container-opacity 1))
(when (and (empty? @text-value) (not images?) (not @maximized?))
(reanimated/animate-delay container-opacity 0.7 200))
(add-kb-listeners props state animations dimensions keyboard-height)
(kb/add-kb-listeners props state animations dimensions keyboard-height)
#(component-will-unmount props))
[max-height]))
(defn get-kb-height
[curr-height default-height]
(if (and default-height (< curr-height default-height))
default-height
curr-height))
(defn calc-lines
[height]
(let [lines (Math/round (/ height c/line-height))]
(if platform/ios? lines (dec lines))))
(defn calc-max-height
[window-height margin-top kb-height images]
(let [max-height
(- window-height margin-top kb-height c/handle-container-height c/actions-container-height)]
(if (seq images)
(- max-height c/images-container-height)
max-height)))
;;; MAIN
(defn sheet
;; safe-area consumer insets makes incorrect values on Android
[insets window-height layout-height opacity background-y]
[:f>
(fn []
@@ -562,23 +313,23 @@
content-height (reagent/atom (or input-content-height
c/input-height))
{:keys [keyboard-shown keyboard-height]} (hooks/use-keyboard)
kb-height (get-kb-height keyboard-height
@(:kb-default-height state))
max-height (calc-max-height window-height
margin-top
kb-height
images)
lines (calc-lines @content-height)
max-lines (calc-lines max-height)
kb-height (kb/get-kb-height keyboard-height
@(:kb-default-height state))
max-height (utils/calc-max-height window-height
margin-top
kb-height
images)
lines (utils/calc-lines @content-height)
max-lines (utils/calc-lines max-height)
initial-height (if (> lines 1)
c/multiline-minimized-height
c/input-height)
animations {:gradient-opacity (reanimated/use-shared-value
0)
:container-opacity (reanimated/use-shared-value
(if (and (nil? input-text)
(not (seq
images)))
(if (utils/empty-input?
input-text
images)
0.7
1))
:height (reanimated/use-shared-value
@@ -586,7 +337,7 @@
:saved-height (reanimated/use-shared-value
initial-height)
:last-height (reanimated/use-shared-value
(bounded-val
(utils/bounded-val
@content-height
c/input-height
max-height))
@@ -603,11 +354,10 @@
[reanimated/view
{:style (style/sheet-container insets (:container-opacity animations))
:on-layout #(handle-layout % state layout-height)}
[bar]
[sub-view/bar]
[reanimated/touchable-opacity
{:active-opacity 1
:on-press #(.focus ^js @(:input-ref props)) ;; for android when first entering
;; screen
:on-press #(.focus ^js @(:input-ref props))
:style (style/input-container (:height animations) max-height)}
[rn/text-input
{:ref #(reset! (:input-ref props) %)
@@ -629,19 +379,11 @@
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
:style (style/input @(:maximized? state)
@(:saved-emoji-kb-extra-height props))}]
[gradient-components props state animations dimensions]]
[sub-view/gradients props state animations dimensions]]
[images/images-list]
[actions (:input-ref props) (:text-value state) (seq images) animations window-height
[actions/view (:input-ref props) (:text-value state) (seq images) animations window-height
insets]]]))]))])
(defn blur-view
[layout-height]
[:f>
(fn []
[reanimated/view {:style (style/blur-container layout-height)}
[blur/view style/blur-view]])])
(defn bottom-sheet-composer
[]
[:f>
@@ -653,5 +395,5 @@
layout-height (reanimated/use-shared-value (+ c/composer-default-height (:bottom insets)))]
[rn/view
[reanimated/view {:style (style/background opacity background-y window-height)}]
[blur-view layout-height]
[sub-view/blur-view layout-height]
[sheet insets window-height layout-height opacity background-y]]))])