mirror of
https://github.com/status-im/status-mobile.git
synced 2025-03-01 00:30:49 +00:00
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
This commit is contained in:
parent
3dfd9df935
commit
d24eb96c9d
@ -60,11 +60,11 @@
|
|||||||
"Custom properties that must be removed from properties map passed to InputText."
|
"Custom properties that must be removed from properties map passed to InputText."
|
||||||
[:type :blur? :error? :right-icon :left-icon :disabled? :small? :button
|
[:type :blur? :error? :right-icon :left-icon :disabled? :small? :button
|
||||||
:label :char-limit :on-char-limit-reach :icon-name :multiline? :on-focus :on-blur
|
: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
|
(defn- base-input
|
||||||
[{:keys [blur? error? right-icon left-icon disabled? small? button
|
[{: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]
|
on-change-text on-char-limit-reach weight default-value on-clear]
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [theme (quo.theme/use-theme-value)
|
(let [theme (quo.theme/use-theme-value)
|
||||||
@ -119,7 +119,8 @@
|
|||||||
:current-chars char-count
|
:current-chars char-count
|
||||||
:char-limit char-limit
|
:char-limit char-limit
|
||||||
:theme theme}])
|
: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]
|
(when-let [{:keys [icon-name]} left-icon]
|
||||||
[left-accessory
|
[left-accessory
|
||||||
{:variant-colors variant-colors
|
{:variant-colors variant-colors
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
[react-native.hooks :as hooks]
|
[react-native.hooks :as hooks]
|
||||||
[react-native.reanimated :as reanimated]
|
[react-native.reanimated :as reanimated]
|
||||||
[status-im.common.bottom-sheet.style :as style]
|
[status-im.common.bottom-sheet.style :as style]
|
||||||
|
[utils.number]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def duration 450)
|
(def duration 450)
|
||||||
@ -66,19 +67,23 @@
|
|||||||
gradient-cover? customization-color hide-handle? blur-radius]
|
gradient-cover? customization-color hide-handle? blur-radius]
|
||||||
:or {border-radius 12}}]
|
:or {border-radius 12}}]
|
||||||
(let [theme (quo.theme/use-theme-value)
|
(let [theme (quo.theme/use-theme-value)
|
||||||
|
{window-height :height} (rn/get-window)
|
||||||
[sheet-height set-sheet-height] (rn/use-state 0)
|
[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]
|
handle-sheet-height (rn/use-callback (fn [e]
|
||||||
(when (= sheet-height 0)
|
(when (= sheet-height 0)
|
||||||
(set-sheet-height
|
(set-sheet-height
|
||||||
(get-layout-height e))))
|
(get-layout-height e))))
|
||||||
[sheet-height])
|
[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)
|
[item-height set-item-height] (rn/use-state 0)
|
||||||
handle-item-height (rn/use-callback (fn [e]
|
handle-item-height (rn/use-callback (fn [e]
|
||||||
(when (= item-height 0)
|
(when (= item-height 0)
|
||||||
(set-item-height
|
(set-item-height
|
||||||
(get-layout-height e))))
|
(get-layout-height e))))
|
||||||
[item-height])
|
[item-height])
|
||||||
{window-height :height} (rn/get-window)
|
|
||||||
bg-opacity (reanimated/use-shared-value 0)
|
bg-opacity (reanimated/use-shared-value 0)
|
||||||
translate-y (reanimated/use-shared-value window-height)
|
translate-y (reanimated/use-shared-value window-height)
|
||||||
sheet-gesture (rn/use-memo #(get-sheet-gesture translate-y
|
sheet-gesture (rn/use-memo #(get-sheet-gesture translate-y
|
||||||
@ -96,7 +101,8 @@
|
|||||||
bottom (if selected-item-smaller-than-sheet?
|
bottom (if selected-item-smaller-than-sheet?
|
||||||
(+ sheet-height bottom-margin)
|
(+ sheet-height bottom-margin)
|
||||||
(:bottom insets))
|
(:bottom insets))
|
||||||
sheet-max-height (- window-height (:top insets))
|
sheet-max-height (- layout-height
|
||||||
|
(:top insets))
|
||||||
content-padding-bottom (or padding-bottom-override
|
content-padding-bottom (or padding-bottom-override
|
||||||
(+ (:bottom insets) bottom-margin))]
|
(+ (:bottom insets) bottom-margin))]
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
@ -109,7 +115,9 @@
|
|||||||
(on-close))
|
(on-close))
|
||||||
(rf/dispatch [:hide-bottom-sheet])
|
(rf/dispatch [:hide-bottom-sheet])
|
||||||
true))
|
true))
|
||||||
[rn/view {:style {:flex 1}}
|
[rn/view
|
||||||
|
{:style {:flex 1}
|
||||||
|
:on-layout handle-layout-height}
|
||||||
;; backdrop
|
;; backdrop
|
||||||
[rn/pressable
|
[rn/pressable
|
||||||
{:on-press #(rf/dispatch [:hide-bottom-sheet])
|
{:on-press #(rf/dispatch [:hide-bottom-sheet])
|
||||||
|
@ -7,4 +7,5 @@
|
|||||||
|
|
||||||
(def message-input-wrapper
|
(def message-input-wrapper
|
||||||
{:padding-vertical 8
|
{:padding-vertical 8
|
||||||
|
:flex-shrink 1
|
||||||
:padding-horizontal 20})
|
:padding-horizontal 20})
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[react-native.platform :as platform]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.profile.contact.contact-request.style :as style]
|
[status-im.contexts.profile.contact.contact-request.style :as style]
|
||||||
[status-im.contexts.profile.utils :as profile.utils]
|
[status-im.contexts.profile.utils :as profile.utils]
|
||||||
@ -15,6 +16,7 @@
|
|||||||
customization-color customization-color
|
customization-color customization-color
|
||||||
full-name (profile.utils/displayed-name profile)
|
full-name (profile.utils/displayed-name profile)
|
||||||
profile-picture (profile.utils/photo profile)
|
profile-picture (profile.utils/photo profile)
|
||||||
|
input-ref (rn/use-ref-atom nil)
|
||||||
[message set-message] (rn/use-state "")
|
[message set-message] (rn/use-state "")
|
||||||
on-message-change (rn/use-callback #(set-message %))
|
on-message-change (rn/use-callback #(set-message %))
|
||||||
on-message-submit (rn/use-callback (fn []
|
on-message-submit (rn/use-callback (fn []
|
||||||
@ -27,6 +29,14 @@
|
|||||||
:text (i18n/label
|
:text (i18n/label
|
||||||
:t/contact-request-was-sent)}]))
|
:t/contact-request-was-sent)}]))
|
||||||
[public-key message])]
|
[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
|
[quo/drawer-top
|
||||||
{:type :context-tag
|
{:type :context-tag
|
||||||
@ -39,17 +49,21 @@
|
|||||||
(i18n/label :t/contact-request-message-prompt)]
|
(i18n/label :t/contact-request-message-prompt)]
|
||||||
[rn/view {:style style/message-input-wrapper}
|
[rn/view {:style style/message-input-wrapper}
|
||||||
[quo/input
|
[quo/input
|
||||||
{:type :text
|
{:type :text
|
||||||
:multiline? true
|
:ref #(reset! input-ref %)
|
||||||
:char-limit constants/contact-request-message-max-length
|
:multiline? true
|
||||||
:max-length constants/contact-request-message-max-length
|
:char-limit constants/contact-request-message-max-length
|
||||||
:placeholder (i18n/label :t/type-something)
|
:max-length constants/contact-request-message-max-length
|
||||||
:auto-focus true
|
:placeholder (i18n/label :t/type-something)
|
||||||
:accessibility-label :contact-request-message
|
:auto-focus true
|
||||||
:label (i18n/label :t/message)
|
:accessibility-label :contact-request-message
|
||||||
:on-change-text on-message-change}]]
|
: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
|
[quo/bottom-actions
|
||||||
{:actions :one-action
|
{:container-style {:style {:flex 1}}
|
||||||
|
:actions :one-action
|
||||||
:button-one-props {:disabled? (string/blank? message)
|
:button-one-props {:disabled? (string/blank? message)
|
||||||
:accessibility-label :send-contact-request
|
:accessibility-label :send-contact-request
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
|
@ -92,19 +92,21 @@
|
|||||||
(def bottom-sheet
|
(def bottom-sheet
|
||||||
(reagent/reactify-component
|
(reagent/reactify-component
|
||||||
(fn []
|
(fn []
|
||||||
(let [{:keys [sheets hide?]} (rf/sub [:bottom-sheet])
|
(let [{:keys [sheets hide?]} (rf/sub [:bottom-sheet])
|
||||||
sheet (last sheets)
|
sheet (last sheets)
|
||||||
{:keys [theme]} sheet
|
{:keys [theme]} sheet
|
||||||
insets (safe-area/get-insets)
|
insets (safe-area/get-insets)
|
||||||
user-theme (theme/get-theme)]
|
user-theme (theme/get-theme)
|
||||||
|
keyboard-vertical-offset (- (max 20 (:bottom insets)))]
|
||||||
^{:key (str "sheet" @reloader/cnt)}
|
^{:key (str "sheet" @reloader/cnt)}
|
||||||
[theme/provider {:theme (or theme user-theme)}
|
[theme/provider {:theme (or theme user-theme)}
|
||||||
[inactive]
|
[inactive]
|
||||||
[rn/keyboard-avoiding-view
|
[rn/keyboard-avoiding-view
|
||||||
{:style {:position :relative :flex 1}
|
{:style {:position :relative :flex 1}
|
||||||
:keyboard-vertical-offset (- (max 20 (:bottom insets)))}
|
:keyboard-vertical-offset keyboard-vertical-offset}
|
||||||
(when sheet
|
(when sheet
|
||||||
[bottom-sheet/view {:insets insets :hide? hide?}
|
[bottom-sheet/view
|
||||||
|
{:insets insets :hide? hide?}
|
||||||
sheet])]]))
|
sheet])]]))
|
||||||
functional-compiler))
|
functional-compiler))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user