diff --git a/src/status_im/chat/events/input.cljs b/src/status_im/chat/events/input.cljs index 865dbfe4a1..720423e154 100644 --- a/src/status_im/chat/events/input.cljs +++ b/src/status_im/chat/events/input.cljs @@ -83,40 +83,24 @@ [{:keys [current-chat-id] :as db} metadata] (assoc-in db [:chats current-chat-id :input-metadata] metadata)) -(defn set-chat-seq-arg-input-text - "Sets input text for current sequential argument in active chat" - [{:keys [current-chat-id] :as db} text] - (assoc-in db [:chats current-chat-id :seq-argument-input-text] text)) - -(defn clear-seq-arguments - "Clears sequential arguments for current-chat" - [{:keys [current-chat-id chats] :as db}] - (-> db - (assoc-in [:chats current-chat-id :seq-arguments] []) - (assoc-in [:chats current-chat-id :seq-argument-input-text] nil))) - (defn set-command-argument "Sets command argument in active chat" [{:keys [current-chat-id] :as db} index arg move-to-next?] (let [command (-> (get-in db [:chats current-chat-id :input-text]) - (input-model/split-command-args)) - seq-params? (-> (input-model/selected-chat-command db) - (get-in [:command :sequential-params]))] - (if seq-params? - (set-chat-seq-arg-input-text db arg) - (let [arg (string/replace arg (re-pattern constants/arg-wrapping-char) "") - command-name (first command) - command-args (into [] (rest command)) - command-args (if (< index (count command-args)) - (assoc command-args index arg) - (conj command-args arg)) - input-text (str command-name - constants/spacing-char - (input-model/join-command-args command-args) - (when (and move-to-next? - (= index (dec (count command-args)))) - constants/spacing-char))] - (set-chat-input-text db input-text))))) + (input-model/split-command-args))] + (let [arg (string/replace arg (re-pattern constants/arg-wrapping-char) "") + command-name (first command) + command-args (into [] (rest command)) + command-args (if (< index (count command-args)) + (assoc command-args index arg) + (conj command-args arg)) + input-text (str command-name + constants/spacing-char + (input-model/join-command-args command-args) + (when (and move-to-next? + (= index (dec (count command-args)))) + constants/spacing-char))] + (set-chat-input-text db input-text)))) (defn load-chat-parameter-box "Returns fx for loading chat parameter box for active chat" @@ -134,12 +118,10 @@ args (-> (get-in db [:chats current-chat-id :input-text]) input-model/split-command-args rest) - seq-arg (get-in db [:chats current-chat-id :seq-argument-input-text]) to (get-in db [:contacts/contacts current-chat-id :address]) from (get-in db [:account/account :address]) params {:parameters {:args args - :bot-db bot-db - :seq-arg seq-arg} + :bot-db bot-db} :context {:data data :from from :to to}}] @@ -169,44 +151,27 @@ (cond-> {:db new-db} chat-parameter-box-fx - (merge chat-parameter-box-fx) - - (and (= selection (+ (count constants/command-char) - (count (get-in command [:command :name])) - (count constants/spacing-char))) - (get-in command [:command :sequential-params])) - (merge (chat-input-focus new-db :seq-input-ref))))) + (merge chat-parameter-box-fx)))) (defn select-chat-input-command "Selects command + (optional) arguments as input for active chat" - [{:keys [prefill prefill-bot-db sequential-params name owner-id] :as command} metadata prevent-auto-focus? {:keys [db]}] + [{:keys [prefill prefill-bot-db name owner-id] :as command} metadata prevent-auto-focus? {:keys [db]}] (let [{:keys [current-chat-id chat-ui-props]} db db' (-> db (bots-events/clear-bot-db owner-id) - clear-seq-arguments (model/set-chat-ui-props {:show-suggestions? false :result-box nil}) (set-chat-input-metadata metadata) (set-chat-input-text (str (commands-model/command-name command) constants/spacing-char - (when-not sequential-params - (input-model/join-command-args prefill))))) + (input-model/join-command-args prefill)))) fx (assoc (load-chat-parameter-box db' command) :db db')] (cond-> fx prefill-bot-db (update :db bots-events/update-bot-db {:db prefill-bot-db :bot owner-id}) - (not (and sequential-params - prevent-auto-focus?)) - (merge (chat-input-focus (:db fx) :input-ref)) - - sequential-params - (as-> fx' - (cond-> (update fx' :db - set-chat-seq-arg-input-text - (string/join constants/spacing-char prefill)) - (not prevent-auto-focus?) - (merge fx' (chat-input-focus (:db fx') :seq-input-ref))))))) + (not prevent-auto-focus?) + (merge (chat-input-focus (:db fx) :input-ref))))) ;; TODO(goranjovic) - generalize setting something as a command argument (defn set-contact-as-command-argument @@ -354,7 +319,6 @@ (defn cleanup-chat-command [db] (-> (model/set-chat-ui-props db {:sending-in-progress? false}) - (clear-seq-arguments) (set-chat-input-metadata nil) (set-chat-input-text nil))) @@ -383,10 +347,9 @@ (= :complete (input-model/command-completion chat-command))) (defn command-complete-fx - "command is complete, clear sequential arguments and proceed with command processing" + "command is complete, set `:sendint-in-progress?` flag and proceed with command processing" [db chat-command message-id current-time] (-> db - clear-seq-arguments (model/set-chat-ui-props {:sending-in-progress? true}) (proceed-command chat-command message-id current-time))) @@ -416,11 +379,7 @@ (when-not (get-in db [:chat-ui-props current-chat-id :sending-in-progress?]) (let [input-text (get-in db [:chats current-chat-id :input-text]) chat-command (-> (input-model/selected-chat-command db) - (as-> selected-command - (if (get-in selected-command [:command :sequential-params]) - (assoc selected-command :args - (get-in db [:chats current-chat-id :seq-arguments])) - (update selected-command :args (partial remove string/blank?)))))] + (update :args (partial remove string/blank?)))] (if (:command chat-command) ;; Returns true if current input contains command (if (command-complete? chat-command) @@ -428,66 +387,12 @@ (command-not-complete-fx db input-text)) (plain-text-message-fx db cofx input-text current-chat-id current-public-key)))))) -(handlers/register-handler-db - ::update-seq-arguments - [re-frame/trim-v] - (fn [{:keys [current-chat-id chats] :as db} [chat-id]] - (let [chat-id (or chat-id current-chat-id) - text (get-in chats [chat-id :seq-argument-input-text])] - (-> db - (update-in [:chats chat-id :seq-arguments] #(into [] (conj % text))) - (assoc-in [:chats chat-id :seq-argument-input-text] nil))))) - -(handlers/register-handler-fx - :send-seq-argument - (fn [{{:keys [current-chat-id chats] :as db} :db} _] - (let [text (get-in chats [current-chat-id :seq-argument-input-text]) - seq-arguments (get-in chats [current-chat-id :seq-arguments]) - command (-> (input-model/selected-chat-command db) - (assoc :args (into [] (conj seq-arguments text))))] - (commands-events/request-command-message-data db (command->message db command) - {:data-type :validator - :proceed-event-creator (fn [validation-response] - [::proceed-validation - validation-response - [[::update-seq-arguments current-chat-id] - [:send-current-message]]])})))) - -(handlers/register-handler-db - :set-chat-seq-arg-input-text - [re-frame/trim-v] - (fn [db [text]] - (set-chat-seq-arg-input-text db text))) - (handlers/register-handler-fx :update-text-selection [re-frame/trim-v] (fn [{:keys [db]} [selection]] (update-text-selection db selection))) -(handlers/register-handler-fx - :select-prev-argument - (fn [{{:keys [chat-ui-props current-chat-id] :as db} :db} _] - (let [command (input-model/selected-chat-command db)] - (if (get-in command [:command :sequential-params]) - (-> db - (set-command-argument 0 "" false) - (set-chat-seq-arg-input-text "") - (load-chat-parameter-box (:command command))) - (let [arg-pos (input-model/argument-position db)] - (when (pos? arg-pos) - (let [input-text (get-in db [:chats current-chat-id :input-text]) - new-sel (->> (input-model/split-command-args input-text) - (take (inc arg-pos)) - (input-model/join-command-args) - (count)) - ref (get-in chat-ui-props [current-chat-id :input-ref])] - (-> db - (update-text-selection new-sel) - (assoc ::set-native-props - {:ref ref - :props {:selection {:start new-sel :end new-sel}}}))))))))) - (handlers/register-handler-fx :set-contact-as-command-argument [re-frame/trim-v] diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index d584744600..c3800721e2 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -17,7 +17,6 @@ [status-im.chat.views.message.options :as message-options] [status-im.chat.views.message.datemark :as message-datemark] [status-im.chat.views.message.message :as message] - [status-im.chat.views.input.input :as input] [status-im.chat.views.toolbar-content :as toolbar-content] [status-im.ui.components.animation :as animation] [status-im.ui.components.list.views :as list] diff --git a/src/status_im/chat/specs.cljs b/src/status_im/chat/specs.cljs index f390cc08df..94043e5d50 100644 --- a/src/status_im/chat/specs.cljs +++ b/src/status_im/chat/specs.cljs @@ -8,8 +8,7 @@ (s/def :chat/chat-animations (s/nilable map?)) ; {id (string) props (map)} (s/def :chat/chat-ui-props (s/nilable map?)) ; {id (string) props (map)} (s/def :chat/chat-list-ui-props (s/nilable map?)) -(s/def :chat/layout-height (s/nilable number?)) ; height of chat's view layout -(s/def :chat/expandable-view-height-to-value (s/nilable number?)) +(s/def :chat/layout-height (s/nilable number?)) ; height of chat's view layout (s/def :chat/selected-participants (s/nilable set?)) (s/def :chat/chat-loaded-callbacks (s/nilable map?)) (s/def :chat/public-group-topic (s/nilable string?)) diff --git a/src/status_im/chat/styles/animations.cljs b/src/status_im/chat/styles/animations.cljs index 33020e680a..f62bedca5b 100644 --- a/src/status_im/chat/styles/animations.cljs +++ b/src/status_im/chat/styles/animations.cljs @@ -1,7 +1,6 @@ (ns status-im.chat.styles.animations (:require [status-im.ui.components.styles :as common])) -(def color-root-border "rgba(192, 198, 202, 0.28)") (def header-draggable-icon "rgba(73, 84, 93, 0.23)") (def overlap-container @@ -18,8 +17,6 @@ :right 0 :bottom bottom :position :absolute - :border-top-color color-root-border - :border-top-width 1 :elevation 2 :max-height max-height}) diff --git a/src/status_im/chat/styles/input/input.cljs b/src/status_im/chat/styles/input/input.cljs index 8e3b3781d3..a5c82a966c 100644 --- a/src/status_im/chat/styles/input/input.cljs +++ b/src/status_im/chat/styles/input/input.cljs @@ -5,7 +5,7 @@ (def min-input-height 36) (def padding-vertical 8) (def border-height 1) -(def max-input-height (* 4 min-input-height)) +(def max-input-height (* 5 min-input-height)) (defnstyle root [margin-bottom] {:background-color colors/white @@ -25,21 +25,23 @@ :padding-bottom padding-vertical :flex 1}) -(defn input-animated [content-height] - {:align-items :flex-start - :flex-direction :row - :flex-grow 1 - :height (min (max min-input-height content-height) max-input-height)}) +(def input-animated + {:align-items :flex-start + :flex-direction :row + :flex-grow 1 + :min-height min-input-height + :max-height max-input-height}) -(defnstyle input-view [content-height single-line-input?] +(defnstyle input-view [single-line-input?] {:flex 1 :font-size 15 :padding-top 9 :padding-bottom 5 :padding-right 12 - :height (if single-line-input? + :min-height min-input-height + :max-height (if single-line-input? min-input-height - (+ (min (max min-input-height content-height) max-input-height))) + max-input-height) :android {:padding-top 3}}) (def invisible-input-text diff --git a/src/status_im/chat/styles/input/parameter_box.cljs b/src/status_im/chat/styles/input/parameter_box.cljs index db9578c8da..191564e8c9 100644 --- a/src/status_im/chat/styles/input/parameter_box.cljs +++ b/src/status_im/chat/styles/input/parameter_box.cljs @@ -3,7 +3,7 @@ [status-im.ui.components.colors :as colors])) (def root - {:background-color common/color-white - :border-top-color colors/gray-light - :border-top-width 1}) + {:background-color common/color-white + :border-bottom-color colors/gray-light + :border-bottom-width 1}) diff --git a/src/status_im/chat/styles/input/suggestions.cljs b/src/status_im/chat/styles/input/suggestions.cljs index fb6a314713..6cab42b3f9 100644 --- a/src/status_im/chat/styles/input/suggestions.cljs +++ b/src/status_im/chat/styles/input/suggestions.cljs @@ -12,14 +12,13 @@ :border-top-color colors/gray-light :border-top-width 1}) -(defn item-suggestion-container [last?] +(def item-suggestion-container {:flex-direction :row :align-items :center :height item-height - :margin-left 14 - :padding-right 14 + :padding-horizontal 14 :border-bottom-color colors/gray-light - :border-bottom-width (if last? 0 border-height)}) + :border-bottom-width border-height}) (def item-suggestion-name {:color common/color-black diff --git a/src/status_im/chat/views/input/input.cljs b/src/status_im/chat/views/input/input.cljs index ecf8399250..b98164093c 100644 --- a/src/status_im/chat/views/input/input.cljs +++ b/src/status_im/chat/views/input/input.cljs @@ -18,23 +18,12 @@ [status-im.utils.platform :as platform] [status-im.utils.utils :as utils])) -;; TODO(pacamara) Symptomatic fix, root cause is react-native onLayout returning -;; inconsistent height values, more investigation needed -(defn android-blank-line-extra-height [input-text] - (if (and platform/android? input-text (string/ends-with? input-text "\n")) - (/ style/min-input-height 2) - 0)) - -(defview basic-text-input [{:keys [set-layout-height-fn set-container-width-fn height single-line-input?]}] +(defview basic-text-input [{:keys [set-container-width-fn height single-line-input?]}] (letsubs [{:keys [input-text]} [:get-current-chat] - input-focused? [:get-current-chat-ui-prop :input-focused?] - input-ref (atom nil) cooldown-enabled? [:chat-cooldown-enabled?]] [react/text-input (merge - {:ref #(when % - (re-frame/dispatch [:set-chat-ui-props {:input-ref %}]) - (reset! input-ref %)) + {:ref #(when % (re-frame/dispatch [:set-chat-ui-props {:input-ref %}])) :accessibility-label :chat-message-input :multiline (not single-line-input?) :default-value (or input-text "") @@ -43,34 +32,14 @@ :on-focus #(re-frame/dispatch [:set-chat-ui-props {:input-focused? true :messages-focused? false}]) :on-blur #(re-frame/dispatch [:set-chat-ui-props {:input-focused? false}]) - :on-submit-editing (fn [_] - (if single-line-input? - (re-frame/dispatch [:send-current-message]) - (when @input-ref - (.setNativeProps @input-ref (clj->js {:text input-text}))))) - :on-layout (fn [e] - (set-container-width-fn (.-width (.-layout (.-nativeEvent e))))) - :on-change (fn [e] - (let [native-event (.-nativeEvent e) - text (.-text native-event) - content-size (.. native-event -contentSize)] - (when (and (not single-line-input?) - content-size) - (set-layout-height-fn (.-height content-size))) - (when (not= text input-text) - (re-frame/dispatch [:set-chat-input-text text])))) - :on-content-size-change (when (and (not input-focused?) - (not single-line-input?)) - #(let [s (.-contentSize (.-nativeEvent %)) - w (.-width s) - h (.-height s)] - (set-container-width-fn w) - (set-layout-height-fn h))) + :on-submit-editing #(re-frame/dispatch [:send-current-message]) + :on-layout #(set-container-width-fn (.-width (.-layout (.-nativeEvent %)))) + :on-change #(re-frame/dispatch [:set-chat-input-text (.-text (.-nativeEvent %))]) :on-selection-change #(let [s (-> (.-nativeEvent %) (.-selection)) end (.-end s)] (re-frame/dispatch [:update-text-selection end])) - :style (style/input-view height single-line-input?) + :style (style/input-view single-line-input?) :placeholder-text-color colors/gray :auto-capitalize :sentences} (when cooldown-enabled? @@ -85,16 +54,6 @@ (set-layout-width-fn w))} (or input-text "")])) -(defview invisible-input-height [{:keys [set-layout-height-fn container-width]}] - (letsubs [{:keys [input-text]} [:get-current-chat]] - [react/text {:style (style/invisible-input-text-height container-width) - :on-layout #(let [h (-> (.-nativeEvent %) - (.-layout) - (.-height) - (+ (android-blank-line-extra-height input-text)))] - (set-layout-height-fn h))} - (or input-text "")])) - (defn- input-helper-view-on-update [{:keys [opacity-value placeholder]}] (fn [_] (let [to-value (if @placeholder 1 0)] @@ -119,49 +78,18 @@ :number {:keyboard-type "numeric"} nil)) -(defview seq-input [{:keys [command-width container-width]}] - (letsubs [command [:selected-chat-command] - arg-pos [:current-chat-argument-position] - {:keys [seq-arg-input-text]} [:get-current-chat]] - (when (get-in command [:command :sequential-params]) - (let [{:keys [placeholder type]} (get-in command [:command :params arg-pos])] - [react/text-input (merge {:ref #(re-frame/dispatch [:set-chat-ui-props {:seq-input-ref %}]) - :style (style/seq-input-text command-width container-width) - :default-value (or seq-arg-input-text "") - :on-change-text #(do (re-frame/dispatch [:set-chat-seq-arg-input-text %]) - (re-frame/dispatch [:set-chat-ui-props {:validation-messages nil}])) - :placeholder placeholder - :accessibility-label :chat-request-input - :blur-on-submit false - :editable true - :on-submit-editing (fn [] - (when-not (or (string/blank? seq-arg-input-text) - (get-in command [:command :hide-send-button])) - (re-frame/dispatch [:send-seq-argument])) - (utils/set-timeout - #(re-frame/dispatch [:chat-input-focus :seq-input-ref]) - 100))} - (get-options type))])))) - (defview input-view [{:keys [single-line-input?]}] (letsubs [command [:selected-chat-command]] (let [component (reagent/current-component) set-layout-width-fn #(reagent/set-state component {:width %}) - set-layout-height-fn #(reagent/set-state component {:height %}) set-container-width-fn #(reagent/set-state component {:container-width %}) - {:keys [width height container-width]} (reagent/state component)] + {:keys [width]} (reagent/state component)] [react/view {:style style/input-root} - [react/animated-view {:style (style/input-animated height)} + [react/animated-view {:style style/input-animated} [invisible-input {:set-layout-width-fn set-layout-width-fn}] - [invisible-input-height {:set-layout-height-fn set-layout-height-fn - :container-width container-width}] - [basic-text-input {:set-layout-height-fn set-layout-height-fn - :set-container-width-fn set-container-width-fn - :height height + [basic-text-input {:set-container-width-fn set-container-width-fn :single-line-input? single-line-input?}] - [input-helper {:width width}] - [seq-input {:command-width width - :container-width container-width}]]]))) + [input-helper {:width width}]]]))) (defview commands-button [] (letsubs [commands-responses [:get-available-commands-responses]] diff --git a/src/status_im/chat/views/input/send_button.cljs b/src/status_im/chat/views/input/send_button.cljs index 3e2c884e83..a2b8cf77d6 100644 --- a/src/status_im/chat/views/input/send_button.cljs +++ b/src/status_im/chat/views/input/send_button.cljs @@ -27,24 +27,14 @@ on-update (send-button-view-on-update {:spin-value spin-value :command-completion command-completion})] {:component-did-update on-update} - (let [{:keys [hide-send-button sequential-params]} (:command selected-command)] - (when - (and (sendable? input-text) - (or (not selected-command) - (some #{:complete :less-than-needed} [command-completion])) - (not hide-send-button)) - [react/touchable-highlight {:on-press #(if sequential-params - (do - (when-not (string/blank? seq-arg-input-text) - (re-frame/dispatch [:send-seq-argument])) - (utils/set-timeout - (fn [] (re-frame/dispatch [:chat-input-focus :seq-input-ref])) - 100)) - (re-frame/dispatch [:send-current-message]))} - (let [spin (.interpolate spin-value (clj->js {:inputRange [0 1] - :outputRange ["0deg" "90deg"]}))] - [react/animated-view - {:style (style/send-message-container spin) - :accessibility-label :send-message-button} - [vi/icon :icons/input-send {:container-style style/send-message-icon - :color :white}]])])))) + (when (and (sendable? input-text) + (or (not selected-command) + (some #{:complete :less-than-needed} [command-completion]))) + [react/touchable-highlight {:on-press #(re-frame/dispatch [:send-current-message])} + (let [spin (.interpolate spin-value (clj->js {:inputRange [0 1] + :outputRange ["0deg" "90deg"]}))] + [react/animated-view + {:style (style/send-message-container spin) + :accessibility-label :send-message-button} + [vi/icon :icons/input-send {:container-style style/send-message-icon + :color :white}]])]))) diff --git a/src/status_im/chat/views/input/suggestions.cljs b/src/status_im/chat/views/input/suggestions.cljs index f5532042ad..1c10cda2dc 100644 --- a/src/status_im/chat/views/input/suggestions.cljs +++ b/src/status_im/chat/views/input/suggestions.cljs @@ -11,7 +11,7 @@ (defn suggestion-item [{:keys [on-press name description last? accessibility-label]}] [react/touchable-highlight (cond-> {:on-press on-press} accessibility-label (assoc :accessibility-label accessibility-label)) - [react/view (style/item-suggestion-container last?) + [react/view style/item-suggestion-container [react/text {:style style/item-suggestion-name} name] [react/text {:style style/item-suggestion-description diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 5fed9f4f52..485cd915db 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -241,7 +241,6 @@ :chat/chat-ui-props :chat/chat-list-ui-props :chat/layout-height - :chat/expandable-view-height-to-value :chat/message-data :chat/message-status :chat/selected-participants