Enter scan code tab in Syncing (#16852)
* feat: add enter scan code view This commit adds the enter sync code UI. Fixes : #16062 Design link : https://www.figma.com/file/V6nlpAWIf2e1XU8RJ9yQPe/Syncing-for-Mobile?node-id=675%3A179729&mode=dev Review notes : We do not make use of quo2/input here because currently that component does not allow stretching to fit in sync code which spans upto 3 lines.
This commit is contained in:
parent
c2833ae33d
commit
7043e03dd4
|
@ -0,0 +1,31 @@
|
|||
### How should the paste button behave when clipboard is empty?
|
||||
|
||||
This question first came up as a review comment to this PR
|
||||
https://github.com/status-im/status-mobile/pull/16852
|
||||
|
||||
There were 2 considerations :
|
||||
- Either keep the paste button disabled when there is nothing in the clipboard OR
|
||||
- Always keep the paste button enabled
|
||||
|
||||
There were positives and negatives for both approaches.
|
||||
|
||||
Positives of keeping paste button disabled when there is nothing in clipboard would require us to
|
||||
check the value of clipboard as soon as the component is mounted (i.e when the user first sees
|
||||
the screen). In iOS this means a native permissions dialog would appear requesting for permissions
|
||||
to paste from the clipboard.
|
||||
|
||||
Negatives of this approach is that as soon as any user navigates to this screen they are greeted with
|
||||
this popup which can be annoying sometimes.
|
||||
|
||||
Positives of keeping paste button always enabled is that we can trigger a request to the clipboard on
|
||||
tap of the paste button which would trigger the native permissions dialog requesting for permissions
|
||||
to paste from the clipboard.
|
||||
In this case seeing this dialog is okay because the user has initiated a paste action.
|
||||
|
||||
Negatives of this approach is that in the event the clipboard is empty the user will still see the
|
||||
system dialog and on approving nothing will be pasted (because the clipboard was empty).
|
||||
This behaviour can be confusing.
|
||||
|
||||
On consulting the Design Team via discord it was concluded that out of the two approaches
|
||||
having the paste button always enabled is a better UX overall.
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
(ns status-im2.contexts.syncing.enter-sync-code.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.typography :as typography]))
|
||||
|
||||
(def container-text-input
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-horizontal 20})
|
||||
|
||||
(defn text-input-container
|
||||
[invalid?]
|
||||
{:padding-left 12
|
||||
:padding-right 7
|
||||
:min-height 38
|
||||
:flex 1
|
||||
:flex-direction :row
|
||||
:border-width 1
|
||||
:border-radius 12
|
||||
:border-color (if invalid?
|
||||
colors/danger-50-opa-40
|
||||
colors/neutral-60)})
|
||||
|
||||
(defn text-input
|
||||
[]
|
||||
(merge typography/monospace
|
||||
typography/paragraph-1
|
||||
{:flex 1
|
||||
:padding-top 6
|
||||
:padding-bottom 8
|
||||
:color colors/white
|
||||
:text-align-vertical :top}))
|
||||
|
||||
(def label-texts-container
|
||||
{:flex-direction :row
|
||||
:height 18
|
||||
:margin-bottom 8})
|
||||
|
||||
(def button-paste
|
||||
{:margin-top 8})
|
||||
|
||||
(def clear-icon
|
||||
{:size 20
|
||||
:color colors/neutral-80-opa-30})
|
||||
|
||||
(def right-icon-touchable-area
|
||||
{:margin-left 8
|
||||
:padding-right 4
|
||||
:padding-top 6
|
||||
:margin-bottom 4})
|
||||
|
||||
(def label-pairing
|
||||
{:color colors/white-opa-40})
|
||||
|
||||
(def label-container
|
||||
{:flex-direction :row
|
||||
:margin-left 20
|
||||
:line-height 18
|
||||
:margin-top 20
|
||||
:margin-bottom 8})
|
||||
|
||||
(def continue-button-container
|
||||
{:margin-top 12
|
||||
:padding-horizontal 22})
|
|
@ -0,0 +1,76 @@
|
|||
(ns status-im2.contexts.syncing.enter-sync-code.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[reagent.core :as reagent]
|
||||
[react-native.core :as rn]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im2.contexts.syncing.enter-sync-code.style :as style]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.syncing.utils :as sync-utils]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [sync-code-value (reagent/atom "")]
|
||||
(fn []
|
||||
(let [invalid? false
|
||||
show-paste-button? (string/blank? @sync-code-value)
|
||||
profile-color (rf/sub [:profile/customization-color])]
|
||||
[:<>
|
||||
[rn/view
|
||||
{:style style/label-container}
|
||||
[quo/text
|
||||
{:style style/label-pairing
|
||||
:weight :medium
|
||||
:size :paragraph-2}
|
||||
(i18n/label :t/type-pairing-code)]]
|
||||
[rn/view {:style style/container-text-input}
|
||||
[rn/view {:style (style/text-input-container invalid?)}
|
||||
[rn/text-input
|
||||
{:style (style/text-input)
|
||||
:value @sync-code-value
|
||||
:placeholder (i18n/label :t/scan-sync-code-placeholder)
|
||||
:on-change-text (fn [scan-code]
|
||||
(reset! sync-code-value scan-code)
|
||||
(reagent/flush))
|
||||
:blur-on-submit true
|
||||
:return-key-type :done
|
||||
:accessibility-label :enter-sync-code-input
|
||||
:auto-capitalize :none
|
||||
:placeholder-text-color colors/white-opa-40
|
||||
:multiline true}]
|
||||
(if show-paste-button?
|
||||
[quo/button
|
||||
{:on-press (fn [_]
|
||||
(clipboard/get-string #(reset! sync-code-value %)))
|
||||
:type :outline
|
||||
:container-style style/button-paste
|
||||
:size 24}
|
||||
(i18n/label :t/paste)]
|
||||
|
||||
[rn/pressable
|
||||
{:accessibility-label :input-right-icon
|
||||
:style style/right-icon-touchable-area
|
||||
:on-press (fn [_]
|
||||
(reset! sync-code-value nil))}
|
||||
[quo/icon :i/clear style/clear-icon]])]]
|
||||
[quo/button
|
||||
{:type :primary
|
||||
:disabled? (string/blank? @sync-code-value)
|
||||
:customization-color profile-color
|
||||
:container-style style/continue-button-container
|
||||
:on-press (fn [_]
|
||||
(if (sync-utils/valid-connection-string? @sync-code-value)
|
||||
(debounce/debounce-and-dispatch
|
||||
[:syncing/input-connection-string-for-bootstrapping
|
||||
@sync-code-value]
|
||||
300)
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:icon :i/info
|
||||
:icon-color colors/danger-50
|
||||
:theme :dark
|
||||
:text (i18n/label
|
||||
:t/error-this-is-not-a-sync-qr-code)}])))}
|
||||
(i18n/label :t/confirm)]]))))
|
|
@ -133,11 +133,6 @@
|
|||
{:color colors/white-opa-70
|
||||
:margin-bottom 16})
|
||||
|
||||
(def enter-sync-code-container
|
||||
{:margin-top 20
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn bottom-container
|
||||
[translate-y padding-bottom]
|
||||
(reanimated/apply-animations-to-style
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as transforms]))
|
||||
[utils.transforms :as transforms]
|
||||
[status-im2.contexts.syncing.enter-sync-code.view :as enter-sync-code]))
|
||||
|
||||
;; Android allow local network access by default. So, we need this check on iOS only.
|
||||
(defonce preflight-check-passed? (reagent/atom (if platform/ios? false true)))
|
||||
|
@ -199,15 +200,6 @@
|
|||
[viewfinder qr-view-finder]
|
||||
[camera-and-local-network-access-permission-view]))
|
||||
|
||||
(defn- enter-sync-code-tab
|
||||
[]
|
||||
[rn/view {:style style/enter-sync-code-container}
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :medium
|
||||
:style {:color colors/white}}
|
||||
"Yet to be implemented"]])
|
||||
|
||||
(defn- f-bottom-view
|
||||
[insets translate-y]
|
||||
[rn/touchable-without-feedback
|
||||
|
@ -374,7 +366,7 @@
|
|||
{})}
|
||||
(case @active-tab
|
||||
1 [scan-qr-code-tab @qr-view-finder]
|
||||
2 [enter-sync-code-tab]
|
||||
2 [enter-sync-code/view]
|
||||
nil)]
|
||||
[rn/view {:style style/flex-spacer}]
|
||||
(when show-bottom-view?
|
||||
|
|
|
@ -2331,5 +2331,7 @@
|
|||
"here-is-a-cat-in-a-box-instead": "Here’s a cat in a box instead",
|
||||
"accounts-count": "{{count}} accounts",
|
||||
"enter-eth": "Enter any ETH address or ENS name.",
|
||||
"eth-or-ens": "ETH address or ENS name."
|
||||
"eth-or-ens": "ETH address or ENS name.",
|
||||
"type-pairing-code": "Type or paste pairing code",
|
||||
"scan-sync-code-placeholder": "cs2:4FH..."
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue