parent
08fb0de7b0
commit
4e6a37fdd0
|
@ -51,7 +51,8 @@
|
|||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/cursor chat-id] cursor)
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))}
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))
|
||||
:set-text-input-value [chat-id new-text text-input-ref]}
|
||||
(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).
|
||||
|
@ -126,7 +127,6 @@
|
|||
|
||||
text (get-in message [:content :text])]
|
||||
{:dispatch [:chat.ui.input/set-chat-input-text text current-chat-id]
|
||||
:set-input-text [current-chat-id text]
|
||||
:db (-> db
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
|
||||
message)
|
||||
|
@ -196,7 +196,7 @@
|
|||
[{:keys [db] :as cofx}]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
(fx/merge cofx
|
||||
{:set-input-text [current-chat-id ""]}
|
||||
{:set-text-input-value [current-chat-id ""]}
|
||||
(clean-input current-chat-id)
|
||||
(mentions/clear-mentions)
|
||||
(mentions/clear-cursor))))
|
||||
|
|
|
@ -208,7 +208,7 @@
|
|||
e)) text-with-mentions)
|
||||
info (mentions/->info hydrated-mentions)
|
||||
new-text (string/join (map second hydrated-mentions))]
|
||||
{:set-input-text [chat-id new-text]
|
||||
{:set-text-input-value [chat-id new-text]
|
||||
:db
|
||||
(-> db
|
||||
(assoc-in [:chats/cursor chat-id] (:mention-end info))
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
[quo2.core :as quo]
|
||||
[quo.gesture-handler :as gesture-handler]))
|
||||
|
||||
(defn edit-message []
|
||||
(defn edit-message [reset-composer-callback]
|
||||
[rn/view {:style style/container
|
||||
:accessibility-label :edit-message}
|
||||
[rn/view {:style style/content-container}
|
||||
|
@ -20,7 +20,8 @@
|
|||
(i18n/label :t/editing-message)]]]
|
||||
[gesture-handler/touchable-without-feedback
|
||||
{:accessibility-label :reply-cancel-button
|
||||
:on-press #(rf/dispatch [:chat.ui/cancel-message-edit])}
|
||||
:on-press #(do (reset-composer-callback true)
|
||||
(rf/dispatch [:chat.ui/cancel-message-edit]))}
|
||||
[quo/button {:width 24
|
||||
:size 24
|
||||
:type :outline}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
(defn edit-message-auto-focus-wrapper [text-input-ref _]
|
||||
(let [had-edit (atom nil)]
|
||||
(fn [_ edit]
|
||||
(fn [_ edit cleanup-composer-callback]
|
||||
(focus-input-on-edit edit had-edit text-input-ref)
|
||||
(when edit
|
||||
[rn/view {:style style/container}
|
||||
[edit/edit-message]]))))
|
||||
[edit/edit-message cleanup-composer-callback]]))))
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[oops.core :as oops]))
|
||||
|
||||
(defonce input-texts (atom {}))
|
||||
(defonce mentions-enabled (reagent/atom {}))
|
||||
(defonce mentions-enabled? (reagent/atom {}))
|
||||
(defonce chat-input-key (reagent/atom 1))
|
||||
(defonce text-input-ref (reagent/atom nil))
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
|||
:chat.ui/clear-inputs
|
||||
(fn []
|
||||
(reset! input-texts {})
|
||||
(reset! mentions-enabled {})
|
||||
(reset! mentions-enabled? {})
|
||||
(reset! chat-input-key 1)))
|
||||
|
||||
(defn input-focus [text-input-ref]
|
||||
|
@ -51,14 +51,14 @@
|
|||
|
||||
(defn reset-input [refs chat-id]
|
||||
(some-> ^js (quo.react/current-ref (:text-input-ref refs)) .clear)
|
||||
(swap! mentions-enabled update :render not)
|
||||
(swap! mentions-enabled? update :render not)
|
||||
(swap! input-texts dissoc chat-id))
|
||||
|
||||
(defn clear-input [chat-id refs]
|
||||
(hide-send refs)
|
||||
(if (get @mentions-enabled chat-id)
|
||||
(if (get @mentions-enabled? chat-id)
|
||||
(do
|
||||
(swap! mentions-enabled dissoc chat-id)
|
||||
(swap! mentions-enabled? dissoc chat-id)
|
||||
;;we need this timeout, because if we clear text input and first index was a mention object with blue color,
|
||||
;;after clearing text will be typed with this blue color, so we render white text first and then clear it
|
||||
(js/setTimeout #(reset-input refs chat-id) 50))
|
||||
|
@ -105,8 +105,8 @@
|
|||
(when (and (empty? prev-text) (seq text))
|
||||
(show-send refs))
|
||||
|
||||
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled assoc chat-id true))
|
||||
(when (and (not (get @mentions-enabled? chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled? assoc chat-id true))
|
||||
|
||||
;; NOTE(rasom): on iOS `on-selection-change` is canceled in case if it
|
||||
;; happens during typing because it is not needed for mention
|
||||
|
@ -129,8 +129,8 @@
|
|||
range (.-range ^js native-event)
|
||||
start (.-start ^js range)
|
||||
end (.-end ^js range)]
|
||||
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled assoc chat-id true))
|
||||
(when (and (not (get @mentions-enabled? chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled? assoc chat-id true))
|
||||
|
||||
(>evt
|
||||
[::mentions/on-text-input
|
||||
|
@ -144,12 +144,13 @@
|
|||
(when platform/android?
|
||||
(>evt [::mentions/calculate-suggestions mentionable-users]))))
|
||||
|
||||
(defn text-input [{:keys [set-active-panel refs chat-id sending-image on-content-size-change]}]
|
||||
(let [cooldown-enabled? (<sub [:chats/current-chat-cooldown-enabled?])
|
||||
(defn text-input [{:keys [set-active-panel refs chat-id sending-image on-content-size-change initial-value]}]
|
||||
(let [_ (reset! text-input-ref (:text-input-ref refs))
|
||||
cooldown-enabled? (<sub [:chats/current-chat-cooldown-enabled?])
|
||||
mentionable-users (<sub [:chats/mentionable-users])
|
||||
timeout-id (atom nil)
|
||||
last-text-change (atom nil)
|
||||
mentions-enabled (get @mentions-enabled chat-id)
|
||||
timeout-id (reagent/atom nil)
|
||||
last-text-change (reagent/atom nil)
|
||||
mentions-enabled? (get @mentions-enabled? chat-id)
|
||||
props {:style (style/text-input)
|
||||
:ref (:text-input-ref refs)
|
||||
:max-font-size-multiplier 1
|
||||
|
@ -159,6 +160,7 @@
|
|||
:editable (not cooldown-enabled?)
|
||||
:blur-on-submit false
|
||||
:auto-focus false
|
||||
:default-value initial-value
|
||||
:on-focus #(set-active-panel nil)
|
||||
:max-length chat.constants/max-text-size
|
||||
:placeholder-text-color (:text-02 @quo.colors/theme)
|
||||
|
@ -175,7 +177,7 @@
|
|||
:on-text-input (partial on-text-input mentionable-users chat-id)}
|
||||
input-with-mentions (<sub [:chat/input-with-mentions])
|
||||
children (fn []
|
||||
(if mentions-enabled
|
||||
(if mentions-enabled?
|
||||
(map-indexed
|
||||
(fn [index [item text]]
|
||||
[index [item]]
|
||||
|
@ -203,8 +205,10 @@
|
|||
(.setNativeProps ^js text-input (clj->js {:text text})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:set-input-text
|
||||
(fn [[chat-id text]]
|
||||
:set-text-input-value
|
||||
(fn [[chat-id text local-text-input-ref]]
|
||||
(when local-text-input-ref
|
||||
(reset! text-input-ref local-text-input-ref))
|
||||
(if platform/ios?
|
||||
(.setNativeProps ^js (quo.react/current-ref @text-input-ref) (clj->js {:text text}))
|
||||
(do
|
||||
|
@ -297,7 +301,7 @@
|
|||
(let [text-input-handle (rn/find-node-handle @text-input-ref)]
|
||||
(oops/ocall manager :startActionMode text-input-handle))))
|
||||
|
||||
:render
|
||||
:reagent-render
|
||||
(fn [_]
|
||||
(let [ref #(do (reset! text-input-ref %)
|
||||
(when ref
|
||||
|
@ -333,9 +337,9 @@
|
|||
:chat-id chat-id
|
||||
:selection-event selection-event})))
|
||||
props (merge props {:ref ref
|
||||
:style nil
|
||||
:style (dissoc style :margin-horizontal)
|
||||
:on-selection-change on-selection-change
|
||||
:on-selection on-selection})]
|
||||
[rn-selectable-text-input {:menuItems @menu-items :style style}
|
||||
[rn/text-input props
|
||||
[children]]]))})))
|
||||
children]]))})))
|
||||
|
|
|
@ -40,17 +40,18 @@
|
|||
ens-name?
|
||||
(assoc :subtitle alias))]]))
|
||||
|
||||
(defn autocomplete-mentions [suggestions]
|
||||
(defn autocomplete-mentions [suggestions text-input-ref]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [animation (reanimated/use-shared-value 0)]
|
||||
(quo.react/effect! #(reanimated/set-shared-value animation (reanimated/with-timing (if (seq suggestions) 0 200))))
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY animation}]}
|
||||
{:bottom 0 :position :absolute :z-index 5 :max-height 180})}
|
||||
{:bottom 0 :position :absolute :z-index 5 :elevation 5 :max-height 180})}
|
||||
[list/flat-list
|
||||
{:keyboardShouldPersistTaps :always
|
||||
:data suggestions
|
||||
:key-fn first
|
||||
:render-fn mention-item
|
||||
:render-data text-input-ref
|
||||
:content-container-style {:padding-bottom 12}}]]))])
|
||||
|
|
|
@ -19,33 +19,42 @@
|
|||
[i18n.i18n :as i18n]
|
||||
[status-im.ui2.screens.chat.composer.edit.view :as edit]))
|
||||
|
||||
(defn calculate-y [context keyboard-shown min-y max-y added-value]
|
||||
(if keyboard-shown
|
||||
(defn calculate-y [context min-y max-y added-value chat-id]
|
||||
(let [input-text (:input-text (get (<sub [:chat/inputs]) chat-id))
|
||||
num-lines (count (string/split input-text "\n"))]
|
||||
(if (= (:state @context) :max)
|
||||
max-y
|
||||
(do (swap! context assoc :state :max) max-y)
|
||||
(if (< (:y @context) max-y)
|
||||
(+ (:y @context) added-value)
|
||||
(do
|
||||
(swap! context assoc :state :max)
|
||||
max-y)))
|
||||
(do
|
||||
(swap! context assoc :state :min)
|
||||
min-y)))
|
||||
(if (<= 5 num-lines)
|
||||
(do (swap! context assoc :state :max) max-y)
|
||||
(do (swap! context assoc :state :min) min-y))))))
|
||||
|
||||
(defn calculate-y-with-mentions [y max-y max-height chat-id suggestions reply]
|
||||
(let [input-text (:input-text (get (<sub [:chat/inputs]) chat-id))
|
||||
num-lines (count (string/split input-text "\n"))
|
||||
text-height (* num-lines 22)
|
||||
mentions-height (min 132 (+ 16 (* 46 (- (count suggestions) 1))))
|
||||
should-translate (if (< (- max-height text-height) mentions-height) true false)
|
||||
should-translate? (if (< (- max-height text-height) mentions-height) true false)
|
||||
min-value (if-not reply mentions-height (+ mentions-height 44))
|
||||
; translate value when mentions list appear while at bottom of expanded input sheet
|
||||
mentions-translate-value (if should-translate (min min-value (- mentions-height (- max-height text-height))) mentions-height)]
|
||||
(when (or (< y max-y) should-translate) mentions-translate-value)))
|
||||
mentions-translate-value (if should-translate? (min min-value (- mentions-height (- max-height text-height))) mentions-height)]
|
||||
(when (or (< y max-y) should-translate?) mentions-translate-value)))
|
||||
|
||||
(defn get-y-value [context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply]
|
||||
(let [y (calculate-y context keyboard-shown min-y max-y added-value)]
|
||||
y (+ y (when (seq suggestions) (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)))))
|
||||
(defn get-y-value [context min-y max-y added-value max-height chat-id suggestions reply]
|
||||
(let [y (calculate-y context min-y max-y added-value chat-id)
|
||||
y-with-mentions (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)]
|
||||
(+ y (when (seq suggestions) y-with-mentions))))
|
||||
|
||||
(defn- clean-and-minimize-composer
|
||||
([context chat-id refs min-y]
|
||||
(clean-and-minimize-composer context chat-id refs min-y false))
|
||||
([context chat-id refs min-y edit?]
|
||||
(input/clear-input chat-id refs)
|
||||
(swap! context assoc :y (if edit?
|
||||
(- min-y 38)
|
||||
min-y))
|
||||
(swap! context assoc :clear true)))
|
||||
|
||||
(defn get-bottom-sheet-gesture [context translate-y text-input-ref keyboard-shown min-y max-y shared-height max-height set-bg-opacity]
|
||||
(-> (gesture/gesture-pan)
|
||||
|
@ -73,7 +82,6 @@
|
|||
(reanimated/set-shared-value shared-height (reanimated/with-timing max-height))
|
||||
(set-bg-opacity 1))
|
||||
(do
|
||||
(swap! context assoc :state :min)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
|
||||
(set-bg-opacity 0)
|
||||
|
@ -90,7 +98,7 @@
|
|||
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
|
||||
(set-bg-opacity 0))
|
||||
(when (not= (:state @context) :max)
|
||||
(let [new-y (+ min-y (- (max (oget evt "nativeEvent" "contentSize" "height") 22) 22))]
|
||||
(let [new-y (+ min-y (- (max (oget evt "nativeEvent" "contentSize" "height") 40) 40))]
|
||||
(if (< new-y max-y)
|
||||
(do
|
||||
(if (> (- max-y new-y) 120)
|
||||
|
@ -127,7 +135,7 @@
|
|||
:pdy 0 ;used for gesture
|
||||
:state :min ;:min, :custom-chat-available, :custom-chat-unavailable, :max
|
||||
:clear false})
|
||||
keyboard-was-shown (atom false)
|
||||
keyboard-was-shown? (atom false)
|
||||
text-input-ref (quo.react/create-ref)
|
||||
send-ref (quo.react/create-ref)
|
||||
refs {:send-ref send-ref
|
||||
|
@ -144,34 +152,32 @@
|
|||
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56 - top-bar height
|
||||
added-value (if (and (not (seq suggestions)) (or edit reply)) 38 0) ; increased height of input box needed when reply
|
||||
min-y (+ min-y (when (or edit reply) 38))
|
||||
y (get-y-value context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply)
|
||||
y (get-y-value context min-y max-y added-value max-height chat-id suggestions reply)
|
||||
translate-y (reanimated/use-shared-value 0)
|
||||
shared-height (reanimated/use-shared-value min-y)
|
||||
bg-opacity (reanimated/use-shared-value 0)
|
||||
clean-and-minimize-composer-fn #(clean-and-minimize-composer context chat-id refs min-y %)
|
||||
bg-bottom (reanimated/use-shared-value (- window-height))
|
||||
|
||||
set-bg-opacity (fn [value]
|
||||
(reanimated/set-shared-value bg-bottom (if (= value 1) 0 (- window-height)))
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing value)))
|
||||
input-content-change (get-input-content-change context translate-y shared-height max-height
|
||||
set-bg-opacity keyboard-shown min-y max-y)
|
||||
bottom-sheet-gesture (get-bottom-sheet-gesture context translate-y (:text-input-ref refs) keyboard-shown
|
||||
min-y max-y shared-height max-height set-bg-opacity)]
|
||||
blank-composer? (string/blank? (get @input/input-texts chat-id))
|
||||
bottom-sheet-gesture (get-bottom-sheet-gesture context translate-y text-input-ref keyboard-shown
|
||||
min-y max-y shared-height max-height set-bg-opacity)
|
||||
initial-value (or (get @input/input-texts chat-id) nil)]
|
||||
(quo.react/effect! #(do
|
||||
(when (and @keyboard-was-shown (not keyboard-shown))
|
||||
(when (and @keyboard-was-shown? (not keyboard-shown))
|
||||
(swap! context assoc :state :min))
|
||||
(reset! keyboard-was-shown keyboard-shown)
|
||||
(when blank-composer?
|
||||
(clean-and-minimize-composer-fn false))
|
||||
(reset! keyboard-was-shown? keyboard-shown)
|
||||
(if (#{:max :custom-chat-unavailable} (:state @context))
|
||||
(set-bg-opacity 1)
|
||||
(set-bg-opacity 0))
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing (min y max-height)))))
|
||||
(quo.react/effect! #(when (and (not edit) (= (:state @context) :max))
|
||||
(swap! context assoc :state :min)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
|
||||
(set-bg-opacity 0)
|
||||
(re-frame/dispatch [:dismiss-keyboard])) edit)
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:height shared-height}
|
||||
{:z-index 2})}
|
||||
|
@ -182,12 +188,13 @@
|
|||
(styles/input-bottom-sheet window-height))}
|
||||
;handle
|
||||
[rn/view {:style (styles/bottom-sheet-handle)}]
|
||||
[edit/edit-message-auto-focus-wrapper (:text-input-ref refs) edit]
|
||||
[reply/reply-message-auto-focus-wrapper (:text-input-ref refs) reply]
|
||||
[edit/edit-message-auto-focus-wrapper text-input-ref edit clean-and-minimize-composer-fn]
|
||||
[reply/reply-message-auto-focus-wrapper text-input-ref reply]
|
||||
[rn/view {:style {:height (- max-y 80 added-value)}}
|
||||
[input/text-input {:chat-id chat-id
|
||||
:on-content-size-change input-content-change
|
||||
:sending-image false
|
||||
:initial-value initial-value
|
||||
:refs refs
|
||||
:set-active-panel #()}]]]]
|
||||
;CONTROLS
|
||||
|
@ -202,15 +209,22 @@
|
|||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied)) 50))}))
|
||||
:icon true :type :outline :size 32} :i/image]
|
||||
:icon true
|
||||
:type :outline
|
||||
:size 32} :i/image]
|
||||
[rn/view {:width 12}]
|
||||
[quo2.button/button {:icon true :type :outline :size 32} :i/reaction]
|
||||
[quo2.button/button {:icon true
|
||||
:type :outline
|
||||
:size 32} :i/reaction]
|
||||
[rn/view {:flex 1}]
|
||||
;;SEND button
|
||||
[rn/view {:ref send-ref :style (when-not (seq (get @input/input-texts chat-id)) {:width 0 :right -100})}
|
||||
[quo2.button/button {:icon true :size 32 :accessibility-label :send-message-button
|
||||
:on-press #(do (swap! context assoc :clear true)
|
||||
(input/clear-input chat-id refs)
|
||||
[rn/view {:ref send-ref
|
||||
:style (when-not (seq (get @input/input-texts chat-id)) {:width 0
|
||||
:right -100})}
|
||||
[quo2.button/button {:icon true
|
||||
:size 32
|
||||
:accessibility-label :send-message-button
|
||||
:on-press #(do (clean-and-minimize-composer-fn false)
|
||||
(re-frame/dispatch [:chat.ui/send-current-message]))}
|
||||
:i/arrow-up]]])
|
||||
;black background
|
||||
|
@ -218,4 +232,4 @@
|
|||
{:opacity bg-opacity
|
||||
:transform [{:translateY bg-bottom}]}
|
||||
(styles/bottom-sheet-background window-height))}]
|
||||
[mentions/autocomplete-mentions suggestions]]))])))])
|
||||
[mentions/autocomplete-mentions suggestions text-input-ref]]))])))])
|
||||
|
|
Loading…
Reference in New Issue