Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d433285acb | ||
|
|
eb16f4b6c4 | ||
|
|
9268060aa9 | ||
|
|
7ab9e7abd0 | ||
|
|
2430bde3d5 | ||
|
|
739556f2b4 | ||
|
|
f4ac7a4c51 | ||
|
|
36fac66eac |
@@ -3,6 +3,7 @@
|
||||
[quo.react :as react]
|
||||
[quo.react-native :as rn]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.config :as config]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]
|
||||
[native-module.core :as native-module]))
|
||||
@@ -167,17 +168,20 @@
|
||||
cursor (+ at-sign-idx (count primary-name) 2)]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))
|
||||
:set-text-input-value [chat-id new-text text-input-ref]
|
||||
:dispatch [:chat.ui/set-chat-input-text new-text chat-id]}
|
||||
;; NOTE(rasom): Some keyboards do not react on selection property passed to
|
||||
;; text input (specifically Samsung keyboard with predictive text set on).
|
||||
;; In this case, if the user continues typing after the programmatic change,
|
||||
;; the new text is added to the last known cursor position before
|
||||
;; programmatic change. By calling `reset-text-input-cursor` we force the
|
||||
;; keyboard's cursor position to be changed before the next input.
|
||||
(reset-text-input-cursor text-input-ref cursor)
|
||||
(let [common {:db (-> db
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))
|
||||
:dispatch [:chat.ui/set-chat-input-text new-text chat-id]}
|
||||
extra (if (not config/new-composer-enabled?)
|
||||
;; NOTE(rasom): Some keyboards do not react on selection property passed to
|
||||
;; text input (specifically Samsung keyboard with predictive text set on).
|
||||
;; In this case, if the user continues typing after the programmatic change,
|
||||
;; the new text is added to the last known cursor position before
|
||||
;; programmatic change. By calling `reset-text-input-cursor` we force the
|
||||
;; keyboard's cursor position to be changed before the next input.
|
||||
{:set-text-input-value [chat-id new-text text-input-ref]
|
||||
:reset-text-input-cursor (reset-text-input-cursor text-input-ref cursor)}
|
||||
{})]
|
||||
(merge common extra))
|
||||
(recheck-at-idxs public-key))))
|
||||
|
||||
(rf/defn clear-suggestions
|
||||
|
||||
@@ -159,4 +159,4 @@
|
||||
|
||||
(def default-kdf-iterations 3200)
|
||||
|
||||
(def ^:const new-composer-enabled? false)
|
||||
(def ^:const new-composer-enabled? true)
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
(def ^:const edit-container-height 32)
|
||||
|
||||
(def ^:const mentions-max-height 240)
|
||||
|
||||
(def ^:const extra-content-offset (if platform/ios? 6 0))
|
||||
|
||||
(def ^:const content-change-threshold 10)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.handlers
|
||||
(:require [react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :as oops]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
|
||||
[utils.re-frame :as rf]))
|
||||
(:require
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :as oops]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn focus
|
||||
[{:keys [input-ref] :as props}
|
||||
@@ -70,7 +71,8 @@
|
||||
(reanimated/animate height new-height)
|
||||
(reanimated/set-shared-value saved-height new-height))
|
||||
(when (= new-height max-height)
|
||||
(reset! maximized? true))
|
||||
(reset! maximized? true)
|
||||
(rf/dispatch [:chat.ui/set-input-maximized true]))
|
||||
(if (utils/show-background? saved-height max-height new-height)
|
||||
(do
|
||||
(reanimated/set-shared-value background-y 0)
|
||||
@@ -82,10 +84,12 @@
|
||||
|
||||
(defn scroll
|
||||
[event
|
||||
{:keys [scroll-y]}
|
||||
{:keys [gradient-z-index focused?]}
|
||||
{:keys [gradient-opacity]}
|
||||
{:keys [lines max-lines]}]
|
||||
(let [y (oops/oget event "nativeEvent.contentOffset.y")]
|
||||
(reset! scroll-y y)
|
||||
(when (utils/show-top-gradient? y lines max-lines gradient-opacity focused?)
|
||||
(reset! gradient-z-index 1)
|
||||
(js/setTimeout #(reanimated/animate gradient-opacity 1) 0))
|
||||
@@ -105,10 +109,12 @@
|
||||
(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])
|
||||
(rf/dispatch [:mention/on-change-text text]))
|
||||
|
||||
(defn selection-change
|
||||
[event {:keys [lock-selection? cursor-position]}]
|
||||
(println "selectionc ahnge")
|
||||
(when-not @lock-selection?
|
||||
(reset! cursor-position (oops/oget event "nativeEvent.selection.end"))))
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.mentions.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]))
|
||||
|
||||
|
||||
(defn shadow
|
||||
[]
|
||||
(if platform/ios?
|
||||
{:shadow-radius (colors/theme-colors 30 50)
|
||||
:shadow-opacity (colors/theme-colors 0.1 0.7)
|
||||
:shadow-color colors/neutral-100
|
||||
:shadow-offset {:width 0 :height (colors/theme-colors 8 12)}}
|
||||
{:elevation 10}))
|
||||
|
||||
(defn container
|
||||
[opacity bottom]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
(merge
|
||||
{:position :absolute
|
||||
:bottom bottom
|
||||
:left 8
|
||||
:right 8
|
||||
:border-radius 16
|
||||
:z-index 4
|
||||
:max-height constants/mentions-max-height
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)}
|
||||
(shadow))))
|
||||
@@ -0,0 +1,67 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.mentions.view
|
||||
(:require
|
||||
[react-native.hooks :as hooks]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.common.contact-list-item.view :as contact-list-item]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.mentions.style :as style]))
|
||||
|
||||
(defn update-cursor
|
||||
[user {:keys [cursor-position input-ref]}]
|
||||
(when platform/android?
|
||||
(let [new-cursor-pos (+ (count (:primary-name user)) @cursor-position)]
|
||||
(reset! cursor-position new-cursor-pos)
|
||||
(reagent/next-tick #(when @input-ref
|
||||
(.setNativeProps ^js @input-ref
|
||||
(clj->js {:selection {:start new-cursor-pos
|
||||
:end
|
||||
new-cursor-pos}})))))))
|
||||
|
||||
(defn mention-item
|
||||
[user _ _ render-data]
|
||||
[contact-list-item/contact-list-item
|
||||
{:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/select-mention nil user])
|
||||
(update-cursor user render-data))}
|
||||
user])
|
||||
|
||||
(defn- f-view
|
||||
[suggestions-atom props state animations max-height cursor-pos]
|
||||
(let [{:keys [keyboard-height]} (hooks/use-keyboard)
|
||||
suggestions (rf/sub [:chat/mention-suggestions])
|
||||
opacity (reanimated/use-shared-value (if (seq suggestions) 1 0))
|
||||
size (count suggestions)
|
||||
data {:keyboard-height keyboard-height
|
||||
:insets (safe-area/get-insets)
|
||||
:curr-height (reanimated/get-shared-value (:height animations))
|
||||
:window-height (rf/sub [:dimensions/window-height])
|
||||
:reply (rf/sub [:chats/reply-message])
|
||||
:edit (rf/sub [:chats/edit-message])}
|
||||
mentions-pos (utils/calc-suggestions-position cursor-pos max-height size state data)]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(if (seq suggestions)
|
||||
(reset! suggestions-atom suggestions)
|
||||
(js/setTimeout #(reset! suggestions-atom suggestions) 300))
|
||||
(reanimated/animate opacity (if (seq suggestions) 1 0)))
|
||||
[(seq suggestions)])
|
||||
[reanimated/view
|
||||
{:style (style/container opacity mentions-pos)}
|
||||
[rn/flat-list
|
||||
{:keyboard-should-persist-taps :always
|
||||
:data (vals @suggestions-atom)
|
||||
:key-fn :key
|
||||
:render-fn mention-item
|
||||
:render-data {:cursor-position (:cursor-position state)
|
||||
:input-ref (:input-ref props)}
|
||||
:accessibility-label :mentions-list}]]))
|
||||
|
||||
(defn view
|
||||
[props state animations max-height cursor-pos]
|
||||
(let [suggestions-atom (reagent/atom {})]
|
||||
[:f> f-view suggestions-atom props state animations max-height cursor-pos]))
|
||||
@@ -0,0 +1,42 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.selectable-input.view
|
||||
(:require [utils.i18n :as i18n]))
|
||||
|
||||
(declare first-level-menu-items second-level-menu-items)
|
||||
|
||||
(defn calculate-input-text
|
||||
[{:keys [full-text selection-start selection-end]} content]
|
||||
(let [head (subs full-text 0 selection-start)
|
||||
tail (subs full-text selection-end)]
|
||||
(str head content tail)))
|
||||
|
||||
(defn reset-to-first-level-menu
|
||||
[first-level menu-items]
|
||||
(reset! first-level true)
|
||||
(reset! menu-items first-level-menu-items))
|
||||
|
||||
(defn append-markdown-char
|
||||
[{:keys [first-level menu-items content selection-start selection-end text-input-handle
|
||||
selection-event]
|
||||
:as params} wrap-chars]
|
||||
(let [content (str wrap-chars content wrap-chars)
|
||||
new-text (calculate-input-text params content)
|
||||
len-wrap-chars (count wrap-chars)
|
||||
selection-start (+ selection-start len-wrap-chars)
|
||||
selection-end (+ selection-end len-wrap-chars)]
|
||||
;don't update selection directly here, process it within on-selection-change instead
|
||||
;so that we can avoid java.lang.IndexOutOfBoundsException: setSpan..
|
||||
(reset! selection-event {:start selection-start
|
||||
:end selection-end
|
||||
:text-input-handle text-input-handle})
|
||||
;(update-input-text params new-text)
|
||||
(reset-to-first-level-menu first-level menu-items)))
|
||||
|
||||
|
||||
(def second-level-menus
|
||||
{:bold #(append-markdown-char % "**")
|
||||
|
||||
:italic #(append-markdown-char % "*")
|
||||
|
||||
:strikethrough #(append-markdown-char % "~~")})
|
||||
|
||||
(def second-level-menu-items (map i18n/label (keys second-level-menus)))
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
@@ -90,3 +91,53 @@
|
||||
(reanimated/set-shared-value last-height constants/input-height))
|
||||
(reset! text-value "")
|
||||
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height]))
|
||||
|
||||
(defn update-input
|
||||
[{:keys [input-ref]}
|
||||
{:keys [text-value]}
|
||||
input-text]
|
||||
(when (and input-text (not= @text-value input-text))
|
||||
(reset! text-value input-text)
|
||||
(when @input-ref
|
||||
(.setNativeProps ^js @input-ref (clj->js {:text input-text})))))
|
||||
|
||||
(defn count-lines
|
||||
[s]
|
||||
(-> s
|
||||
(string/split #"\n" -1)
|
||||
(butlast)
|
||||
count))
|
||||
|
||||
(defn cursor-y-position-relative-to-container
|
||||
[{:keys [scroll-y]}
|
||||
{:keys [cursor-position text-value]}]
|
||||
(let [sub-text (subs @text-value 0 @cursor-position)
|
||||
sub-text-lines (count-lines sub-text)
|
||||
scrolled-lines (Math/round (/ @scroll-y constants/line-height))
|
||||
sub-text-lines-in-view (- sub-text-lines scrolled-lines)]
|
||||
(* sub-text-lines-in-view constants/line-height)))
|
||||
|
||||
(defn calc-suggestions-position
|
||||
[cursor-pos max-height size
|
||||
{:keys [maximized?]}
|
||||
{:keys [insets curr-height window-height keyboard-height edit reply]}]
|
||||
(let [base (+ constants/composer-default-height (:bottom insets) 8)
|
||||
base (+ base (- curr-height constants/input-height))
|
||||
base (if edit
|
||||
(+ base constants/edit-container-height)
|
||||
base)
|
||||
base (if reply
|
||||
(+ base constants/reply-container-height)
|
||||
base)
|
||||
view-height (- window-height keyboard-height (:top insets))
|
||||
container-height (bounded-val
|
||||
(* (/ constants/mentions-max-height 4) size)
|
||||
(/ constants/mentions-max-height 4)
|
||||
constants/mentions-max-height)]
|
||||
(if @maximized?
|
||||
(if (< (+ cursor-pos container-height) max-height)
|
||||
(+ constants/actions-container-height (:bottom insets))
|
||||
(+ constants/actions-container-height (:bottom insets) (- max-height cursor-pos) 18))
|
||||
(if (< (+ base container-height) view-height)
|
||||
base
|
||||
(+ constants/actions-container-height (:bottom insets) (- curr-height cursor-pos) 18)))))
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[oops.core :as oops]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.style :as style]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.images.view :as images]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.reply.view :as reply]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.edit.view :as edit]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.mentions.view :as mentions]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.actions.view :as actions]
|
||||
@@ -20,131 +22,150 @@
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.effects :as effects]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.gesture :as drag-gesture]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.handlers :as handler]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.gradients.view :as gradients]))
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.gradients.view :as gradients]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.selectable-input.view :as selectable-input]))
|
||||
|
||||
(defn sheet
|
||||
[insets window-height blur-height opacity background-y]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [props {:input-ref (atom nil)
|
||||
:keyboard-show-listener (atom nil)
|
||||
:keyboard-frame-listener (atom nil)
|
||||
:keyboard-hide-listener (atom nil)
|
||||
:emoji-kb-extra-height (atom nil)
|
||||
:saved-emoji-kb-extra-height (atom nil)
|
||||
:replying? (atom nil)
|
||||
:sending-images? (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)
|
||||
:gradient-z-index (reagent/atom 0)
|
||||
:kb-default-height (reagent/atom nil)
|
||||
:gesture-enabled? (reagent/atom true)
|
||||
:lock-selection? (reagent/atom true)
|
||||
:focused? (reagent/atom false)
|
||||
:lock-layout? (reagent/atom false)
|
||||
:maximized? (reagent/atom false)
|
||||
:recording? (reagent/atom false)}]
|
||||
(let [props {:input-ref (atom nil)
|
||||
:keyboard-show-listener (atom nil)
|
||||
:keyboard-frame-listener (atom nil)
|
||||
:keyboard-hide-listener (atom nil)
|
||||
:emoji-kb-extra-height (atom nil)
|
||||
:saved-emoji-kb-extra-height (atom nil)
|
||||
:replying? (atom nil)
|
||||
:sending-images? (atom nil)
|
||||
:editing? (atom nil)
|
||||
:record-permission? (atom nil)
|
||||
:record-reset-fn (atom nil)
|
||||
:scroll-y (atom 0)}
|
||||
state {:text-value (reagent/atom "")
|
||||
:cursor-position (reagent/atom 0)
|
||||
:saved-cursor-position (reagent/atom 0)
|
||||
:gradient-z-index (reagent/atom 0)
|
||||
:kb-default-height (reagent/atom nil)
|
||||
:gesture-enabled? (reagent/atom true)
|
||||
:lock-selection? (reagent/atom true)
|
||||
:focused? (reagent/atom false)
|
||||
:lock-layout? (reagent/atom false)
|
||||
:maximized? (reagent/atom false)
|
||||
:recording? (reagent/atom false)}
|
||||
selectable-input-ref (atom nil)
|
||||
menu-items (reagent/atom selectable-input/first-level-menu-items)
|
||||
manager (rn/selectable-text-input-manager)]
|
||||
[: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])
|
||||
(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]
|
||||
:as chat-input} (rf/sub [:chats/current-chat-input])
|
||||
content-height (reagent/atom (or input-content-height
|
||||
constants/input-height))
|
||||
:as chat-input} (rf/sub [:chats/current-chat-input])
|
||||
content-height (reagent/atom (or input-content-height
|
||||
constants/input-height))
|
||||
{:keys [keyboard-shown keyboard-height]} (hooks/use-keyboard)
|
||||
kb-height (kb/get-kb-height keyboard-height
|
||||
@(:kb-default-height state))
|
||||
max-height (utils/calc-max-height window-height
|
||||
kb-height
|
||||
insets
|
||||
(seq images)
|
||||
reply
|
||||
edit)
|
||||
lines (utils/calc-lines @content-height)
|
||||
max-lines (utils/calc-lines max-height)
|
||||
initial-height (if (> lines 1)
|
||||
constants/multiline-minimized-height
|
||||
constants/input-height)
|
||||
animations {:gradient-opacity (reanimated/use-shared-value
|
||||
0)
|
||||
:container-opacity (reanimated/use-shared-value
|
||||
(if (utils/empty-input?
|
||||
input-text
|
||||
images
|
||||
reply
|
||||
audio)
|
||||
0.7
|
||||
1))
|
||||
:height (reanimated/use-shared-value
|
||||
initial-height)
|
||||
:saved-height (reanimated/use-shared-value
|
||||
initial-height)
|
||||
:last-height (reanimated/use-shared-value
|
||||
(utils/bounded-val
|
||||
@content-height
|
||||
constants/input-height
|
||||
max-height))
|
||||
:opacity opacity
|
||||
:background-y background-y}
|
||||
dimensions {:content-height content-height
|
||||
:max-height max-height
|
||||
:window-height window-height
|
||||
:lines lines
|
||||
:max-lines max-lines}
|
||||
show-bottom-gradient? (utils/show-bottom-gradient? state dimensions)]
|
||||
kb-height (kb/get-kb-height keyboard-height
|
||||
@(:kb-default-height state))
|
||||
max-height (utils/calc-max-height window-height
|
||||
kb-height
|
||||
insets
|
||||
(boolean (seq images))
|
||||
reply
|
||||
edit)
|
||||
lines (utils/calc-lines @content-height)
|
||||
max-lines (utils/calc-lines max-height)
|
||||
initial-height (if (> lines 1)
|
||||
constants/multiline-minimized-height
|
||||
constants/input-height)
|
||||
animations {:gradient-opacity (reanimated/use-shared-value
|
||||
0)
|
||||
:container-opacity (reanimated/use-shared-value
|
||||
(if (utils/empty-input?
|
||||
input-text
|
||||
images
|
||||
reply
|
||||
audio)
|
||||
0.7
|
||||
1))
|
||||
:height (reanimated/use-shared-value
|
||||
initial-height)
|
||||
:saved-height (reanimated/use-shared-value
|
||||
initial-height)
|
||||
:last-height (reanimated/use-shared-value
|
||||
(utils/bounded-val
|
||||
@content-height
|
||||
constants/input-height
|
||||
max-height))
|
||||
:opacity opacity
|
||||
:background-y background-y}
|
||||
dimensions {:content-height content-height
|
||||
:max-height max-height
|
||||
:window-height window-height
|
||||
:lines lines
|
||||
:max-lines max-lines}
|
||||
show-bottom-gradient? (utils/show-bottom-gradient? state dimensions)
|
||||
cursor-pos (utils/cursor-y-position-relative-to-container
|
||||
props
|
||||
state)]
|
||||
(effects/initialize props
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
chat-input
|
||||
keyboard-height
|
||||
(seq images)
|
||||
(boolean (seq images))
|
||||
reply
|
||||
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 state]
|
||||
[edit/view edit #(utils/cancel-edit-message state animations)]
|
||||
[reanimated/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props)))
|
||||
:style (style/input-container (:height animations) max-height)
|
||||
:accessibility-label :message-input-container}
|
||||
[rn/text-input
|
||||
{:ref #(reset! (:input-ref props) %)
|
||||
:default-value @(:text-value state)
|
||||
:on-focus #(handler/focus props state animations dimensions)
|
||||
:on-blur #(handler/blur state animations dimensions images reply)
|
||||
:on-content-size-change #(handler/content-size-change %
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
(or keyboard-shown edit))
|
||||
:on-scroll #(handler/scroll % state animations dimensions)
|
||||
:on-change-text #(handler/change-text % props state)
|
||||
:on-selection-change #(handler/selection-change % state)
|
||||
:max-height max-height
|
||||
:max-font-size-multiplier 1
|
||||
:multiline true
|
||||
:placeholder (i18n/label :t/type-something)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:style (style/input props state)
|
||||
:accessibility-label :chat-message-input}]
|
||||
[gradients/view props state animations show-bottom-gradient?]]
|
||||
[images/images-list]
|
||||
[actions/view props state animations window-height insets (seq images)]]]))]))])
|
||||
(rn/use-effect (fn []
|
||||
(let [selectable-text-input-handle (rn/find-node-handle @selectable-input-ref)
|
||||
text-input-handle (rn/find-node-handle @(:input-ref props))]
|
||||
(oops/ocall manager :setupMenuItems selectable-text-input-handle text-input-handle))))
|
||||
(utils/update-input props state input-text)
|
||||
[:<>
|
||||
[mentions/view props state animations max-height cursor-pos]
|
||||
[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 state]
|
||||
[edit/view edit #(utils/cancel-edit-message state animations)]
|
||||
[reanimated/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props)))
|
||||
:style (style/input-container (:height animations) max-height)
|
||||
:accessibility-label :message-input-container}
|
||||
[rn/selectable-text-input {:ref #(reset! selectable-input-ref %)
|
||||
:menuItems @menu-items}
|
||||
[rn/text-input
|
||||
{:ref #(reset! (:input-ref props) %)
|
||||
:default-value @(:text-value state)
|
||||
:on-focus #(handler/focus props state animations dimensions)
|
||||
:on-blur #(handler/blur state animations dimensions images reply)
|
||||
:on-content-size-change #(handler/content-size-change %
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
(or keyboard-shown edit))
|
||||
:on-scroll #(handler/scroll % props state animations dimensions)
|
||||
:on-change-text #(handler/change-text % props state)
|
||||
:on-selection-change #(handler/selection-change % state)
|
||||
:on-selection (fn [e] (println "onselection"))
|
||||
:max-height max-height
|
||||
:max-font-size-multiplier 1
|
||||
:multiline true
|
||||
:placeholder (i18n/label :t/type-something)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:style (style/input props state)
|
||||
:accessibility-label :chat-message-input}]]
|
||||
[gradients/view props state animations show-bottom-gradient?]]
|
||||
[images/images-list]
|
||||
[actions/view props state animations window-height insets
|
||||
(boolean (seq images))]]]]))]))])
|
||||
|
||||
(defn f-bottom-sheet-composer
|
||||
[insets]
|
||||
|
||||
Reference in New Issue
Block a user