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:
Siddarth Kumar 2023-10-05 21:05:54 +05:30 committed by GitHub
parent c2833ae33d
commit 7043e03dd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 17 deletions

View File

@ -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.

View File

@ -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})

View File

@ -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)]]))))

View File

@ -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

View File

@ -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?

View File

@ -2331,5 +2331,7 @@
"here-is-a-cat-in-a-box-instead": "Heres 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..."
}