[#19004] Password input cursor is jumping when typing password fast (#19029)

This commit is contained in:
flexsurfer 2024-02-28 15:23:15 +01:00 committed by GitHub
parent bd7ced5f25
commit 26dd51c5da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 74 deletions

View File

@ -12,7 +12,7 @@
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.security.core :as security])) [utils.security.core :as security]))
(defn get-error-message (defn- get-error-message
[error] [error]
(if (and (some? error) (if (and (some? error)
(or (= error "file is not a database") (or (= error "file is not a database")
@ -21,40 +21,17 @@
(i18n/label :t/oops-wrong-password) (i18n/label :t/oops-wrong-password)
error)) error))
(defn- on-change-password (defn- error-info
[entered-password] [error-message processing shell?]
(debounce/debounce-and-dispatch [:profile/on-password-input-changed (let [theme (quo.theme/use-theme-value)
{:password (security/mask-data entered-password) on-press (rn/use-callback
:error ""}] (fn []
100)) (rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
(defn- view-internal {:content #(forgot-password-doc/view {:shell? shell?})
[{:keys [default-password theme shell? on-press-biometrics blur?]}] :theme theme
(let [{:keys [error processing]} (rf/sub [:profile/login]) :shell? shell?}]))
error-message (get-error-message error) [theme])]
error? (boolean (seq error-message))]
[:<>
[rn/view {:style {:flex-direction :row}}
[quo/input
{:container-style {:flex 1}
:type :password
:blur? blur?
:disabled? processing
:placeholder (i18n/label :t/type-your-password)
:auto-focus true
:error? error?
:label (i18n/label :t/profile-password)
:on-change-text on-change-password
:default-value (security/safe-unmask-data default-password)}]
(when on-press-biometrics
[quo/button
{:container-style style/auth-button
:on-press on-press-biometrics
:icon-only? true
:background (when blur? :blur)
:type :outline}
:i/face-id])]
(when error?
[rn/view {:style style/error-message} [rn/view {:style style/error-message}
[quo/info-message [quo/info-message
{:type :error {:type :error
@ -64,17 +41,50 @@
[rn/pressable [rn/pressable
{:hit-slop {:top 6 :bottom 20 :left 0 :right 0} {:hit-slop {:top 6 :bottom 20 :left 0 :right 0}
:disabled processing :disabled processing
:on-press (fn [] :on-press on-press}
(rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
{:content #(forgot-password-doc/view {:shell? shell?})
:theme theme
:shell? shell?}]))}
[rn/text [rn/text
{:style {:text-decoration-line :underline {:style {:text-decoration-line :underline
:color (colors/resolve-color :danger theme)} :color (colors/resolve-color :danger theme)}
:size :paragraph-2 :size :paragraph-2
:suppress-highlighting true} :suppress-highlighting true}
(i18n/label :t/forgot-password)]]])])) (i18n/label :t/forgot-password)]]]))
(defn view
[{:keys [shell? on-press-biometrics blur?]}]
(let [{:keys [error processing]} (rf/sub [:profile/login])
error-message (rn/use-memo #(get-error-message error) [error])
error? (boolean (seq error-message))
default-value (rn/use-ref-atom "") ;;bug on Android
;;https://github.com/status-im/status-mobile/issues/19004
on-change-password (rn/use-callback
(fn [entered-password]
(reset! default-value entered-password)
(debounce/debounce-and-dispatch [:profile/on-password-input-changed
{:password (security/mask-data
entered-password)
:error ""}]
100)))]
[:<>
[rn/view {:style {:flex-direction :row}}
[quo/input
{:container-style {:flex 1}
:type :password
:default-value @default-value
:blur? blur?
:disabled? processing
:placeholder (i18n/label :t/type-your-password)
:auto-focus true
:error? error?
:label (i18n/label :t/profile-password)
:on-change-text on-change-password}]
(when on-press-biometrics
[quo/button
{:container-style style/auth-button
:on-press on-press-biometrics
:icon-only? true
:background (when blur? :blur)
:type :outline}
:i/face-id])]
(when error?
[error-info error-message processing shell?])]))
(def view (quo.theme/with-theme view-internal))

View File

@ -5,7 +5,6 @@
[react-native.core :as rn] [react-native.core :as rn]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.confirmation-drawer.view :as confirmation-drawer] [status-im.common.confirmation-drawer.view :as confirmation-drawer]
[status-im.common.standard-authentication.core :as standard-authentication] [status-im.common.standard-authentication.core :as standard-authentication]
[status-im.config :as config] [status-im.config :as config]
@ -133,8 +132,8 @@
[:profile.login/login-with-biometric-if-available key-uid]) [:profile.login/login-with-biometric-if-available key-uid])
(when-not keycard-pairing (set-hide-profiles)))}])) (when-not keycard-pairing (set-hide-profiles)))}]))
(defn- f-profiles-section (defn- profiles-section
[{:keys [set-hide-profiles]}] [{:keys [hide-profiles]}]
(let [profiles (vals (rf/sub [:profile/profiles-overview])) (let [profiles (vals (rf/sub [:profile/profiles-overview]))
translate-x (reanimated/use-shared-value @translate-x-atom)] translate-x (reanimated/use-shared-value @translate-x-atom)]
(rn/use-mount (fn [] (rn/use-mount (fn []
@ -165,42 +164,38 @@
:key-fn :key-uid :key-fn :key-uid
:content-container-style {:padding-bottom 20} :content-container-style {:padding-bottom 20}
:render-data {:last-index (dec (count profiles)) :render-data {:last-index (dec (count profiles))
:set-hide-profiles set-hide-profiles} :set-hide-profiles hide-profiles}
:render-fn profile-card}]])) :render-fn profile-card}]]))
(defn profiles-section
[props]
[:f> f-profiles-section props])
(defn password-input (defn password-input
[] []
(let [password (rf/sub [:profile/login-password]) (let [auth-method (rf/sub [:auth-method])
auth-method (rf/sub [:auth-method])] on-press-biometrics (when (= auth-method constants/auth-method-biometric)
[standard-authentication/password-input (rn/use-callback
{:shell? true
:blur? true
:on-press-biometrics (when (= auth-method constants/auth-method-biometric)
(fn [] (fn []
(rf/dispatch [:biometric/authenticate (rf/dispatch [:biometric/authenticate
{:on-success #(rf/dispatch {:on-success #(rf/dispatch
[:profile.login/biometric-success]) [:profile.login/biometric-success])
:on-fail #(rf/dispatch :on-fail #(rf/dispatch
[:profile.login/biometric-auth-fail [:profile.login/biometric-auth-fail
%])}]))) %])}]))))]
:default-password password}])) [standard-authentication/password-input
{:shell? true
:blur? true
:on-press-biometrics on-press-biometrics}]))
(defn login-section (defn login-section
[{:keys [set-show-profiles]}] [{:keys [show-profiles]}]
(let [processing (rf/sub [:profile/login-processing]) (let [processing (rf/sub [:profile/login-processing])
{:keys [key-uid name customization-color]} (rf/sub [:profile/login-profile]) {:keys [key-uid name
customization-color]} (rf/sub [:profile/login-profile])
sign-in-enabled? (rf/sub [:sign-in-enabled?]) sign-in-enabled? (rf/sub [:sign-in-enabled?])
profile-picture (rf/sub [:profile/login-profiles-picture key-uid]) profile-picture (rf/sub [:profile/login-profiles-picture key-uid])
login-multiaccount #(rf/dispatch [:profile.login/login])] login-multiaccount (rn/use-callback #(rf/dispatch [:profile.login/login]))]
[rn/keyboard-avoiding-view [rn/keyboard-avoiding-view
{:style style/login-container {:style style/login-container
:keyboardVerticalOffset (- (safe-area/get-bottom))} :keyboardVerticalOffset (- (safe-area/get-bottom))}
[rn/view [rn/view {:style style/multi-profile-button-container}
{:style style/multi-profile-button-container}
(when config/quo-preview-enabled? (when config/quo-preview-enabled?
[quo/button [quo/button
{:size 32 {:size 32
@ -217,7 +212,7 @@
:type :grey :type :grey
:background :blur :background :blur
:icon-only? true :icon-only? true
:on-press set-show-profiles :on-press show-profiles
:disabled? processing :disabled? processing
:accessibility-label :show-profiles} :accessibility-label :show-profiles}
:i/multi-profile]] :i/multi-profile]]
@ -241,16 +236,13 @@
:container-style {:margin-bottom (+ (safe-area/get-bottom) 12)}} :container-style {:margin-bottom (+ (safe-area/get-bottom) 12)}}
(i18n/label :t/log-in)]])) (i18n/label :t/log-in)]]))
;; we had to register it here, because of hotreload, overwise on hotreload it will be reseted
(defonce show-profiles? (reagent/atom false))
(defn view (defn view
[] []
(let [set-show-profiles #(reset! show-profiles? true) (let [[show-profiles? set-show-profiles] (rn/use-state false)
set-hide-profiles #(reset! show-profiles? false)] show-profiles (rn/use-callback #(set-show-profiles true))
(fn [] hide-profiles (rn/use-callback #(set-show-profiles false))]
[:<> [:<>
[background/view true] [background/view true]
(if @show-profiles? (if show-profiles?
[profiles-section {:set-hide-profiles set-hide-profiles}] [profiles-section {:hide-profiles hide-profiles}]
[login-section {:set-show-profiles set-show-profiles}])]))) [login-section {:show-profiles show-profiles}])]))