UI for mobile to mobile local pairing - updated (#14514)
* ui for local pairing lint-fix removed un-necessary + addressing some of the feedback on PR more feedback + removing feature toggle from ui getting rid of comments/log messages over here tidy up logs fix typos and more i18n stuff swap % with a named parameter getting rid of global state + lint-fix get rid of un-used function icon guidelines and more kebab case stuff :> moving stuff to events and utils namespace :main-icons -> :i :) address feedback and adhere to guidelines etc fixed the :t/ qualification moree feedback :-D referring status-im.utils.security for now adding "cs" to constants make tests pass re-frame to rf addressing feedback moving icons to icons2 & renaming stuff trying to make this file the way it was before missed out on updating these references getting rid of the icons moved to icons2 This reverts commit be8552c0d3daaf7a7333cfeaf304d97c86d50d3e. fixing mistakes getting rid of the s * this rename makes sense to me * adding an alias to the view * fixed broken up namespaces
This commit is contained in:
parent
621e41e6ab
commit
fc07fbf787
1
.env
1
.env
|
@ -32,3 +32,4 @@ COMMANDS_ENABLED=1
|
|||
TWO_MINUTES_SYNCING=1
|
||||
SWAP_ENABLED=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
|
1
.env.e2e
1
.env.e2e
|
@ -32,3 +32,4 @@ COMMUNITIES_MANAGEMENT_ENABLED=1
|
|||
DELETE_MESSAGE_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
|
|
@ -34,3 +34,4 @@ DELETE_MESSAGE_ENABLED=1
|
|||
TWO_MINUTES_SYNCING=1
|
||||
ENABLE_QUO_PREVIEW=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
|
|
@ -940,6 +940,52 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getConnectionStringForBootstrappingAnotherDevice(final String configJSON, final Callback callback) throws JSONException {
|
||||
final JSONObject jsonConfig = new JSONObject(configJSON);
|
||||
final String keyUID = jsonConfig.getString("keyUID");
|
||||
final String keyStorePath = this.getKeyStorePath(keyUID);
|
||||
jsonConfig.put("keystorePath", keyStorePath);
|
||||
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString());
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void inputConnectionStringForBootstrapping(final String connectionString, final String configJSON, final Callback callback) throws JSONException {
|
||||
final JSONObject jsonConfig = new JSONObject(configJSON);
|
||||
final String keyStorePath = pathCombine(this.getNoBackupDirectory(), "/keystore");
|
||||
jsonConfig.put("keystorePath", keyStorePath);
|
||||
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.inputConnectionStringForBootstrapping(connectionString,jsonConfig.toString());
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void hashTypedData(final String data, final Callback callback) {
|
||||
Log.d(TAG, "hashTypedData");
|
||||
|
|
|
@ -318,6 +318,42 @@ RCT_EXPORT_METHOD(hashMessage:(NSString *)message
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// getConnectionStringForBootstrappingAnotherDevice
|
||||
RCT_EXPORT_METHOD(getConnectionStringForBootstrappingAnotherDevice:(NSString *)configJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
||||
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
|
||||
NSString *keyUID = [configDict objectForKey:@"keyUID"];
|
||||
NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID];
|
||||
NSString *keystoreDir = multiaccountKeystoreDir.path;
|
||||
|
||||
[configDict setValue:keystoreDir forKey:@"keystorePath"];
|
||||
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
|
||||
|
||||
NSString *result = StatusgoGetConnectionStringForBootstrappingAnotherDevice(modifiedConfigJSON);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// inputConnectionStringForBootstrapping
|
||||
RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs
|
||||
configJSON:(NSString *)configJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
||||
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
NSURL *multiaccountKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
|
||||
NSString *keystoreDir = multiaccountKeystoreDir.path;
|
||||
|
||||
[configDict setValue:keystoreDir forKey:@"keystorePath"];
|
||||
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
|
||||
|
||||
NSString *result = StatusgoInputConnectionStringForBootstrapping(cs,modifiedConfigJSON);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// hashTypedData
|
||||
RCT_EXPORT_METHOD(hashTypedData:(NSString *)data
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 377 KiB |
Binary file not shown.
After Width: | Height: | Size: 738 KiB |
|
@ -200,3 +200,10 @@
|
|||
(def ^:const community-member-role-all 1)
|
||||
(def ^:const community-member-role-manage-users 2)
|
||||
(def ^:const community-member-role-moderator 3)
|
||||
|
||||
(def local-pairing-connection-string-identifier
|
||||
"If any string begins with cs we know its a connection string.
|
||||
This is useful when we read QR codes we know it is a connection string if it begins with this identifier.
|
||||
An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 "
|
||||
"cs")
|
||||
|
||||
|
|
|
@ -239,6 +239,23 @@
|
|||
(log/debug "[native-module] hash-message")
|
||||
(.hashMessage ^js (status) message callback))
|
||||
|
||||
(defn get-connection-string-for-bootstrapping-another-device
|
||||
"Generates connection string form status-go for the purpose of local pairing on the sender end"
|
||||
[config-json callback]
|
||||
(log/info "[native-module] Fetching Connection String"
|
||||
{:fn :get-connection-string-for-bootstrapping-another-device
|
||||
:config-json config-json})
|
||||
(.getConnectionStringForBootstrappingAnotherDevice ^js (status) config-json callback))
|
||||
|
||||
(defn input-connection-string-for-bootstrapping
|
||||
"Provides connection string to status-go for the purpose of local pairing on the receiver end"
|
||||
[connection-string config-json callback]
|
||||
(log/info "[native-module] Sending Connection String"
|
||||
{:fn :input-connection-string-for-bootstrapping
|
||||
:config-json config-json
|
||||
:connection-string connection-string})
|
||||
(.inputConnectionStringForBootstrapping ^js (status) connection-string config-json callback))
|
||||
|
||||
(defn hash-typed-data
|
||||
"used for keycard"
|
||||
[data callback]
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
[status-im.add-new.db :as new-chat.db]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.group-chats.core :as group-chats]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn scan-qr-code
|
||||
{:events [::scan-code]}
|
||||
|
@ -87,6 +88,11 @@
|
|||
{:dispatch [:wallet-connect-legacy/pair data]}
|
||||
{:dispatch [:wallet-connect/pair data]})))
|
||||
|
||||
(fx/defn handle-local-pairing
|
||||
{:events [::handle-local-pairing-uri]}
|
||||
[_ data]
|
||||
{:dispatch [:syncing/input-connection-string-for-bootstrapping data]})
|
||||
|
||||
(fx/defn match-scan
|
||||
{:events [::match-scanned-value]}
|
||||
[cofx {:keys [type] :as data}]
|
||||
|
@ -98,9 +104,14 @@
|
|||
:browser (handle-browse cofx data)
|
||||
:eip681 (handle-eip681 cofx data)
|
||||
:wallet-connect (handle-wallet-connect cofx data)
|
||||
:localpairing (handle-local-pairing cofx data)
|
||||
(do
|
||||
(log/info "Unable to find matcher for scanned value"
|
||||
{:type type
|
||||
:event ::match-scanned-value})
|
||||
{:dispatch [:navigate-back]
|
||||
:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}}))
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}})))
|
||||
|
||||
(fx/defn on-scan
|
||||
{:events [::on-scan-success]}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[status-im.utils.http :as http]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im.constants :as constants]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def ethereum-scheme "ethereum:")
|
||||
|
@ -223,6 +224,9 @@
|
|||
(wallet-connect/url? uri)
|
||||
(cb {:type :wallet-connect :data uri})
|
||||
|
||||
(string/starts-with? uri constants/local-pairing-connection-string-identifier)
|
||||
(cb {:type :localpairing :data uri})
|
||||
|
||||
:else
|
||||
(cb {:type :undefined
|
||||
:data uri}))))
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
{:db (assoc db :peer-stats peer-stats
|
||||
:peers-count (count (:peers peer-stats)))}))
|
||||
|
||||
(defn handle-local-pairing-signals [signal-type]
|
||||
(log/info "local pairing signal received"
|
||||
{:signal-type signal-type}))
|
||||
|
||||
(fx/defn process
|
||||
{:events [:signals/signal-received]}
|
||||
[{:keys [db] :as cofx} event-str]
|
||||
|
@ -77,4 +81,5 @@
|
|||
"local-notifications" (local-notifications/process cofx (js->clj event-js :keywordize-keys true))
|
||||
"community.found" (link.preview/cache-community-preview-data (js->clj event-js :keywordize-keys true))
|
||||
"status.updates.timedout" (visibility-status-updates/handle-visibility-status-updates cofx (js->clj event-js :keywordize-keys true))
|
||||
"localPairing" (handle-local-pairing-signals event-str)
|
||||
(log/debug "Event " type " not handled"))))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[quo.core :as quo]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im2.setup.config :as config]
|
||||
[status-im.ui.components.list.views :as list])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
[status-im.multiaccounts.key-storage.core :as multiaccounts.key-storage]
|
||||
[status-im.keycard.recovery :as keycard]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im2.setup.config :as config]
|
||||
[status-im.utils.security]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.core :as quo]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
|
@ -89,7 +90,17 @@
|
|||
[quo/list-item {:theme :accent
|
||||
:on-press #(hide-sheet-and-dispatch [:multiaccounts.login.ui/export-db-submitted])
|
||||
:icon :main-icons/send
|
||||
:title "Export unencrypted"}])]]))
|
||||
:title "Export unencrypted"}])
|
||||
(when config/local-pairing-mode-enabled?
|
||||
[:<>
|
||||
[quo/list-item {:theme :accent
|
||||
:on-press #(hide-sheet-and-dispatch [::qr-scanner/scan-code {:handler ::qr-scanner/on-scan-success}])
|
||||
:icon :i/key
|
||||
:title (i18n/label :t/scan-sync-code)}]
|
||||
[quo/list-item {:theme :accent
|
||||
:on-press #(hide-sheet-and-dispatch [:navigate-to :multiaccounts])
|
||||
:icon :i/key
|
||||
:title (i18n/label :t/show-existing-keys)}]])]]))
|
||||
|
||||
(def bottom-sheet
|
||||
{:content bottom-sheet-view})
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.profile.user.styles :as styles]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im2.setup.config :as config]
|
||||
[status-im.utils.gfycat.core :as gfy]
|
||||
[status-im.utils.universal-links.utils :as universal-links]
|
||||
[status-im.ui.components.profile-header.view :as profile-header]
|
||||
|
@ -67,7 +67,8 @@
|
|||
@(re-frame/subscribe [:multiaccount])
|
||||
active-contacts-count @(re-frame/subscribe [:contacts/active-count])
|
||||
chain @(re-frame/subscribe [:chain-keyword])
|
||||
registrar (stateofus/get-cached-registrar chain)]
|
||||
registrar (stateofus/get-cached-registrar chain)
|
||||
local-pairing-mode-enabled? config/local-pairing-mode-enabled?]
|
||||
[:<>
|
||||
[visibility-status/visibility-status-button
|
||||
visibility-status/calculate-button-height-and-dispatch-popover]
|
||||
|
@ -160,6 +161,13 @@
|
|||
:accessibility-label :about-button
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :about-app])}]
|
||||
(when local-pairing-mode-enabled?
|
||||
[quo/list-item
|
||||
{:icon :i/mobile
|
||||
:title (i18n/label :t/syncing)
|
||||
:accessibility-label :syncing
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :settings-syncing])}])
|
||||
[react/view {:padding-vertical 24}
|
||||
[quo/list-item
|
||||
{:icon :main-icons/log-out
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
(ns status-im2.contexts.syncing.events
|
||||
(:require [utils.re-frame :as rf]
|
||||
[status-im.utils.security :as security]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im2.contexts.syncing.sheets.enter-password.view :as sheet]))
|
||||
|
||||
(rf/defn initiate-local-pairing-with-connection-string
|
||||
{:events [:syncing/input-connection-string-for-bootstrapping]}
|
||||
[{:keys [db]} {:keys [data]}]
|
||||
(let [config-map (.stringify js/JSON (clj->js {:keyUID "" :keystorePath "" :password ""}))
|
||||
connection-string data]
|
||||
(status/input-connection-string-for-bootstrapping
|
||||
connection-string
|
||||
config-map
|
||||
#(log/info "this is response from initiate-local-pairing-with-connection-string " %))))
|
||||
|
||||
(rf/defn preparations-for-connection-string
|
||||
{:events [:syncing/get-connection-string-for-bootstrapping-another-device]}
|
||||
[{:keys [db]} entered-password]
|
||||
(let [sha3-pwd (status/sha3 (str (security/safe-unmask-data entered-password)))
|
||||
key-uid (get-in db [:multiaccount :key-uid])
|
||||
config-map (.stringify js/JSON (clj->js {:keyUID key-uid :keystorePath "" :password sha3-pwd}))]
|
||||
(status/get-connection-string-for-bootstrapping-another-device
|
||||
config-map
|
||||
(fn [connection-string]
|
||||
(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:show-handle? false
|
||||
:content (fn []
|
||||
[sheet/qr-code-view-with-connection-string connection-string])}])))))
|
|
@ -0,0 +1,60 @@
|
|||
(ns status-im2.contexts.syncing.sheets.enter-password.view
|
||||
(:require [react-native.core :as rn]
|
||||
[utils.re-frame :as rf]
|
||||
[quo2.core :as quo]
|
||||
[quo.core :as quo-old]
|
||||
[i18n.i18n :as i18n]
|
||||
[clojure.string :as string]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]))
|
||||
|
||||
(defn qr-code-view-with-connection-string [connection-string]
|
||||
(let [window-width (rf/sub [:dimensions/window-width])
|
||||
eighty-percent-screen-width (* window-width 0.8)
|
||||
valid-cs? (string/starts-with? connection-string constants/local-pairing-connection-string-identifier)]
|
||||
[:<>
|
||||
(if valid-cs?
|
||||
[rn/view {:margin 20}
|
||||
[quo/text {:accessibility-label :sync-code-generated
|
||||
:weight :bold
|
||||
:size :heading-1
|
||||
:style {:color colors/neutral-100
|
||||
:margin 20}}
|
||||
(i18n/label :t/sync-code-generated)]
|
||||
[qr-code-viewer/qr-code-view eighty-percent-screen-width connection-string]
|
||||
[quo/information-box {:type :informative
|
||||
:closable? false
|
||||
:icon :i/placeholder
|
||||
:style {:margin-top 20}} (i18n/label :t/instruction-after-qr-generated)]]
|
||||
[rn/view {:margin 20}
|
||||
[rn/view {:padding-horizontal 8}
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:preparations-for-connection-string])}
|
||||
(i18n/label :t/try-your-luck-again)]]])]))
|
||||
|
||||
(defn sheet []
|
||||
(let [entered-password (atom "")]
|
||||
[:<>
|
||||
[rn/view {:margin 20}
|
||||
[rn/view
|
||||
[quo/text {:accessibility-label :sync-code-generated
|
||||
:weight :bold
|
||||
:size :heading-1
|
||||
:style {:color colors/neutral-100
|
||||
:margin 20}}
|
||||
(i18n/label :t/enter-your-password)]
|
||||
[rn/view {:flex-direction :row :align-items :center}
|
||||
[rn/view {:flex 1}
|
||||
[quo-old/text-input ;;TODO : migrate text-input from quo to quo2 namespace
|
||||
{:placeholder (i18n/label :t/enter-your-password)
|
||||
:auto-focus true
|
||||
:accessibility-label :password-input
|
||||
:show-cancel false
|
||||
:on-change-text #(reset! entered-password %)
|
||||
:secure-text-entry true}]]]
|
||||
[rn/view {:padding-horizontal 18
|
||||
:margin-top 20}
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:syncing/get-connection-string-for-bootstrapping-another-device @entered-password])}
|
||||
(i18n/label :t/generate-scan-sync-code)]]]]]))
|
|
@ -0,0 +1,34 @@
|
|||
(ns status-im2.contexts.syncing.sheets.sync-device-notice.styles
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def sync-devices-header
|
||||
{:width "100%"})
|
||||
|
||||
(def sync-devices-header-image
|
||||
{:width "100%"
|
||||
:height 192})
|
||||
|
||||
(def sync-devices-body-container
|
||||
{:margin-bottom 20
|
||||
:border-radius 20
|
||||
:z-index 2
|
||||
:margin-top -16
|
||||
:background-color colors/white
|
||||
:padding 20})
|
||||
|
||||
(def header-text
|
||||
{:color colors/neutral-100})
|
||||
|
||||
(def instructions-text
|
||||
{:color colors/neutral-100
|
||||
:margin-top 8})
|
||||
|
||||
(def list-item-text
|
||||
{:color colors/neutral-100
|
||||
:margin-top 18})
|
||||
|
||||
(def setup-syncing-button
|
||||
{:margin-top 21})
|
||||
|
||||
(def secondary-body-container
|
||||
{:margin-top 21})
|
|
@ -0,0 +1,54 @@
|
|||
(ns status-im2.contexts.syncing.sheets.sync-device-notice.view
|
||||
(:require
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.syncing.sheets.sync-device-notice.styles :as styles]
|
||||
[status-im2.contexts.syncing.sheets.enter-password.view :as enter-password]
|
||||
[utils.re-frame :as rf]
|
||||
[quo2.core :as quo]
|
||||
[i18n.i18n :as i18n]))
|
||||
|
||||
(defn sheet []
|
||||
[:<>
|
||||
[rn/view {:style styles/sync-devices-header}
|
||||
[rn/image {:source (js/require "../resources/images/ui/sync-new-device-cover-background.png")
|
||||
:style styles/sync-devices-header-image}]]
|
||||
[rn/view {:style styles/sync-devices-body-container}
|
||||
[quo/text {:accessibility-label :privacy-policy
|
||||
:weight :bold
|
||||
:size :heading-1
|
||||
:style styles/header-text}
|
||||
(i18n/label :t/sync-new-device)]
|
||||
|
||||
[quo/text {:accessibility-label :privacy-policy
|
||||
:weight :regular
|
||||
:size :paragraph-1
|
||||
:style styles/instructions-text}
|
||||
(i18n/label :t/sync-instructions-text)]
|
||||
|
||||
[quo/text {:accessibility-label :privacy-policy
|
||||
:weight :regular
|
||||
:size :paragraph-2
|
||||
:style styles/list-item-text}
|
||||
(i18n/label :t/sync-instruction-step-1)]
|
||||
|
||||
[quo/text {:accessibility-label :privacy-policy
|
||||
:weight :regular
|
||||
:size :paragraph-2
|
||||
:style styles/list-item-text}
|
||||
(i18n/label :t/sync-instruction-step-2)]
|
||||
|
||||
[quo/text {:accessibility-label :privacy-policy
|
||||
:weight :regular
|
||||
:size :paragraph-2
|
||||
:style styles/list-item-text}
|
||||
(i18n/label :t/sync-instruction-step-3)]
|
||||
|
||||
[quo/button {:type :secondary
|
||||
:size 40
|
||||
:style styles/setup-syncing-button
|
||||
:before :i/face-id20
|
||||
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:show-handle? false
|
||||
:content (fn []
|
||||
[enter-password/sheet])}])}
|
||||
(i18n/label :t/setup-syncing)]]])
|
|
@ -0,0 +1,24 @@
|
|||
(ns status-im2.contexts.syncing.styles
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def container-main
|
||||
{:margin 16})
|
||||
|
||||
(def devices-container
|
||||
{:border-color colors/neutral-20
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
:margin-top 12})
|
||||
|
||||
(def device-row
|
||||
{:flex-direction :row
|
||||
:padding-vertical 10
|
||||
:padding-left 10})
|
||||
|
||||
(def device-column
|
||||
{:flex-direction :column
|
||||
:margin-left 10
|
||||
:align-self :center})
|
||||
|
||||
(def sync-device-container
|
||||
{:padding 10})
|
|
@ -0,0 +1,44 @@
|
|||
(ns status-im2.contexts.syncing.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.core :as quo]
|
||||
[i18n.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im2.contexts.syncing.styles :as styles]
|
||||
[status-im2.contexts.syncing.sheets.sync-device-notice.view :as sync-device-notice]))
|
||||
|
||||
(defn render-device [device-name device-status]
|
||||
[:<>
|
||||
[rn/view {:style styles/device-row}
|
||||
[quo/icon-avatar {:size :medium
|
||||
:icon :i/placeholder
|
||||
:color :primary
|
||||
:style {:margin-vertical 10}}]
|
||||
[rn/view {:style styles/device-column}
|
||||
[quo/text {:accessibility-label :device-name
|
||||
:weight :medium
|
||||
:size :paragraph-1
|
||||
:style {:color colors/neutral-100}} device-name]
|
||||
|
||||
[quo/text {:accessibility-label :device-status
|
||||
:weight :regular
|
||||
:size :paragraph-2
|
||||
:style {:color colors/neutral-50}} device-status]]]])
|
||||
|
||||
(defn views []
|
||||
[rn/view {:style styles/container-main}
|
||||
[quo/text {:accessibility-label :synced-devices-title
|
||||
:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color colors/neutral-50}} (i18n/label :t/synced-devices)]
|
||||
[rn/view {:style styles/devices-container}
|
||||
[render-device "iPhone 11" (i18n/label :t/this-device)] ;; note : the device name is hardcoded for now
|
||||
[rn/view {:style styles/sync-device-container}
|
||||
[quo/button {:label :primary
|
||||
:size 40
|
||||
:before :i/placeholder
|
||||
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:show-handle? false
|
||||
:content (fn []
|
||||
[sync-device-notice/sheet])}])}
|
||||
(i18n/label :t/sync-new-device)]]]])
|
|
@ -5,7 +5,8 @@
|
|||
[status-im2.contexts.shell.view :as shell]
|
||||
[status-im2.contexts.quo-preview.main :as quo.preview]
|
||||
[status-im2.contexts.chat.messages.view :as chat]
|
||||
|
||||
[status-im2.contexts.syncing.view :as settings-syncing]
|
||||
[i18n.i18n :as i18n]
|
||||
;; TODO remove when not used anymore
|
||||
[status-im.ui.screens.screens :as old-screens]))
|
||||
|
||||
|
@ -29,7 +30,12 @@
|
|||
|
||||
{:name :community-overview
|
||||
:options {:topBar {:visible false}}
|
||||
:component communities.overview/overview}]
|
||||
:component communities.overview/overview}
|
||||
|
||||
{:name :settings-syncing
|
||||
:insets {:bottom true}
|
||||
:options {:topBar {:title {:text (i18n/label :t/syncing)}}}
|
||||
:component settings-syncing/views}]
|
||||
|
||||
(when config/quo-preview-enabled?
|
||||
quo.preview/screens)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||
(def stickers-test-enabled? (enabled? (get-config :STICKERS_TEST_ENABLED "0")))
|
||||
(def local-pairing-mode-enabled? (enabled? (get-config :LOCAL_PAIRING_ENABLED "1")))
|
||||
|
||||
;; CONFIG VALUES
|
||||
(def log-level (string/upper-case (get-config :LOG_LEVEL "")))
|
||||
|
@ -138,3 +139,7 @@
|
|||
|
||||
;;TODO for development only should be removed in status 2.0
|
||||
(def new-ui-enabled? true)
|
||||
|
||||
;; TODO: Remove this (highly) temporary flag once the new Activity Center is
|
||||
;; usable enough to replace the old one **in the new UI**.
|
||||
(def new-activity-center-enabled? true)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[i18n.i18n :as i18n]
|
||||
|
||||
status-im2.setup.events
|
||||
status-im2.contexts.syncing.events
|
||||
status-im2.subs.root
|
||||
status-im2.navigation.core
|
||||
|
||||
|
|
|
@ -1894,5 +1894,20 @@
|
|||
"unmute-group": "Unmute group",
|
||||
"remove-user-from-group": "Remove {{username}} from the group",
|
||||
"edit-name-image": "Edit name and image",
|
||||
"owner": "Owner"
|
||||
"owner": "Owner",
|
||||
"local-pairing-experimental-mode": "Local Pairing Mode (alpha)",
|
||||
"syncing": "Syncing",
|
||||
"synced-devices": "Synced Devices",
|
||||
"sync-new-device": "Sync a new device",
|
||||
"sync-instructions-text": "You own your data. Synchronize it among all your devices.",
|
||||
"sync-instruction-step-1": "1. Verify login with password",
|
||||
"sync-instruction-step-2": "2. Reveal a temporary QR and Sync Code",
|
||||
"sync-instruction-step-3": "3. Share that info with your new device",
|
||||
"setup-syncing": "Setup Syncing",
|
||||
"sync-code-generated": "Sync code generated",
|
||||
"generate-scan-sync-code": "Generate Scan Sync Code",
|
||||
"try-your-luck-again": "Try your luck again!",
|
||||
"instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”",
|
||||
"show-existing-keys": "Show Existing Keys",
|
||||
"scan-sync-code": "Scan Sync Code"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue