fix: create password for small screen (#20645)
* fix: create password for small screen * feat: use floating button page Signed-off-by: yqrashawn <namy.19@gmail.com> * fix: use keyboard will show for ios Signed-off-by: yqrashawn <namy.19@gmail.com> * fix: safe area bottom on devices without physical home button Signed-off-by: yqrashawn <namy.19@gmail.com> * feat(create-password): tips and checkbox stick with confirm button * fix: floating button blur after rebase * fix(floating-button): absolute content avoid keyboard view --------- Signed-off-by: yqrashawn <namy.19@gmail.com>
This commit is contained in:
parent
525609f0af
commit
55c620e59d
|
@ -4,11 +4,37 @@
|
||||||
[oops.core :as oops]
|
[oops.core :as oops]
|
||||||
[react-native.core :as rn]))
|
[react-native.core :as rn]))
|
||||||
|
|
||||||
|
(defn- add-keyboard-listener
|
||||||
|
[listener callback]
|
||||||
|
(oops/ocall rn/keyboard "addListener" listener callback))
|
||||||
|
|
||||||
(defn use-keyboard
|
(defn use-keyboard
|
||||||
[]
|
[]
|
||||||
(let [kb (.useKeyboard hooks)]
|
(let [[keyboard-height set-keyboard-height] (rn/use-state 0)
|
||||||
{:keyboard-shown (.-keyboardShown ^js kb)
|
[did-show? set-did-show] (rn/use-state false)
|
||||||
:keyboard-height (.-keyboardHeight ^js kb)}))
|
[will-show? set-will-show] (rn/use-state false)]
|
||||||
|
(rn/use-mount
|
||||||
|
(fn []
|
||||||
|
(let [will-show-listener (add-keyboard-listener "keyboardWillShow" #(set-will-show true))
|
||||||
|
did-show-listener (add-keyboard-listener "keyboardDidShow"
|
||||||
|
(fn [e]
|
||||||
|
(set-did-show true)
|
||||||
|
(set-keyboard-height
|
||||||
|
(oops/oget e "endCoordinates.height"))))
|
||||||
|
will-hide-listener (add-keyboard-listener "keyboardWillHide" #(set-will-show false))
|
||||||
|
did-hide-listener (add-keyboard-listener "keyboardDidHide"
|
||||||
|
(fn [e]
|
||||||
|
(set-did-show false)
|
||||||
|
(when e
|
||||||
|
(oops/oget e "endCoordinates.height"))))]
|
||||||
|
(fn []
|
||||||
|
(oops/ocall will-show-listener "remove")
|
||||||
|
(oops/ocall did-show-listener "remove")
|
||||||
|
(oops/ocall will-hide-listener "remove")
|
||||||
|
(oops/ocall did-hide-listener "remove")))))
|
||||||
|
{:keyboard-shown did-show?
|
||||||
|
:keyboard-will-show? will-show?
|
||||||
|
:keyboard-height keyboard-height}))
|
||||||
|
|
||||||
(defn use-back-handler
|
(defn use-back-handler
|
||||||
[handler]
|
[handler]
|
||||||
|
|
|
@ -3,21 +3,23 @@
|
||||||
[react-native.safe-area :as safe-area]))
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
(defn content-container
|
(defn content-container
|
||||||
[blur? keyboard-shown?]
|
[blur? keyboard-shown? {:keys [padding-vertical padding-horizontal]}]
|
||||||
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
|
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
|
||||||
(cond-> {:margin-top :auto
|
(cond-> {:margin-top :auto
|
||||||
:overflow :hidden
|
:overflow :hidden
|
||||||
:margin-bottom margin-bottom
|
:margin-bottom margin-bottom
|
||||||
:padding-vertical 12
|
:padding-vertical (or padding-vertical 12)
|
||||||
:padding-horizontal 20}
|
:padding-horizontal (or padding-horizontal 20)}
|
||||||
blur? (dissoc :padding-vertical :padding-horizontal))))
|
blur? (dissoc :padding-vertical :padding-horizontal))))
|
||||||
|
|
||||||
(defn blur-inner-container
|
(defn blur-inner-container
|
||||||
[theme shell-overlay?]
|
[{:keys [theme shell-overlay? padding-vertical padding-horizontal background-color]}]
|
||||||
{:background-color (colors/theme-colors colors/white-70-blur
|
{:background-color (or background-color
|
||||||
(if shell-overlay?
|
(colors/theme-colors
|
||||||
colors/neutral-80-opa-80-blur
|
colors/white-70-blur
|
||||||
colors/neutral-95-opa-70-blur)
|
(if shell-overlay?
|
||||||
theme)
|
colors/neutral-80-opa-80-blur
|
||||||
:padding-vertical 12
|
colors/neutral-95-opa-70-blur)
|
||||||
:padding-horizontal 20})
|
theme))
|
||||||
|
:padding-vertical (or padding-vertical 12)
|
||||||
|
:padding-horizontal (or padding-horizontal 20)})
|
||||||
|
|
|
@ -6,20 +6,25 @@
|
||||||
[status-im.common.floating-button-page.floating-container.style :as style]))
|
[status-im.common.floating-button-page.floating-container.style :as style]))
|
||||||
|
|
||||||
(defn- blur-container
|
(defn- blur-container
|
||||||
[child shell-overlay?]
|
[shell-overlay? blur-options child]
|
||||||
(let [theme (quo.theme/use-theme)]
|
(let [theme (quo.theme/use-theme)]
|
||||||
[quo/blur
|
[quo/blur
|
||||||
{:blur-amount 20
|
(or blur-options
|
||||||
:blur-type :transparent
|
{:blur-amount 20
|
||||||
:overlay-color :transparent}
|
:blur-type :transparent
|
||||||
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
|
:overlay-color :transparent})
|
||||||
|
[rn/view
|
||||||
|
{:style (style/blur-inner-container (assoc
|
||||||
|
blur-options
|
||||||
|
:theme theme
|
||||||
|
:shell-overlay? shell-overlay?))}
|
||||||
child]]))
|
child]]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
|
[{:keys [on-layout keyboard-shown? blur? shell-overlay? blur-options]} child]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (style/content-container blur? keyboard-shown?)
|
{:style (style/content-container blur? keyboard-shown? blur-options)
|
||||||
:on-layout on-layout}
|
:on-layout on-layout}
|
||||||
(if blur?
|
(if blur?
|
||||||
[blur-container child shell-overlay?]
|
[blur-container shell-overlay? blur-options child]
|
||||||
child)])
|
child)])
|
||||||
|
|
|
@ -13,3 +13,13 @@
|
||||||
:bottom 0
|
:bottom 0
|
||||||
:left 0
|
:left 0
|
||||||
:right 0})
|
:right 0})
|
||||||
|
|
||||||
|
(defn content-keyboard-avoiding-view
|
||||||
|
[{:keys [top bottom]}]
|
||||||
|
{:position :absolute
|
||||||
|
:top top
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom bottom})
|
||||||
|
|
||||||
|
(def scroll-view-container {:flex 1})
|
||||||
|
|
|
@ -30,13 +30,15 @@
|
||||||
(reset! ratom height))))
|
(reset! ratom height))))
|
||||||
|
|
||||||
(defn- init-keyboard-listeners
|
(defn- init-keyboard-listeners
|
||||||
[{:keys [on-did-show scroll-view-ref]}]
|
[{:keys [on-did-show on-will-show scroll-view-ref]}]
|
||||||
(let [keyboard-will-show? (reagent/atom false)
|
(let [keyboard-will-show? (reagent/atom false)
|
||||||
keyboard-did-show? (reagent/atom false)
|
keyboard-did-show? (reagent/atom false)
|
||||||
add-listener (fn [listener callback]
|
add-listener (fn [listener callback]
|
||||||
(oops/ocall rn/keyboard "addListener" listener callback))
|
(oops/ocall rn/keyboard "addListener" listener callback))
|
||||||
will-show-listener (add-listener "keyboardWillShow"
|
will-show-listener (add-listener "keyboardWillShow"
|
||||||
#(reset! keyboard-will-show? true))
|
(fn [e]
|
||||||
|
(reset! keyboard-will-show? true)
|
||||||
|
(when on-will-show (on-will-show e))))
|
||||||
did-show-listener (add-listener "keyboardDidShow"
|
did-show-listener (add-listener "keyboardDidShow"
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(reset! keyboard-did-show? true)
|
(reset! keyboard-did-show? true)
|
||||||
|
@ -58,7 +60,8 @@
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [header footer customization-color footer-container-padding header-container-style
|
[{:keys [header footer customization-color footer-container-padding header-container-style
|
||||||
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
|
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?
|
||||||
|
blur-options content-avoid-keyboard?]
|
||||||
:or {footer-container-padding (safe-area/get-top)}}
|
:or {footer-container-padding (safe-area/get-top)}}
|
||||||
& children]
|
& children]
|
||||||
(reagent/with-let [scroll-view-ref (atom nil)
|
(reagent/with-let [scroll-view-ref (atom nil)
|
||||||
|
@ -69,29 +72,34 @@
|
||||||
content-container-height (reagent/atom 0)
|
content-container-height (reagent/atom 0)
|
||||||
content-scroll-y (reagent/atom 0)
|
content-scroll-y (reagent/atom 0)
|
||||||
keyboard-height (reagent/atom 0)
|
keyboard-height (reagent/atom 0)
|
||||||
|
reset-keyboard-height #(reset! keyboard-height (oops/oget
|
||||||
|
%
|
||||||
|
"endCoordinates.height"))
|
||||||
{:keys [keyboard-will-show?
|
{:keys [keyboard-will-show?
|
||||||
keyboard-did-show?
|
keyboard-did-show?
|
||||||
remove-listeners]} (init-keyboard-listeners
|
remove-listeners]} (init-keyboard-listeners
|
||||||
{:scroll-view-ref scroll-view-ref
|
(cond-> {:scroll-view-ref scroll-view-ref}
|
||||||
:on-did-show
|
platform/ios?
|
||||||
(fn [e]
|
(assoc :on-will-show reset-keyboard-height)
|
||||||
(reset! keyboard-height
|
(not platform/ios?)
|
||||||
(oops/oget e "endCoordinates.height")))})
|
(assoc :on-did-show reset-keyboard-height)))
|
||||||
set-header-height (set-height-on-layout header-height)
|
set-header-height (set-height-on-layout header-height)
|
||||||
set-content-container-height (set-height-on-layout content-container-height)
|
set-content-container-height (set-height-on-layout content-container-height)
|
||||||
set-footer-container-height (set-height-on-layout footer-container-height)
|
set-footer-container-height (set-height-on-layout footer-container-height)
|
||||||
set-content-y-scroll (fn [event]
|
set-content-y-scroll (fn [event]
|
||||||
(reset! content-scroll-y
|
(reset! content-scroll-y
|
||||||
(oops/oget event "nativeEvent.contentOffset.y")))]
|
(oops/oget event "nativeEvent.contentOffset.y")))
|
||||||
|
bottom-safe-area (safe-area/get-bottom)]
|
||||||
(let [keyboard-shown? (if platform/ios? @keyboard-will-show? @keyboard-did-show?)
|
(let [keyboard-shown? (if platform/ios? @keyboard-will-show? @keyboard-did-show?)
|
||||||
footer-container-padding (+ footer-container-padding (rf/sub [:alert-banners/top-margin]))
|
footer-container-padding (+ footer-container-padding (rf/sub [:alert-banners/top-margin]))
|
||||||
show-background? (show-background {:window-height window-height
|
show-background? (show-background
|
||||||
:footer-container-height @footer-container-height
|
{:window-height window-height
|
||||||
:keyboard-height @keyboard-height
|
:footer-container-height @footer-container-height
|
||||||
:content-scroll-y @content-scroll-y
|
:keyboard-height @keyboard-height
|
||||||
:content-container-height @content-container-height
|
:content-scroll-y @content-scroll-y
|
||||||
:header-height @header-height
|
:content-container-height @content-container-height
|
||||||
:keyboard-shown? keyboard-shown?})]
|
:header-height @header-height
|
||||||
|
:keyboard-shown? keyboard-shown?})]
|
||||||
[:<>
|
[:<>
|
||||||
(when gradient-cover?
|
(when gradient-cover?
|
||||||
[quo/gradient-cover {:customization-color customization-color}])
|
[quo/gradient-cover {:customization-color customization-color}])
|
||||||
|
@ -100,20 +108,28 @@
|
||||||
{:on-layout set-header-height
|
{:on-layout set-header-height
|
||||||
:style header-container-style}
|
:style header-container-style}
|
||||||
header]
|
header]
|
||||||
[gesture/scroll-view
|
[(if content-avoid-keyboard? rn/keyboard-avoiding-view rn/view)
|
||||||
{:ref set-scroll-ref
|
{:style
|
||||||
:on-scroll set-content-y-scroll
|
(if content-avoid-keyboard?
|
||||||
:scroll-event-throttle 64
|
(style/content-keyboard-avoiding-view
|
||||||
:content-container-style {:flex-grow 1
|
{:top @header-height
|
||||||
:padding-bottom (when @keyboard-did-show?
|
:bottom (if keyboard-shown?
|
||||||
@footer-container-height)}
|
@footer-container-height
|
||||||
:always-bounce-vertical @keyboard-did-show?
|
(+ bottom-safe-area @footer-container-height))})
|
||||||
:shows-vertical-scroll-indicator false
|
style/scroll-view-container)}
|
||||||
:keyboard-should-persist-taps keyboard-should-persist-taps}
|
[gesture/scroll-view
|
||||||
(into [rn/view
|
{:ref set-scroll-ref
|
||||||
{:style content-container-style
|
:on-scroll set-content-y-scroll
|
||||||
:on-layout set-content-container-height}]
|
:scroll-event-throttle 64
|
||||||
children)]
|
:content-container-style {:flex-grow 1}
|
||||||
|
:always-bounce-vertical @keyboard-did-show?
|
||||||
|
:automatically-adjust-keyboard-insets true
|
||||||
|
:shows-vertical-scroll-indicator false
|
||||||
|
:keyboard-should-persist-taps keyboard-should-persist-taps}
|
||||||
|
(into [rn/view
|
||||||
|
{:style content-container-style
|
||||||
|
:on-layout set-content-container-height}]
|
||||||
|
children)]]
|
||||||
[rn/keyboard-avoiding-view
|
[rn/keyboard-avoiding-view
|
||||||
{:style style/keyboard-avoiding-view
|
{:style style/keyboard-avoiding-view
|
||||||
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
|
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
|
||||||
|
@ -121,8 +137,9 @@
|
||||||
[floating-container/view
|
[floating-container/view
|
||||||
{:on-layout set-footer-container-height
|
{:on-layout set-footer-container-height
|
||||||
:keyboard-shown? keyboard-shown?
|
:keyboard-shown? keyboard-shown?
|
||||||
:blur? show-background?
|
:blur-options blur-options
|
||||||
:shell-overlay? shell-overlay?}
|
:shell-overlay? shell-overlay?
|
||||||
|
:blur? show-background?}
|
||||||
footer]]]])
|
footer]]]])
|
||||||
(finally
|
(finally
|
||||||
(remove-listeners))))
|
(remove-listeners))))
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
(:require
|
(:require
|
||||||
[quo.foundations.colors :as colors]))
|
[quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def flex-fill {:flex 1})
|
|
||||||
|
|
||||||
(def heading {:margin-bottom 20})
|
(def heading {:margin-bottom 20})
|
||||||
(def heading-subtitle {:color colors/white})
|
(def heading-subtitle {:color colors/white})
|
||||||
(def heading-title (assoc heading-subtitle :margin-bottom 8))
|
(def heading-title (assoc heading-subtitle :margin-bottom 8))
|
||||||
|
@ -14,23 +12,15 @@
|
||||||
(def space-between-inputs {:height 16})
|
(def space-between-inputs {:height 16})
|
||||||
|
|
||||||
(def password-tips
|
(def password-tips
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:justify-content :space-between
|
:justify-content :space-between
|
||||||
:margin-horizontal 20})
|
:padding-horizontal 20})
|
||||||
|
|
||||||
(def top-part
|
(def form-container
|
||||||
{:margin-horizontal 20
|
{:justify-content :space-between
|
||||||
:margin-top 12})
|
:padding-top 12
|
||||||
|
:padding-horizontal 20})
|
||||||
|
|
||||||
(def bottom-part
|
(def disclaimer-container {:padding-horizontal 20})
|
||||||
{:flex 1
|
(def footer-container {:padding-bottom 12})
|
||||||
:margin-top 12
|
(def footer-button-container {:margin-top 20 :padding-horizontal 20})
|
||||||
:justify-content :flex-end})
|
|
||||||
|
|
||||||
(def disclaimer-container
|
|
||||||
{:margin-horizontal 20
|
|
||||||
:margin-vertical 4})
|
|
||||||
|
|
||||||
(def button-container
|
|
||||||
{:margin-horizontal 20
|
|
||||||
:margin-vertical 12})
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
(ns status-im.contexts.onboarding.create-password.view
|
(ns status-im.contexts.onboarding.create-password.view
|
||||||
(:require
|
(:require
|
||||||
[oops.core :refer [ocall]]
|
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[react-native.platform :as platform]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[reagent.core :as reagent]
|
[status-im.common.floating-button-page.view :as floating-button]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.onboarding.create-password.style :as style]
|
[status-im.contexts.onboarding.create-password.style :as style]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
[quo/tips {:completed? symbols?}
|
[quo/tips {:completed? symbols?}
|
||||||
(i18n/label :t/password-creation-tips-4)]]])
|
(i18n/label :t/password-creation-tips-4)]]])
|
||||||
|
|
||||||
(defn password-validations
|
(defn validate-password
|
||||||
[password]
|
[password]
|
||||||
(let [validations (juxt utils.string/has-lower-case?
|
(let [validations (juxt utils.string/has-lower-case?
|
||||||
utils.string/has-upper-case?
|
utils.string/has-upper-case?
|
||||||
|
@ -111,68 +111,25 @@
|
||||||
(filter true?)
|
(filter true?)
|
||||||
count))
|
count))
|
||||||
|
|
||||||
(defn password-form
|
(defn- use-password-checks
|
||||||
[]
|
[password]
|
||||||
(let [password (reagent/atom "")
|
(rn/use-memo
|
||||||
repeat-password (reagent/atom "")
|
(fn []
|
||||||
accepts-disclaimer? (reagent/atom false)
|
(let [{:keys [long-enough?]
|
||||||
focused-input (reagent/atom nil)
|
:as validations} (validate-password password)]
|
||||||
show-password-validation? (reagent/atom false)
|
{:password-long-enough? long-enough?
|
||||||
same-password-length? #(and (seq @password)
|
:password-validations validations
|
||||||
(= (count @password) (count @repeat-password)))]
|
:password-strength (calc-password-strength validations)
|
||||||
(fn []
|
:empty-password? (empty? password)}))
|
||||||
(let [{user-color :color} (rf/sub [:onboarding/profile])
|
[password]))
|
||||||
{:keys [long-enough?]
|
|
||||||
:as validations} (password-validations @password)
|
|
||||||
password-strength (calc-password-strength validations)
|
|
||||||
empty-password? (empty? @password)
|
|
||||||
same-passwords? (and (not empty-password?) (= @password @repeat-password))
|
|
||||||
meet-requirements? (and (not empty-password?)
|
|
||||||
(utils.string/at-least-n-chars? @password 10)
|
|
||||||
same-passwords?
|
|
||||||
@accepts-disclaimer?)]
|
|
||||||
[:<>
|
|
||||||
[rn/view {:style style/top-part}
|
|
||||||
[header]
|
|
||||||
[password-inputs
|
|
||||||
{:password-long-enough? long-enough?
|
|
||||||
:passwords-match? same-passwords?
|
|
||||||
:empty-password? empty-password?
|
|
||||||
:show-password-validation? @show-password-validation?
|
|
||||||
:on-input-focus #(reset! focused-input :password)
|
|
||||||
:on-change-password (fn [new-value]
|
|
||||||
(reset! password new-value)
|
|
||||||
(when (same-password-length?)
|
|
||||||
(reset! show-password-validation? true)))
|
|
||||||
:on-change-repeat-password (fn [new-value]
|
|
||||||
(reset! repeat-password new-value)
|
|
||||||
(when (same-password-length?)
|
|
||||||
(reset! show-password-validation? true)))
|
|
||||||
:on-blur-repeat-password #(if empty-password?
|
|
||||||
(reset! show-password-validation? false)
|
|
||||||
(reset! show-password-validation? true))}]]
|
|
||||||
|
|
||||||
[rn/view {:style style/bottom-part}
|
(defn- use-repeat-password-checks
|
||||||
(when same-passwords?
|
[password repeat-password]
|
||||||
[rn/view {:style style/disclaimer-container}
|
(rn/use-memo
|
||||||
[quo/disclaimer
|
(fn []
|
||||||
{:blur? true
|
{:same-password-length? (and (seq password) (= (count password) (count repeat-password)))
|
||||||
:on-change #(swap! accepts-disclaimer? not)
|
:same-passwords? (and (seq password) (= password repeat-password))})
|
||||||
:checked? @accepts-disclaimer?}
|
[password repeat-password]))
|
||||||
(i18n/label :t/password-creation-disclaimer)]])
|
|
||||||
(when (and (= @focused-input :password) (not same-passwords?))
|
|
||||||
[help
|
|
||||||
{:validations validations
|
|
||||||
:password-strength password-strength}])
|
|
||||||
|
|
||||||
[rn/view {:style style/button-container}
|
|
||||||
[quo/button
|
|
||||||
{:disabled? (not meet-requirements?)
|
|
||||||
:customization-color user-color
|
|
||||||
:on-press #(rf/dispatch
|
|
||||||
[:onboarding/password-set
|
|
||||||
(security/mask-data @password)])}
|
|
||||||
(i18n/label :t/password-creation-confirm)]]]]))))
|
|
||||||
|
|
||||||
(defn create-password-doc
|
(defn create-password-doc
|
||||||
[]
|
[]
|
||||||
|
@ -183,38 +140,108 @@
|
||||||
[quo/text {:size :paragraph-2}
|
[quo/text {:size :paragraph-2}
|
||||||
(i18n/label :t/create-profile-password-info-box-description)]]])
|
(i18n/label :t/create-profile-password-info-box-description)]]])
|
||||||
|
|
||||||
|
(defn- on-press-info
|
||||||
|
[]
|
||||||
|
(rn/dismiss-keyboard!)
|
||||||
|
(rf/dispatch [:show-bottom-sheet
|
||||||
|
{:content create-password-doc
|
||||||
|
:shell? true}]))
|
||||||
|
|
||||||
|
(defn- navigate-back
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:navigate-back]))
|
||||||
|
|
||||||
|
(defn- page-nav
|
||||||
|
[]
|
||||||
|
(let [{:keys [top]} (safe-area/get-insets)]
|
||||||
|
[quo/page-nav
|
||||||
|
{:margin-top top
|
||||||
|
:background :blur
|
||||||
|
:icon-name :i/arrow-left
|
||||||
|
:on-press navigate-back
|
||||||
|
:right-side [{:icon-name :i/info
|
||||||
|
:on-press on-press-info}]}]))
|
||||||
|
|
||||||
(defn create-password
|
(defn create-password
|
||||||
[]
|
[]
|
||||||
(reagent/with-let [keyboard-shown? (reagent/atom false)
|
(let [[password set-password] (rn/use-state "")
|
||||||
{:keys [top bottom]} (safe-area/get-insets)
|
[repeat-password set-repeat-password] (rn/use-state "")
|
||||||
will-show-listener (ocall rn/keyboard
|
[accepts-disclaimer? set-accepts-disclaimer?] (rn/use-state false)
|
||||||
"addListener"
|
[focused-input set-focused-input] (rn/use-state nil)
|
||||||
"keyboardWillShow"
|
[show-password-validation?
|
||||||
#(reset! keyboard-shown? true))
|
set-show-password-validation?] (rn/use-state false)
|
||||||
will-hide-listener (ocall rn/keyboard
|
{user-color :color} (rf/sub [:onboarding/profile])
|
||||||
"addListener"
|
|
||||||
"keyboardWillHide"
|
|
||||||
#(reset! keyboard-shown? false))
|
{:keys [password-long-enough?
|
||||||
on-press-info (fn []
|
password-validations password-strength
|
||||||
(rn/dismiss-keyboard!)
|
empty-password?]} (use-password-checks password)
|
||||||
(rf/dispatch [:show-bottom-sheet
|
|
||||||
{:content create-password-doc
|
{:keys [same-password-length? same-passwords?]} (use-repeat-password-checks password
|
||||||
:shell? true}]))]
|
repeat-password)
|
||||||
[:<>
|
|
||||||
[rn/touchable-without-feedback
|
meet-requirements? (rn/use-memo
|
||||||
{:on-press rn/dismiss-keyboard!
|
#(and (not empty-password?)
|
||||||
:accessible false}
|
(utils.string/at-least-n-chars? password
|
||||||
[rn/view {:style style/flex-fill}
|
10)
|
||||||
[rn/keyboard-avoiding-view {:style style/flex-fill}
|
same-passwords?
|
||||||
[quo/page-nav
|
accepts-disclaimer?)
|
||||||
{:margin-top top
|
[password repeat-password
|
||||||
:background :blur
|
accepts-disclaimer?])]
|
||||||
:icon-name :i/arrow-left
|
|
||||||
:on-press #(rf/dispatch [:navigate-back])
|
[floating-button/view
|
||||||
:right-side [{:icon-name :i/info
|
{:header [page-nav]
|
||||||
:on-press on-press-info}]}]
|
:keyboard-should-persist-taps :handled
|
||||||
[password-form]
|
:content-avoid-keyboard? true
|
||||||
[rn/view {:style {:height (if-not @keyboard-shown? bottom 0)}}]]]]]
|
:blur-options
|
||||||
(finally
|
{:blur-amount 34
|
||||||
(ocall will-show-listener "remove")
|
:blur-radius 20
|
||||||
(ocall will-hide-listener "remove"))))
|
:blur-type :transparent
|
||||||
|
:overlay-color :transparent
|
||||||
|
:background-color (if platform/android? colors/neutral-100 colors/neutral-80-opa-1-blur)
|
||||||
|
:padding-vertical 0
|
||||||
|
:padding-horizontal 0}
|
||||||
|
:footer-container-padding 0
|
||||||
|
:footer
|
||||||
|
[rn/view
|
||||||
|
{:style style/footer-container}
|
||||||
|
(when same-passwords?
|
||||||
|
[rn/view {:style style/disclaimer-container}
|
||||||
|
[quo/disclaimer
|
||||||
|
{:blur? true
|
||||||
|
:on-change (partial set-accepts-disclaimer? not)
|
||||||
|
:checked? accepts-disclaimer?}
|
||||||
|
(i18n/label :t/password-creation-disclaimer)]])
|
||||||
|
(when (and (= focused-input :password) (not same-passwords?))
|
||||||
|
[help
|
||||||
|
{:validations password-validations
|
||||||
|
:password-strength password-strength}])
|
||||||
|
[quo/button
|
||||||
|
{:container-style style/footer-button-container
|
||||||
|
:disabled? (not meet-requirements?)
|
||||||
|
:customization-color user-color
|
||||||
|
:on-press #(rf/dispatch
|
||||||
|
[:onboarding/password-set
|
||||||
|
(security/mask-data password)])}
|
||||||
|
(i18n/label :t/password-creation-confirm)]]}
|
||||||
|
|
||||||
|
[rn/view {:style style/form-container}
|
||||||
|
[header]
|
||||||
|
[password-inputs
|
||||||
|
{:password-long-enough? password-long-enough?
|
||||||
|
:passwords-match? same-passwords?
|
||||||
|
:empty-password? empty-password?
|
||||||
|
:show-password-validation? show-password-validation?
|
||||||
|
:on-input-focus #(set-focused-input :password)
|
||||||
|
:on-change-password (fn [new-value]
|
||||||
|
(set-password new-value)
|
||||||
|
(when same-password-length?
|
||||||
|
(set-show-password-validation? true)))
|
||||||
|
|
||||||
|
:on-change-repeat-password (fn [new-value]
|
||||||
|
(set-repeat-password new-value)
|
||||||
|
(when same-password-length?
|
||||||
|
(set-show-password-validation? true)))
|
||||||
|
:on-blur-repeat-password #(if empty-password?
|
||||||
|
(set-show-password-validation? false)
|
||||||
|
(set-show-password-validation? true))}]]]))
|
||||||
|
|
Loading…
Reference in New Issue