From a502da6ea43964f485e99e56c86a962da260a05a Mon Sep 17 00:00:00 2001 From: Jamie Caprani Date: Wed, 22 Mar 2023 13:51:38 +0000 Subject: [PATCH] https://github.com/status-im/status-go/compare/9c1c01c6...48eb7052 (#15401) feat: add create profile to onboarding --- .../status/ethereum/module/StatusModule.java | 33 +++++ .../ios/RCTStatus/RCTStatus.m | 35 +++++ .../avatars/user_avatar/component_spec.cljs | 12 ++ .../components/avatars/user_avatar/view.cljs | 14 +- .../components/inputs/profile_input/view.cljs | 17 +-- .../components/inputs/title_input/style.cljs | 6 +- .../components/inputs/title_input/view.cljs | 5 +- src/quo2/foundations/colors.cljs | 6 +- src/status_im/multiaccounts/login/core.cljs | 8 +- src/status_im/native_module/core.cljs | 16 +++ .../ui/screens/multiaccounts/sheets.cljs | 2 +- src/status_im2/constants.cljs | 3 + .../onboarding/create_password/view.cljs | 5 +- .../onboarding/create_profile/style.cljs | 10 ++ .../onboarding/create_profile/view.cljs | 124 +++++++++++++++--- .../onboarding/enable_biometrics/view.cljs | 2 +- .../onboarding/enable_notifications/view.cljs | 2 +- .../contexts/onboarding/events.cljs | 64 ++++++++- .../onboarding/generating_keys/style.cljs | 14 ++ .../onboarding/generating_keys/view.cljs | 30 +++++ .../contexts/onboarding/profiles/view.cljs | 2 +- .../select_photo/method_menu/view.cljs | 71 ++++++++++ src/status_im2/events.cljs | 1 + src/status_im2/navigation/screens.cljs | 27 +++- src/status_im2/subs/root.cljs | 4 + status-go-version.json | 6 +- translations/en.json | 8 ++ 27 files changed, 473 insertions(+), 54 deletions(-) create mode 100644 src/status_im2/contexts/onboarding/generating_keys/style.cljs create mode 100644 src/status_im2/contexts/onboarding/generating_keys/view.cljs create mode 100644 src/status_im2/contexts/onboarding/select_photo/method_menu/view.cljs diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index 2b3d7f3237..1967508809 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -323,6 +323,20 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL callback.invoke(finalConfig); } + @ReactMethod + public void createAccountAndLogin(final String createAccountRequest) { + Log.d(TAG, "createAccountAndLogin"); + String result = Statusgo.createAccountAndLogin(createAccountRequest); + if (result.startsWith("{\"error\":\"\"")) { + Log.d(TAG, "createAccountAndLogin success: " + result); + Log.d(TAG, "Geth node started"); + } else { + Log.e(TAG, "createAccountAndLogin failed: " + result); + } + } + + + @ReactMethod public void saveAccountAndLogin(final String multiaccountData, final String password, final String settings, final String config, final String accountsData) { try { @@ -520,6 +534,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL return; } + Log.d(TAG, "[Opening accounts" + rootDir); + Runnable r = new Runnable() { @Override public void run() { @@ -1129,6 +1145,23 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL executeRunnableStatusGoMethod(() -> Statusgo.deleteImportedKey(address, password, keyStoreDir), callback); } + @ReactMethod(isBlockingSynchronousMethod = true) + public String keystoreDir() { + final String absRootDirPath = this.getNoBackupDirectory(); + return pathCombine(absRootDirPath, "keystore"); + } + + @ReactMethod(isBlockingSynchronousMethod = true) + public String backupDisabledDataDir() { + return this.getNoBackupDirectory(); + } + + + @ReactMethod(isBlockingSynchronousMethod = true) + public String logFilePath() { + return getLogsFile().getAbsolutePath(); + } + @ReactMethod(isBlockingSynchronousMethod = true) public String generateAlias(final String seed) { return Statusgo.generateAlias(seed); diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index f57b5e3898..794eb2cb98 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -857,6 +857,34 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(generateAlias:(NSString *)publicKey) { return StatusgoGenerateAlias(publicKey); } +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(keystoreDir) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *rootUrl =[[fileManager + URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] + lastObject]; + + NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; + + return commonKeystoreDir.path; +} + + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(backupDisabledDataDir) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *rootUrl =[[fileManager + URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] + lastObject]; + return rootUrl.path; +} + +RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(logFilePath) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *rootUrl =[[fileManager + URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] + lastObject]; + return rootUrl.path; +} + RCT_EXPORT_METHOD(generateAliasAsync:(NSString *)publicKey callback:(RCTResponseSenderBlock)callback) { #if DEBUG @@ -934,6 +962,13 @@ RCT_EXPORT_METHOD(identiconAsync:(NSString *)publicKey callback(@[result]); } +RCT_EXPORT_METHOD(createAccountAndLogin:(NSString *)request) { +#if DEBUG + NSLog(@"createAccountAndLogin() method called"); +#endif + StatusgoCreateAccountAndLogin(request); +} + RCT_EXPORT_METHOD(generateAliasAndIdenticonAsync:(NSString *)publicKey callback:(RCTResponseSenderBlock)callback) { #if DEBUG diff --git a/src/quo2/components/avatars/user_avatar/component_spec.cljs b/src/quo2/components/avatars/user_avatar/component_spec.cljs index a8aec064b0..5f983b2264 100644 --- a/src/quo2/components/avatars/user_avatar/component_spec.cljs +++ b/src/quo2/components/avatars/user_avatar/component_spec.cljs @@ -58,6 +58,18 @@ (h/test "Size :small" (h/render (user-avatar-component :small)) + (h/is-truthy (h/get-by-text "NU"))) + + (h/test "Two letters with excess whitespace" + (h/render [user-avatar/user-avatar + {:full-name "New User" + :size :big}]) + (h/is-truthy (h/get-by-text "NU"))) + + (h/test "Two letters with leading whitespace" + (h/render [user-avatar/user-avatar + {:full-name " New User" + :size :big}]) (h/is-truthy (h/get-by-text "NU")))) (h/describe "One letter" diff --git a/src/quo2/components/avatars/user_avatar/view.cljs b/src/quo2/components/avatars/user_avatar/view.cljs index 37658ef1e6..8c0232cc4c 100644 --- a/src/quo2/components/avatars/user_avatar/view.cljs +++ b/src/quo2/components/avatars/user_avatar/view.cljs @@ -5,14 +5,18 @@ [react-native.core :as rn] [react-native.fast-image :as fast-image])) +(defn trim-whitespace [s] (string/join " " (string/split (string/trim s) #"\s+"))) + (defn- extract-initials [full-name amount-initials] (let [upper-case-first-letter (comp string/upper-case first) - names-list (string/split full-name " ")] - (->> names-list - (map upper-case-first-letter) - (take amount-initials) - (string/join)))) + names-list (string/split (trim-whitespace full-name) " ")] + (if (= (first names-list) "") + "" + (->> names-list + (map upper-case-first-letter) + (take amount-initials) + (string/join))))) (defn initials-avatar [{:keys [full-name size draw-ring? customization-color]}] diff --git a/src/quo2/components/inputs/profile_input/view.cljs b/src/quo2/components/inputs/profile_input/view.cljs index a904527ea0..f92f61a373 100644 --- a/src/quo2/components/inputs/profile_input/view.cljs +++ b/src/quo2/components/inputs/profile_input/view.cljs @@ -25,13 +25,13 @@ :height 24 :borderRadius 12}]} [user-avatar/user-avatar - (merge image-picker-props - {:customization-color customization-color - :full-name (if (seq full-name) - full-name - placeholder) - :status-indicator? false - :size :medium})]] + (assoc image-picker-props + :customization-color customization-color + :full-name (if (seq full-name) + full-name + placeholder) + :status-indicator? false + :size :medium)]] [buttons/button {:accessibility-label :select-profile-picture-button :type :grey @@ -47,5 +47,6 @@ [rn/view {:style style/input-container} [title-input/title-input (merge title-input-props - {:placeholder placeholder + {:override-theme :dark + :placeholder placeholder :customization-color customization-color})]]])) diff --git a/src/quo2/components/inputs/title_input/style.cljs b/src/quo2/components/inputs/title_input/style.cljs index f8788334c5..0209098625 100644 --- a/src/quo2/components/inputs/title_input/style.cljs +++ b/src/quo2/components/inputs/title_input/style.cljs @@ -34,9 +34,11 @@ (def text-input-container {:flex 1}) (defn title-text - [disabled? blur?] + [disabled? blur? override-theme] {:text-align-vertical :bottom - :color (when disabled? (get-disabled-color blur?))}) + :color (if disabled? + (get-disabled-color blur?) + (colors/theme-colors colors/neutral-100 colors/white override-theme))}) (defn char-count [blur?] diff --git a/src/quo2/components/inputs/title_input/view.cljs b/src/quo2/components/inputs/title_input/view.cljs index 763e0bc20b..930cde3a92 100644 --- a/src/quo2/components/inputs/title_input/view.cljs +++ b/src/quo2/components/inputs/title_input/view.cljs @@ -16,7 +16,8 @@ on-change-text placeholder max-length - default-value] + default-value + override-theme] :or {max-length 0 default-value ""}}] (let [focused? (reagent/atom false) @@ -34,7 +35,7 @@ (text/text-style {:size :heading-2 :weight :semi-bold - :style (style/title-text disabled? blur?)}) + :style (style/title-text disabled? blur? override-theme)}) :default-value default-value :accessibility-label :profile-title-input :on-focus #(swap! focused? (fn [] true)) diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs index 59e337b9c9..078b8dce37 100644 --- a/src/quo2/foundations/colors.cljs +++ b/src/quo2/foundations/colors.cljs @@ -237,7 +237,11 @@ ([color suffix] (custom-color color suffix nil)) ([color suffix opacity] - (let [base-color (get-in colors-map [(keyword color) suffix])] + (let [color-keyword (keyword color) + base-color (get-in colors-map + [(if (= color-keyword :yinyang) + (if (theme/dark?) :yang :yin) + (keyword color)) suffix])] (if opacity (alpha base-color (/ opacity 100)) base-color)))))) (defn custom-color-by-theme diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index b6c1b71b99..59759f652b 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -479,8 +479,14 @@ (defn redirect-to-root "Decides which root should be initialised depending on user and app state" [db] - (if (get db :tos/accepted?) + (cond + (get db :onboarding-2/new-account?) + (re-frame/dispatch [:navigate-to :enable-notifications]) + + (get db :tos/accepted?) (re-frame/dispatch [:init-root :shell-stack]) + + :else (re-frame/dispatch [:init-root :tos]))) (rf/defn login-only-events diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index d671e524a0..a16fc46280 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -91,6 +91,10 @@ key-uid #(.loginWithConfig ^js (status) account-data hashed-password config)))) +(defn create-account-and-login + [request] + (.createAccountAndLogin ^js (status) (types/clj->json request))) + (defn export-db "NOTE: beware, the password has to be sha3 hashed" [key-uid account-data hashed-password callback] @@ -611,3 +615,15 @@ current-password# new-password callback)) + +(defn backup-disabled-data-dir + [] + (.backupDisabledDataDir ^js (status))) + +(defn keystore-dir + [] + (.keystoreDir ^js (status))) + +(defn log-file-path + [] + (.logFilePath ^js (status))) diff --git a/src/status_im/ui/screens/multiaccounts/sheets.cljs b/src/status_im/ui/screens/multiaccounts/sheets.cljs index 9b80647ab8..3963b508ee 100644 --- a/src/status_im/ui/screens/multiaccounts/sheets.cljs +++ b/src/status_im/ui/screens/multiaccounts/sheets.cljs @@ -12,7 +12,7 @@ [] [quo/list-item {:theme :accent - :on-press #(hide-sheet-and-dispatch [:generate-and-derive-addresses]) + :on-press #(hide-sheet-and-dispatch [:navigate-to :intro]) :icon :main-icons/add :accessibility-label :generate-a-new-key :title (i18n/label :t/generate-a-new-key)}]) diff --git a/src/status_im2/constants.cljs b/src/status_im2/constants.cljs index 7ca5eb8188..0cf3b516f5 100644 --- a/src/status_im2/constants.cljs +++ b/src/status_im2/constants.cljs @@ -90,6 +90,9 @@ (def ^:const command-state-transaction-pending 6) (def ^:const command-state-transaction-sent 7) +(def ^:const profile-default-color :blue) +(def ^:const profile-name-max-length 24) + (def ^:const profile-pictures-show-to-contacts-only 1) (def ^:const profile-pictures-show-to-everyone 2) (def ^:const profile-pictures-show-to-none 3) diff --git a/src/status_im2/contexts/onboarding/create_password/view.cljs b/src/status_im2/contexts/onboarding/create_password/view.cljs index b1feca6751..1d22aa4f27 100644 --- a/src/status_im2/contexts/onboarding/create_password/view.cljs +++ b/src/status_im2/contexts/onboarding/create_password/view.cljs @@ -4,6 +4,7 @@ [react-native.core :as rn] [status-im2.contexts.onboarding.create-password.style :as style] [utils.i18n :as i18n] + [utils.security.core :as security] [status-im2.contexts.onboarding.common.background.view :as background] [utils.re-frame :as rf])) @@ -32,7 +33,9 @@ :weight :semi-bold :style {:color colors/white}} "Create profile password"] [quo/button - {:on-press #(rf/dispatch [:navigate-to :enable-biometrics]) + {:on-press #(rf/dispatch + [:onboarding-2/password-set + (security/mask-data "test123")]) :style {}} (i18n/label :t/continue)]]]) (defn create-password diff --git a/src/status_im2/contexts/onboarding/create_profile/style.cljs b/src/status_im2/contexts/onboarding/create_profile/style.cljs index a1146a7a33..ceb643d09f 100644 --- a/src/status_im2/contexts/onboarding/create_profile/style.cljs +++ b/src/status_im2/contexts/onboarding/create_profile/style.cljs @@ -2,6 +2,14 @@ (:require [quo2.foundations.colors :as colors] [react-native.platform :as platform])) +(def continue-button + {:width "100%" + :margin-top :auto + :margin-bottom 72 + :margin-left :auto + :margin-right :auto + :align-self :flex-end}) + (def page-container {:padding-top (if platform/ios? 44 0) :position :absolute @@ -13,3 +21,5 @@ (def navigation-bar {:height 56}) +(def info-message + {:margin-top 8}) diff --git a/src/status_im2/contexts/onboarding/create_profile/view.cljs b/src/status_im2/contexts/onboarding/create_profile/view.cljs index d52b7ea3f1..233296aa2e 100644 --- a/src/status_im2/contexts/onboarding/create_profile/view.cljs +++ b/src/status_im2/contexts/onboarding/create_profile/view.cljs @@ -1,11 +1,15 @@ (ns status-im2.contexts.onboarding.create-profile.view - (:require [quo2.core :as quo] - [quo2.foundations.colors :as colors] - [react-native.core :as rn] - [status-im2.contexts.onboarding.create-profile.style :as style] + (:require [clojure.string :as string] [utils.i18n :as i18n] + [quo2.core :as quo] + [quo2.foundations.colors :as colors] + [status-im2.contexts.onboarding.create-profile.style :as style] + [react-native.core :as rn] + [reagent.core :as reagent] [status-im2.contexts.onboarding.common.background.view :as background] - [utils.re-frame :as rf])) + [status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu] + [utils.re-frame :as rf] + [status-im2.constants :as c])) (defn navigation-bar [] @@ -18,21 +22,105 @@ :icon-override-theme :dark :on-press #(rf/dispatch [:navigate-back])}}]]) +(def emoji-regex + (new + js/RegExp + #"(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])" + "i")) +(defn has-emojis [s] (re-find emoji-regex s)) +(def common-names ["Ethereum" "Bitcoin"]) +(defn has-common-names [s] (pos? (count (filter #(string/includes? s %) common-names)))) +(def special-characters-regex (new js/RegExp #"[^a-zA-Z\d\s-]" "i")) +(defn has-special-characters [s] (re-find special-characters-regex s)) + +(defn validation-message + [s] + (cond + (or (= s nil) (= s "")) nil + (has-emojis s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)}) + (has-special-characters s) (i18n/label :t/are-not-allowed + {:check (i18n/label :t/special-characters)}) + (string/ends-with? s "-eth") (i18n/label :t/ending-not-allowed {:ending "-eth"}) + (has-common-names s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/common-names)}) + :else nil)) + (defn page - [] - [rn/view {:style style/page-container} - [navigation-bar] - [rn/view {:style {:padding-horizontal 20}} - [quo/text - {:size :heading-1 - :weight :semi-bold - :style {:color colors/white}} "Create Profile"] - [quo/button - {:on-press #(rf/dispatch [:navigate-to :create-profile-password]) - :style {}} (i18n/label :t/continue)]]]) + [{:keys [image-path display-name color]}] + (let [full-name (reagent/atom display-name) + validation-msg (reagent/atom (validation-message @full-name)) + on-change-text (fn [s] + (reset! validation-msg (validation-message s)) + + (reset! full-name s)) + custom-color (reagent/atom (or color c/profile-default-color)) + profile-pic (reagent/atom image-path) + on-change-profile-pic #(reset! profile-pic %) + on-change #(reset! custom-color %)] + (fn [] + [rn/view {:style style/page-container} + [navigation-bar] + [rn/view + {:style {:flex 1 + :padding-horizontal 20}} + [quo/text + {:size :heading-1 + :weight :semi-bold + :style {:color colors/white + :margin-top 12 + :margin-bottom 20}} (i18n/label :t/create-profile)] + [rn/view + {:flex 1 + :align-items :flex-start} + + [rn/view + {:flex-direction :row + :justify-content :center} + [quo/profile-input + {:customization-color @custom-color + :placeholder (i18n/label :t/your-name) + :on-press #(rf/dispatch + [:bottom-sheet/show-sheet + {:override-theme :dark + :content + (fn [] + [method-menu/view on-change-profile-pic])}]) + :image-picker-props {:profile-picture @profile-pic + :full-name @full-name} + :title-input-props {:max-length c/profile-name-max-length + :on-change-text on-change-text}}]] + (when @validation-msg + [quo/info-message + {:type :error + :size :default + :icon :i/info + :style style/info-message} + @validation-msg]) + [quo/text + {:size :paragraph-2 + :style {:color colors/white-70-blur + :margin-top 20 + :margin-bottom 16}} (i18n/label :t/accent-colour)] + [quo/color-picker + {:blur? true + :default-selected? :blue + :selected @custom-color + :on-change on-change}]] + [quo/button + {:accessibility-label :submit-create-profile-button + :type :primary + :override-theme :dark + :override-background-color (colors/custom-color @custom-color 50) + :on-press #(rf/dispatch [:onboarding-2/profile-data-set + {:image-path @profile-pic + :display-name @full-name + :color @custom-color}]) + :style style/continue-button + :disabled (and (not (seq @full-name)) (not @validation-msg))} + (i18n/label :t/continue)]]]))) (defn create-profile [] [rn/view {:style {:flex 1}} - [background/view true] - [page]]) + (let [onboarding-profile-data (rf/sub [:onboarding-2/profile])] + [background/view true] + [page onboarding-profile-data])]) diff --git a/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs b/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs index ddc9948122..689d394469 100644 --- a/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs +++ b/src/status_im2/contexts/onboarding/enable_biometrics/view.cljs @@ -25,7 +25,7 @@ :weight :semi-bold :style {:color colors/white}} "Enable-biometrics"] [quo/button - {:on-press #(rf/dispatch [:navigate-to :enable-notifications]) + {:on-press #(rf/dispatch [:onboarding-2/create-account-and-login]) :type :grey :override-theme :dark :style {}} (i18n/label :t/continue)]]]) diff --git a/src/status_im2/contexts/onboarding/enable_notifications/view.cljs b/src/status_im2/contexts/onboarding/enable_notifications/view.cljs index 72b4bf359f..aa631ac6fd 100644 --- a/src/status_im2/contexts/onboarding/enable_notifications/view.cljs +++ b/src/status_im2/contexts/onboarding/enable_notifications/view.cljs @@ -25,7 +25,7 @@ :weight :semi-bold :style {:color colors/white}} "Enable-notifications"] [quo/button - {:on-press #(rf/dispatch [:navigate-to :shell-stack]) + {:on-press #(rf/dispatch [:init-root :shell-stack]) :type :grey :override-theme :dark :style {}} (i18n/label :t/continue)]]]) diff --git a/src/status_im2/contexts/onboarding/events.cljs b/src/status_im2/contexts/onboarding/events.cljs index c7ee11ae44..660a0913d1 100644 --- a/src/status_im2/contexts/onboarding/events.cljs +++ b/src/status_im2/contexts/onboarding/events.cljs @@ -1,7 +1,67 @@ (ns status-im2.contexts.onboarding.events - (:require [utils.re-frame :as rf])) + (:require + [utils.re-frame :as rf] + [re-frame.core :as re-frame] + [status-im2.config :as config] + [clojure.string :as string] + [utils.security.core :as security] + [status-im.native-module.core :as status] + [status-im.ethereum.core :as ethereum])) + +(re-frame/reg-fx + ::create-account-and-login + (fn [request] + (status/create-account-and-login request))) (rf/defn on-delete-profile-success - {:events [:onboarding/on-delete-profile-success]} + {:events [:onboarding-2/on-delete-profile-success]} [{:keys [db]} key-uid] {:db (update-in db [:multiaccounts/multiaccounts] dissoc key-uid)}) + +(rf/defn profile-data-set + {:events [:onboarding-2/profile-data-set]} + [{:keys [db]} onboarding-data] + {:db (assoc db :onboarding-2/profile onboarding-data) + :dispatch [:navigate-to :create-profile-password]}) + +(rf/defn password-set + {:events [:onboarding-2/password-set]} + [{:keys [db]} password] + {:db (assoc-in db [:onboarding-2/profile :password] password) + :dispatch [:navigate-to :enable-biometrics]}) + +(defn strip-file-prefix + [path] + (when path + (string/replace-first path "file://" ""))) + +(rf/defn create-account-and-login + {:events [:onboarding-2/create-account-and-login]} + [{:keys [db]}] + (let [{:keys [display-name + password + image-path + color]} (:onboarding-2/profile db) + log-enabled? (boolean (not-empty config/log-level)) + request {:displayName display-name + :password (ethereum/sha3 (security/safe-unmask-data password)) + :imagePath (strip-file-prefix image-path) + :color color + :backupDisabledDataDir (status/backup-disabled-data-dir) + :rootKeystoreDir (status/keystore-dir) + ;; Temporary fix until https://github.com/status-im/status-go/issues/3024 is + ;; resolved + :wakuV2Nameserver "1.1.1.1" + :logLevel (when log-enabled? config/log-level) + :logEnabled log-enabled? + :logFilePath (status/log-file-path) + :openseaAPIKey config/opensea-api-key + :verifyTransactionURL config/verify-transaction-url + :verifyENSURL config/verify-ens-url + :verifyENSContractAddress config/verify-ens-contract-address + :verifyTransactionChainID config/verify-transaction-chain-id}] + {::create-account-and-login request + :dispatch [:navigate-to :generating-keys] + :db (-> db + (dissoc :onboarding-2/profile) + (assoc :onboarding-2/new-account? true))})) diff --git a/src/status_im2/contexts/onboarding/generating_keys/style.cljs b/src/status_im2/contexts/onboarding/generating_keys/style.cljs new file mode 100644 index 0000000000..8f69954fd6 --- /dev/null +++ b/src/status_im2/contexts/onboarding/generating_keys/style.cljs @@ -0,0 +1,14 @@ +(ns status-im2.contexts.onboarding.generating-keys.style + (:require [quo2.foundations.colors :as colors] + [react-native.platform :as platform])) + +(def page-container + {:padding-top (if platform/ios? 44 0) + :position :absolute + :top 0 + :bottom 0 + :left 0 + :right 0 + :background-color colors/neutral-80-opa-80-blur}) + +(def navigation-bar {:height 56}) diff --git a/src/status_im2/contexts/onboarding/generating_keys/view.cljs b/src/status_im2/contexts/onboarding/generating_keys/view.cljs new file mode 100644 index 0000000000..43edaa8e86 --- /dev/null +++ b/src/status_im2/contexts/onboarding/generating_keys/view.cljs @@ -0,0 +1,30 @@ +(ns status-im2.contexts.onboarding.generating-keys.view + (:require [quo2.core :as quo] + [quo2.foundations.colors :as colors] + [react-native.core :as rn] + [status-im2.contexts.onboarding.generating-keys.style :as style] + [status-im2.contexts.onboarding.common.background.view :as background] + [utils.i18n :as i18n])) + +(defn navigation-bar + [] + [rn/view {:style style/navigation-bar} + [quo/page-nav + {:align-mid? true + :mid-section {:type :text-only :main-text ""}}]]) + +(defn page + [] + [rn/view {:style style/page-container} + [navigation-bar] + [rn/view {:style {:padding-horizontal 20}} + [quo/text + {:size :heading-1 + :weight :semi-bold + :style {:color colors/white}} (i18n/label :t/generating-keys)]]]) + +(defn generating-keys + [] + [rn/view {:style {:flex 1}} + [background/view true] + [page]]) diff --git a/src/status_im2/contexts/onboarding/profiles/view.cljs b/src/status_im2/contexts/onboarding/profiles/view.cljs index ca103eaec0..10a875d08c 100644 --- a/src/status_im2/contexts/onboarding/profiles/view.cljs +++ b/src/status_im2/contexts/onboarding/profiles/view.cljs @@ -54,7 +54,7 @@ key-uid (fn [result] (let [{:keys [error]} (types/json->clj result)] - (rf/dispatch [:onboarding/on-delete-profile-success key-uid]) + (rf/dispatch [:onboarding-2/on-delete-profile-success key-uid]) (log/info "profile deleted: error" error)))))})) (defn show-confirmation diff --git a/src/status_im2/contexts/onboarding/select_photo/method_menu/view.cljs b/src/status_im2/contexts/onboarding/select_photo/method_menu/view.cljs new file mode 100644 index 0000000000..bcb3082d20 --- /dev/null +++ b/src/status_im2/contexts/onboarding/select_photo/method_menu/view.cljs @@ -0,0 +1,71 @@ +(ns status-im2.contexts.onboarding.select-photo.method-menu.view + (:require + [quo2.core :as quo] + [utils.i18n :as i18n] + ["react-native-image-crop-picker" :default image-picker] + [status-im.multiaccounts.core] + [utils.re-frame :as rf])) + +(def crop-size 1000) + +(def crop-opts + {:cropping true + :cropperCircleOverlay true + :width crop-size + :height crop-size}) + +(defn show-access-error + [o] + (when (= "E_PERMISSION_MISSING" (.-code ^js o)) + (js/console.log (i18n/label :t/error)))) + +(defn show-image-picker + ([images-fn] + (show-image-picker images-fn nil)) + ([images-fn + {:keys [media-type] + :or {media-type "any"} + :as props}] + (-> ^js image-picker + (.openPicker (clj->js (merge {:mediaType media-type} + props))) + (.then images-fn) + (.catch show-access-error)))) + +(defn show-image-picker-camera + ([images-fn] + (show-image-picker-camera images-fn nil)) + ([images-fn props] + + (-> ^js image-picker + (.openCamera (clj->js props)) + (.then images-fn) + (.catch show-access-error)))) + +(defn pick-pic + [update-profile-pic-callback] + (rf/dispatch [:bottom-sheet/hide]) + (show-image-picker + #(update-profile-pic-callback (.-path ^js %)) + crop-opts)) + +(defn take-pic + [update-profile-pic-callback] + (rf/dispatch [:bottom-sheet/hide]) + (show-image-picker-camera + #(update-profile-pic-callback (.-path ^js %)) + crop-opts)) + +(defn view + [update-profile-pic-callback] + [quo/action-drawer + [[{:icon :i/camera + :accessibility-label :take-photo-button + :label (i18n/label :t/profile-pic-take) + :override-theme :dark + :on-press #(take-pic update-profile-pic-callback)} + {:icon :i/image + :override-theme :dark + :accessibility-label :select-from-gallery-button + :label (i18n/label :t/profile-pic-pick) + :on-press #(pick-pic update-profile-pic-callback)}]]]) diff --git a/src/status_im2/events.cljs b/src/status_im2/events.cljs index 77bdbc59a4..ecf8faa74c 100644 --- a/src/status_im2/events.cljs +++ b/src/status_im2/events.cljs @@ -10,6 +10,7 @@ [status-im2.common.theme.core :as theme] [status-im2.common.toasts.events] [status-im2.contexts.add-new-contact.events] + status-im2.contexts.onboarding.events [status-im2.common.bottom-sheet.events] [status-im2.navigation.events :as navigation] [status-im2.db :as db] diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index b108601388..57007323a2 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -21,6 +21,7 @@ [status-im2.contexts.onboarding.new-to-status.view :as new-to-status] [status-im2.contexts.onboarding.sign-in.view :as sign-in] [status-im2.contexts.onboarding.syncing.syncing-devices.view :as syncing-devices] + [status-im2.contexts.onboarding.generating-keys.view :as generating-keys] [status-im2.contexts.onboarding.profiles.view :as profiles] [status-im2.contexts.quo-preview.main :as quo.preview] [status-im2.contexts.shell.view :as shell] @@ -37,10 +38,9 @@ :orientation :portrait :backgroundColor :transparent}} (if platform/android? - {:navigationBar {:backgroundColor colors/neutral-100} - :statusBar {:backgroundColor :transparent - :style :light - :drawBehind true}} + {:statusBar {:backgroundColor :transparent + :style :light + :drawBehind true}} {:statusBar {:style :light}}))) (def bottom-sheet-options @@ -129,9 +129,14 @@ ;; Onboarding - new to Status {:name :new-to-status - :options {:statusBar {:style :light} - :topBar {:visible false} - :navigationBar {:backgroundColor colors/black}} + :options {:statusBar {:style :light} + :topBar {:visible false}} + :insets {:top false} + :component new-to-status/new-to-status} + + {:name :create-profile + :options {:statusBar {:style :light} + :topBar {:visible false}} :insets {:top false} :component new-to-status/new-to-status} @@ -156,6 +161,14 @@ :insets {:top false} :component enable-biometrics/enable-biometrics} + {:name :generating-keys + :options {:statusBar {:style :light} + :topBar {:visible false} + :navigationBar {:backgroundColor colors/black}} + :insets {:top false} + :component generating-keys/generating-keys} + + {:name :enable-notifications :options {:statusBar {:style :light} :topBar {:visible false} diff --git a/src/status_im2/subs/root.cljs b/src/status_im2/subs/root.cljs index 0db8d4e438..0e570fbf41 100644 --- a/src/status_im2/subs/root.cljs +++ b/src/status_im2/subs/root.cljs @@ -268,6 +268,10 @@ ; media-server (reg-root-key-sub :mediaserver/port :mediaserver/port) +; onboarding + +(reg-root-key-sub :onboarding-2/profile :onboarding-2/profile) + ; Testing (reg-root-key-sub :messenger/started? :messenger/started?) diff --git a/status-go-version.json b/status-go-version.json index 708cb1a686..540c7c2a73 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -3,7 +3,7 @@ "_comment": "Instead use: scripts/update-status-go.sh ", "owner": "status-im", "repo": "status-go", - "version": "v0.139.0", - "commit-sha1": "9c1c01c66f652ad6ce6fd4bbfbc613cc7a292878", - "src-sha256": "15cbbzir3bddgdbrrc9pnwdrsahn7a2ihaab7mfz93r0dg3q110i" + "version": "v0.139.1", + "commit-sha1": "48eb7052848a17ab7f972112a3653f0b4cc8537a", + "src-sha256": "0ipmjs6kmdpzyqrxw3nmrzpcmw478mnn1kv97i8khsvfvldlsjga" } diff --git a/translations/en.json b/translations/en.json index 355de0574e..dc21666a5c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -4,6 +4,7 @@ "about-key-storage-title": "About key storage", "about-names-content": "No one can pretend to be you! You’re anonymous by default and never have to reveal your real name. You can register a custom name for a small fee.", "about-names-title": "Names can’t be changed", + "accent-colour": "Accent colour", "access-key": "Access key", "access-existing-keys": "Access existing keys", "accept-and-share-address": "Accept and share address", @@ -49,6 +50,7 @@ "allowing-authorizes-this-dapp": "Allowing authorizes this DApp to retrieve your wallet address and enable Web3", "already-have-asset": "You already have this asset", "amount": "Amount", + "are-not-allowed": "{{check} are not allowed", "are-you-sure-description": "You will not be able to see the whole seed phrase again", "are-you-sure?": "Are you sure?", "ask-in-status": "Ask a question or report a bug", @@ -170,6 +172,7 @@ "close-app-content": "The app will stop and close. When you reopen it, the selected network will be used", "close-app-title": "Warning!", "command-button-send": "Send", + "common-names": "Common names", "communities": "Communities", "community-members": { "one": "{{count}} member", @@ -286,6 +289,7 @@ "counter-9-plus": "9+", "counter-99-plus": "99+", "create": "Create", + "create-profile": "Create profile", "create-a-pin": "Create a 6-digit passcode", "create-a-puk": "Create a 12-digit PUK", "create-group-chat": "Create group chat", @@ -473,6 +477,7 @@ "edit": "Edit", "edit-group": "Edit group", "edit-profile": "Edit profile", + "emojis": "Emojis", "empty-chat-description": "There are no messages \nin this chat yet", "empty-chat-description-one-to-one": "Any messages you send here are encrypted and can only be read by you and ", "empty-chat-description-public": "It's been quiet here for the last {{quiet-hours}}. Start the conversation or ", @@ -481,6 +486,7 @@ "empty-chat-description-public-share-this": "share this chat.", "enable": "Enable", "encrypt-with-password": "Encrypt with password", + "ending-not-allowed": "{{ending}} ending is not allowed", "ens-10-SNT": "10 SNT", "ens-add-username": "Add username", "ens-agree-to": "Agree to ", @@ -1242,6 +1248,7 @@ "signing-phrase": "Signing phrase", "something-went-wrong": "Something went wrong", "soon": "Soon", + "special-characters": "Special characters", "specify-address": "Specify address", "specify-name": "Specify a name", "specify-symbol": "Specify a symbol", @@ -1473,6 +1480,7 @@ "your-contact-code": "Granting access authorizes this DApp to retrieve your chat key", "your-data-belongs-to-you": "If you lose your seed phrase you lose your data and funds", "your-data-belongs-to-you-description": "If you lose access, for example by losing your phone, you can only access your keys with your seed phrase. No one, but you has your seed phrase. Write it down. Keep it safe", + "your-name": "Your Name", "your-recovery-phrase": "Your seed phrase", "your-recovery-phrase-description": "This is your seed phrase. You use it to prove that this is your wallet. You only get to see it once! Write it on paper and keep it in a secure place. You will need it if you lose or reinstall your wallet.", "custom-seed-phrase": "Invalid seed phrase",