From d24eb96c9de2dc6a105846b2a5397501900578e5 Mon Sep 17 00:00:00 2001 From: Sean Hagstrom Date: Thu, 4 Apr 2024 15:54:22 +0100 Subject: [PATCH] Use scrollable multiline text-input in contact request form (#19383) * tweak: augment bottom-sheet component to be aware of keyboard height * tweak: augment quo input component to allow for styling of the input, the input container, and container * tweak: augment contact request input to grow until max screen size is reached for the bottom-sheet * tweak: handle blurring the contact request input when keyboard is dismissed on android * tidy: refactor with the use-keyboard hook * tweak: use on-layout for measuring sheet max-height * tweak: remove use of input-style and flex-direction column * tidy: remove unused requires * tidy: use container-style prop * tidy: fix formatting * fix: default layout-height to window-height --- src/quo/components/inputs/input/view.cljs | 7 ++-- src/status_im/common/bottom_sheet/view.cljs | 14 ++++++-- .../contact/contact_request/style.cljs | 1 + .../profile/contact/contact_request/view.cljs | 34 +++++++++++++------ src/status_im/navigation/view.cljs | 16 +++++---- 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/quo/components/inputs/input/view.cljs b/src/quo/components/inputs/input/view.cljs index 3d1c7e450f..90aeacd590 100644 --- a/src/quo/components/inputs/input/view.cljs +++ b/src/quo/components/inputs/input/view.cljs @@ -60,11 +60,11 @@ "Custom properties that must be removed from properties map passed to InputText." [:type :blur? :error? :right-icon :left-icon :disabled? :small? :button :label :char-limit :on-char-limit-reach :icon-name :multiline? :on-focus :on-blur - :container-style :ref]) + :container-style :input-container-style :ref]) (defn- base-input [{:keys [blur? error? right-icon left-icon disabled? small? button - label char-limit multiline? clearable? on-focus on-blur container-style + label char-limit multiline? clearable? on-focus on-blur container-style input-container-style on-change-text on-char-limit-reach weight default-value on-clear] :as props}] (let [theme (quo.theme/use-theme-value) @@ -119,7 +119,8 @@ :current-chars char-count :char-limit char-limit :theme theme}]) - [rn/view {:style (style/input-container colors-by-status small? disabled?)} + [rn/view + {:style (merge (style/input-container colors-by-status small? disabled?) input-container-style)} (when-let [{:keys [icon-name]} left-icon] [left-accessory {:variant-colors variant-colors diff --git a/src/status_im/common/bottom_sheet/view.cljs b/src/status_im/common/bottom_sheet/view.cljs index 62c163a6ce..e26b9f06ad 100644 --- a/src/status_im/common/bottom_sheet/view.cljs +++ b/src/status_im/common/bottom_sheet/view.cljs @@ -10,6 +10,7 @@ [react-native.hooks :as hooks] [react-native.reanimated :as reanimated] [status-im.common.bottom-sheet.style :as style] + [utils.number] [utils.re-frame :as rf])) (def duration 450) @@ -66,19 +67,23 @@ gradient-cover? customization-color hide-handle? blur-radius] :or {border-radius 12}}] (let [theme (quo.theme/use-theme-value) + {window-height :height} (rn/get-window) [sheet-height set-sheet-height] (rn/use-state 0) + [layout-height set-layout-height] (rn/use-state window-height) handle-sheet-height (rn/use-callback (fn [e] (when (= sheet-height 0) (set-sheet-height (get-layout-height e)))) [sheet-height]) + handle-layout-height (rn/use-callback (fn [e] + (-> (get-layout-height e) + (set-layout-height)))) [item-height set-item-height] (rn/use-state 0) handle-item-height (rn/use-callback (fn [e] (when (= item-height 0) (set-item-height (get-layout-height e)))) [item-height]) - {window-height :height} (rn/get-window) bg-opacity (reanimated/use-shared-value 0) translate-y (reanimated/use-shared-value window-height) sheet-gesture (rn/use-memo #(get-sheet-gesture translate-y @@ -96,7 +101,8 @@ bottom (if selected-item-smaller-than-sheet? (+ sheet-height bottom-margin) (:bottom insets)) - sheet-max-height (- window-height (:top insets)) + sheet-max-height (- layout-height + (:top insets)) content-padding-bottom (or padding-bottom-override (+ (:bottom insets) bottom-margin))] (rn/use-effect @@ -109,7 +115,9 @@ (on-close)) (rf/dispatch [:hide-bottom-sheet]) true)) - [rn/view {:style {:flex 1}} + [rn/view + {:style {:flex 1} + :on-layout handle-layout-height} ;; backdrop [rn/pressable {:on-press #(rf/dispatch [:hide-bottom-sheet]) diff --git a/src/status_im/contexts/profile/contact/contact_request/style.cljs b/src/status_im/contexts/profile/contact/contact_request/style.cljs index 461e6bc2d6..b28684443b 100644 --- a/src/status_im/contexts/profile/contact/contact_request/style.cljs +++ b/src/status_im/contexts/profile/contact/contact_request/style.cljs @@ -7,4 +7,5 @@ (def message-input-wrapper {:padding-vertical 8 + :flex-shrink 1 :padding-horizontal 20}) diff --git a/src/status_im/contexts/profile/contact/contact_request/view.cljs b/src/status_im/contexts/profile/contact/contact_request/view.cljs index bf7ef6914d..deed16ef3b 100644 --- a/src/status_im/contexts/profile/contact/contact_request/view.cljs +++ b/src/status_im/contexts/profile/contact/contact_request/view.cljs @@ -2,6 +2,7 @@ (:require [clojure.string :as string] [quo.core :as quo] [react-native.core :as rn] + [react-native.platform :as platform] [status-im.constants :as constants] [status-im.contexts.profile.contact.contact-request.style :as style] [status-im.contexts.profile.utils :as profile.utils] @@ -15,6 +16,7 @@ customization-color customization-color full-name (profile.utils/displayed-name profile) profile-picture (profile.utils/photo profile) + input-ref (rn/use-ref-atom nil) [message set-message] (rn/use-state "") on-message-change (rn/use-callback #(set-message %)) on-message-submit (rn/use-callback (fn [] @@ -27,6 +29,14 @@ :text (i18n/label :t/contact-request-was-sent)}])) [public-key message])] + (rn/use-mount + (fn [] + (let [listener (.addListener rn/keyboard + "keyboardDidHide" + (fn [_event] + (when (and platform/android? @input-ref) + (.blur ^js @input-ref))))] + #(.remove ^js listener)))) [:<> [quo/drawer-top {:type :context-tag @@ -39,17 +49,21 @@ (i18n/label :t/contact-request-message-prompt)] [rn/view {:style style/message-input-wrapper} [quo/input - {:type :text - :multiline? true - :char-limit constants/contact-request-message-max-length - :max-length constants/contact-request-message-max-length - :placeholder (i18n/label :t/type-something) - :auto-focus true - :accessibility-label :contact-request-message - :label (i18n/label :t/message) - :on-change-text on-message-change}]] + {:type :text + :ref #(reset! input-ref %) + :multiline? true + :char-limit constants/contact-request-message-max-length + :max-length constants/contact-request-message-max-length + :placeholder (i18n/label :t/type-something) + :auto-focus true + :accessibility-label :contact-request-message + :label (i18n/label :t/message) + :on-change-text on-message-change + :container-style {:flex-shrink 1} + :input-container-style {:flex-shrink 1}}]] [quo/bottom-actions - {:actions :one-action + {:container-style {:style {:flex 1}} + :actions :one-action :button-one-props {:disabled? (string/blank? message) :accessibility-label :send-contact-request :customization-color customization-color diff --git a/src/status_im/navigation/view.cljs b/src/status_im/navigation/view.cljs index 62b94ccba8..3dc45d2515 100644 --- a/src/status_im/navigation/view.cljs +++ b/src/status_im/navigation/view.cljs @@ -92,19 +92,21 @@ (def bottom-sheet (reagent/reactify-component (fn [] - (let [{:keys [sheets hide?]} (rf/sub [:bottom-sheet]) - sheet (last sheets) - {:keys [theme]} sheet - insets (safe-area/get-insets) - user-theme (theme/get-theme)] + (let [{:keys [sheets hide?]} (rf/sub [:bottom-sheet]) + sheet (last sheets) + {:keys [theme]} sheet + insets (safe-area/get-insets) + user-theme (theme/get-theme) + keyboard-vertical-offset (- (max 20 (:bottom insets)))] ^{:key (str "sheet" @reloader/cnt)} [theme/provider {:theme (or theme user-theme)} [inactive] [rn/keyboard-avoiding-view {:style {:position :relative :flex 1} - :keyboard-vertical-offset (- (max 20 (:bottom insets)))} + :keyboard-vertical-offset keyboard-vertical-offset} (when sheet - [bottom-sheet/view {:insets insets :hide? hide?} + [bottom-sheet/view + {:insets insets :hide? hide?} sheet])]])) functional-compiler))