Compare commits

..
Author SHA1 Message Date
Parvesh Monu cb15e503d5 fix status bar color 2023-04-06 19:26:14 +05:30
Siddarth Kumar 35ff3a4eca fix chat layout breaking when combining normal text with code blocks (#15585) 2023-04-05 16:49:02 +01:00
Omar Basem 0168ab6baf fix: images 1.22 (#15576)
Author: Omar Basem <omarbasem.0101@gmail.com>
2023-04-05 15:48:34 +05:30
Omar Basem 5ca5c5f2bb fix: image desktop (#15562)
* fix: image desktop not opening
2023-04-03 20:20:16 +05:30
Parvesh Monu 5e9ceec65f fix create profile issues (#15561) 2023-04-03 19:50:31 +05:30
Brian Sztamfater 05d616e417 fix: add min 5 characters validation for display names
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-04-03 19:48:07 +05:30
jakub 3e756ce897 Revert "set signing to auto for debug builds (#15420)"
This reverts commit 3f3cbe98a4.
2023-04-03 09:50:20 +01:00
Andrea Maria Piana 7c362cd246 Use right version 2023-04-03 09:48:36 +01:00
John Ngei 12552c9491 Update communities discover screen
* Fix: discover communities missing data

* made community tags scrollable
2023-03-31 13:45:34 +01:00
Andrea Maria Piana 9cdbf41d74 Bump version to 0.142.5 2023-03-31 13:45:07 +01:00
Andrea Maria Piana 8b05a551d9 Bump release to 1.23.0 2023-03-30 17:30:21 +01:00
Andrea Maria Piana 6417d90e1c Bump version to 1.22.0 2023-03-30 17:30:05 +01:00
Parvesh Monu 21d409ce36 fix display name issues 2023-03-30 19:45:11 +05:30
Ibrahem Khalil d458bca193 Allow/Add mobile link previews for YouTube and Twitter (#15407) 2023-03-30 16:12:56 +02:00
Churikova Tetiana 4f2f8dea4c e2e: new onboarding 2023-03-30 15:15:42 +02:00
Andrea Maria Piana f744d761c0 Set log directory correctly
https://github.com/status-im/status-go/compare/bb6139ae...b38b3817
2023-03-30 13:54:29 +01:00
Jamie Caprani 7ad5e2181d chore: clean up ui for onboarding screens (#15470) 2023-03-30 04:05:42 -07:00
Andrea Maria Piana a10425e318 Save biometrics 2023-03-30 09:17:23 +01:00
frank 9c0ab739ea add simple validation for password, fix #15478 (#15503) 2023-03-30 08:01:22 +08:00
Omar Basem 0503f5cfc9 Image index fix (#15525)
* image index fix
2023-03-29 22:12:38 +04:00
yqrashawn a441156ff9 fix: crash on wallet view (#15502) 2023-03-29 19:50:29 +08:00
Alexanderandpavloburykh 006b11d508 Scrollable list of pinned messages (#15506)
* Scrollable list of pinned messages

* e2e: fix accessibility id

---------

Co-authored-by: pavloburykh <pavlo@status.im>
2023-03-28 20:23:30 +02:00
Parvesh Monu 8f0a990e71 fix user is not navigated to Sign in by syncing page (#15520) 2023-03-28 21:53:55 +05:30
Parvesh Monu f0ca6372cd Implement onboarding slide animation (#15489) 2023-03-28 20:57:54 +05:30
Brian Sztamfater 0f8aec00f2 Add guidelines for defining styles with apply-animations-to-style
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-03-28 11:58:06 -03:00
Roman Volosovskyi de86586208 [#15475] (issue 1) Prevent restoring of an existing multiacc 2023-03-28 12:43:48 +02:00
88 changed files with 1141 additions and 658 deletions
+1 -1
View File
@@ -1 +1 @@
1.21.0
1.22.0
+22
View File
@@ -90,6 +90,28 @@ their styles in the top-level of the properties map, prefer to add them inside t
]
```
### Always apply animated styles in the style file
When implementing styles for reanimated views, we should always define
them in the style file and apply animations with reanimated/apply-animations-to-style
in the style definition.
```clojure
;; bad
(defn circle
[]
(let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity opacity}
style/circle-container)}]))
;; good
(defn circle
[]
(let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style (style/circle-container opacity)}]))
```
### Don't use percents to define width/height
In ReactNative, all layouts use the [flexbox
+12 -6
View File
@@ -417,7 +417,9 @@
TestTargetID = 13B07F861A680F5B00A75B9A;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = 8B5X2M6H2Y;
LastSwiftMigration = 1140;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 1;
@@ -841,8 +843,9 @@
BUNDLE_ID_SUFFIX = .debug;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CUSTOM_PRODUCT_NAME = "Status Debug";
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8B5X2M6H2Y;
@@ -895,7 +898,8 @@
);
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = StatusIm;
PROVISIONING_PROFILE_SPECIFIER = "";
PROVISIONING_PROFILE = "9da75626-9594-43d9-a827-0f6d43c28f54";
PROVISIONING_PROFILE_SPECIFIER = "match Development im.status.ethereum";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -913,8 +917,9 @@
BUNDLE_ID_SUFFIX = "";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CUSTOM_PRODUCT_NAME = Status;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8B5X2M6H2Y;
@@ -959,7 +964,8 @@
);
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = StatusIm;
PROVISIONING_PROFILE_SPECIFIER = "";
PROVISIONING_PROFILE = "e2202b12-7a66-4ff7-af3c-a52e35f32dc1";
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc im.status.ethereum";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
@@ -149,11 +149,15 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
this.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("gethEvent", params);
}
private File getLogsFile() {
private File getPublicStorageDirectory() {
final Context context = this.getReactApplicationContext();
// Environment.getExternalStoragePublicDirectory doesn't work as expected on Android Q
// https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)
final File pubDirectory = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
}
private File getLogsFile() {
final File pubDirectory = this.getPublicStorageDirectory();
final File logFile = new File(pubDirectory, gethLogFileName);
return logFile;
@@ -1170,8 +1174,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
@ReactMethod(isBlockingSynchronousMethod = true)
public String logFilePath() {
return getLogsFile().getAbsolutePath();
public String logFileDirectory() {
return getPublicStorageDirectory().getAbsolutePath();
}
@ReactMethod(isBlockingSynchronousMethod = true)
@@ -882,7 +882,7 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(backupDisabledDataDir) {
return rootUrl.path;
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(logFilePath) {
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(logFileDirectory) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 MiB

+47
View File
@@ -0,0 +1,47 @@
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300;
const easeOut = {
duration: slideAnimationDuration,
easing: Easing.bezier(0, 0, 0.58, 1),
}
// Derived Values
export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
return useDerivedValue(
function () {
'worklet'
return staticProgressBarWidth * (progress.value || 0) / 100;
}
);
}
export function carouselLeftPosition(windowWidth, progress) {
return useDerivedValue(
function () {
'worklet'
const progressValue = progress.value;
switch (true) {
case (progressValue < 25):
return 0;
case (progressValue === 25):
return withTiming(-windowWidth, easeOut);
case (progressValue < 50):
return -windowWidth;
case (progressValue === 50):
return withTiming(-2 * windowWidth, easeOut);
case (progressValue < 75):
return -2 * windowWidth;
case (progressValue === 75):
return withTiming(-3 * windowWidth, easeOut);
case (progressValue < 100):
return -3 * windowWidth;
case (progressValue === 100):
return withTiming(-4 * windowWidth, easeOut);
default:
return 0;
}
});
}
+6 -1
View File
@@ -293,7 +293,10 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
:createNativeWrapper identity
:default #js {}})
(def react-native-redash #js {:clamp nil})
(def react-native-redash
#js
{:clamp nil
:withPause (fn [])})
(def react-native-languages
(clj->js {:default {:language "en"
@@ -370,6 +373,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
"react-native-screens" (clj->js {})
"react-native-reanimated" react-native-reanimated
"react-native-redash/lib/module/v1" react-native-redash
"react-native-redash" react-native-redash
"react-native-fetch-polyfill" fetch
"react-native-status-keycard" status-keycard
"react-native-keychain" keychain
@@ -407,6 +411,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
"../src/js/worklets/bottom_sheet.js" #js {}
"../src/js/worklets/record_audio.js" #js {}
"../src/js/worklets/scroll_view.js" #js {}
"../src/js/worklets/onboarding_carousel.js" #js {}
"../src/js/worklets/lightbox.js" #js {}
"./fleets.js" default-fleets
"@walletconnect/client" wallet-connect-client
@@ -16,7 +16,7 @@
:height 230
:border-radius 20}
:on-press on-press}
[rn/view {:flex 1}
[rn/view {:style style/detail-container}
[rn/view (style/community-cover-container 60)
[rn/image
{:source cover
@@ -40,4 +40,3 @@
{:type :card-view}]]
[rn/view {:style (style/community-tags-position)}
[community-view/community-tags tags]]]]]]])
@@ -46,7 +46,7 @@
(merge {:style {:height 56
:border-radius 16}}
props)
[rn/view {:flex 1}
[rn/view {:style style/detail-container}
[rn/view (style/list-info-container)
[community-icon/community-icon
{:images community-icon} 32]
@@ -5,6 +5,7 @@
[quo2.components.tags.permission-tag :as permission]
[quo2.components.tags.tag :as tag]
[quo2.foundations.colors :as colors]
[quo.gesture-handler :as gesture-handler] ;;TODO move to quo2
[react-native.core :as rn]))
(defn community-stats
@@ -41,17 +42,18 @@
(defn community-tags
[tags]
[rn/view (style/community-tags-container)
[gesture-handler/scroll-view
{:shows-horizontal-scroll-indicator false
:horizontal true}
(for [{:keys [name emoji]} tags]
^{:key name}
[rn/view {:margin-right 8}
[tag/tag
{:size 24
:label name
:type :emoji
:labelled? true
:scrollable? true
:resource emoji}]])])
{:size 24
:label name
:type :emoji
:labelled? true
:resource emoji}]])])
(defn community-title
[{:keys [title description size] :or {size :small}}]
+3 -4
View File
@@ -22,6 +22,9 @@
colors/white
colors/neutral-90)})
(def detail-container
{:flex 1})
(defn stats-count-container
[]
{:flex-direction :row
@@ -37,10 +40,6 @@
{:flex-direction :row
:align-items :center})
(defn community-tags-container
[]
{:flex-direction :row})
(defn card-stats-position
[]
{:position :absolute
@@ -1,7 +1,10 @@
(ns quo2.components.drawers.drawer-buttons.style
(:require [quo2.foundations.colors :as colors]))
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(def outer-container {:height 216})
(def outer-container
{:height 216
:border-radius 20})
(def top-card
{:flex 1
@@ -9,7 +12,9 @@
:padding-horizontal 20
:border-top-left-radius 20
:border-top-right-radius 20
:background-color colors/neutral-80})
:background-color (if platform/ios?
colors/neutral-80-opa-80-blur
colors/neutral-80)})
(def bottom-card
{:position :absolute
@@ -21,7 +26,7 @@
:padding-horizontal 20
:border-top-left-radius 20
:border-top-right-radius 20
:background-color (colors/alpha colors/white 0.05)})
:background-color colors/white-opa-5})
(def bottom-container
{:flex-direction :row
@@ -35,14 +40,14 @@
:width 28
:justify-content :center
:align-items :center
:border-color (colors/alpha colors/white 0.05)})
:border-color colors/white-opa-5})
(def bottom-text
{:flex 1
:color (colors/alpha colors/white 0.7)})
:color colors/white-70-blur})
(def top-text
{:color (colors/alpha colors/white 0.7)})
{:color colors/white-70-blur})
(defn heading-text
[gap]
@@ -3,6 +3,7 @@
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[quo2.components.drawers.drawer-buttons.style :as style]))
(defn render-bottom
@@ -70,7 +71,7 @@
child-2 string, keyword or hiccup
"
[{:keys [container-style top-card bottom-card]} child-1 child-2]
[rn/view
[blur/ios-view
{:style (merge container-style style/outer-container)}
[card
(merge {:gap 4
@@ -6,6 +6,7 @@
[quo2.components.inputs.title-input.view :as title-input]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.hole-view :as hole-view]))
(defn profile-input
@@ -18,20 +19,29 @@
[rn/view
{:style (style/container customization-color)}
[rn/view
[hole-view/hole-view
{:holes [{:x 33
:y 23
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(assoc image-picker-props
:customization-color customization-color
:full-name (if (seq full-name)
full-name
placeholder)
:status-indicator? false
:size :medium)]]
(if platform/ios?
[hole-view/hole-view
{:holes [{:x 33
:y 23
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(assoc image-picker-props
:customization-color customization-color
:full-name (if (seq full-name)
full-name
placeholder)
:status-indicator? false
:size :medium)]]
[user-avatar/user-avatar
(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,6 +57,7 @@
[rn/view {:style style/input-container}
[title-input/title-input
(merge title-input-props
{:override-theme :dark
{:blur? true
:override-theme :dark
:placeholder placeholder
:customization-color customization-color})]]]))
@@ -2,34 +2,35 @@
(:require [quo2.foundations.colors :as colors]))
(defn get-focused-placeholder-color
[blur?]
[blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-20 (colors/alpha colors/white 0.2))
(colors/theme-colors colors/neutral-30 colors/neutral-60)))
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 override-theme)
(colors/theme-colors colors/neutral-30 colors/neutral-60 override-theme))
)
(defn get-placeholder-color
[blur?]
[blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 (colors/alpha colors/white 0.3))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 override-theme)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(defn- get-disabled-color
[blur?]
[blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 (colors/alpha colors/white 0.3))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(defn- get-char-count-color
[blur?]
[blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 (colors/alpha colors/white 0.4))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(defn get-selection-color
[customization-color blur?]
[customization-color blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-100 colors/white)
(colors/custom-color customization-color (if colors/dark? 60 50))))
(colors/theme-colors colors/neutral-100 colors/white override-theme)
(colors/custom-color customization-color (if (or (= :dark override-theme) colors/dark?) 60 50))))
(def text-input-container {:flex 1})
@@ -37,12 +38,12 @@
[disabled? blur? override-theme]
{:text-align-vertical :bottom
:color (if disabled?
(get-disabled-color blur?)
(get-disabled-color blur? override-theme)
(colors/theme-colors colors/neutral-100 colors/white override-theme))})
(defn char-count
[blur?]
{:color (get-char-count-color blur?)})
[blur? override-theme]
{:color (get-char-count-color blur? override-theme)})
(def container
{:flex-direction :row
@@ -45,21 +45,21 @@
:editable (not disabled?)
:max-length max-length
:placeholder placeholder
:selection-color (style/get-selection-color customization-color blur?)
:selection-color (style/get-selection-color customization-color blur? override-theme)
:placeholder-text-color (if @focused?
(style/get-focused-placeholder-color blur?)
(style/get-placeholder-color blur?))}]]
(style/get-focused-placeholder-color blur? override-theme)
(style/get-placeholder-color blur? override-theme))}]]
[rn/view
{:style style/counter-container}
[text/text
[text/text
{:style (style/char-count blur?)
{:style (style/char-count blur? override-theme)
:size :paragraph-2}
(pad-0
(str
(count @value)))]
[text/text
{:style (style/char-count blur?)
{:style (style/char-count blur? override-theme)
:size :paragraph-2}
(str "/"
(pad-0
+10 -9
View File
@@ -203,8 +203,8 @@
}
}
"
[{:keys [one-icon-align-left? horizontal-description? align-mid?
page-nav-color page-nav-background-uri
[{:keys [container-style one-icon-align-left? horizontal-description?
align-mid? page-nav-color page-nav-background-uri
mid-section
left-section
right-section-buttons]}]
@@ -222,13 +222,14 @@
:left-icon (:left-icon mid-section)
:avatar (:avatar mid-section)}]
[rn/view
{:style (cond-> {:display :flex
:flex-direction :row
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
:align-items :center
:padding-horizontal 20
:height 56
:justify-content :space-between}
{:style (cond-> (merge {:display :flex
:flex-direction :row
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
:align-items :center
:padding-horizontal 20
:height 56
:justify-content :space-between}
container-style)
page-nav-background-uri (assoc :background-color page-nav-color)
page-nav-color (assoc :background page-nav-background-uri))}
[rn/view
+2
View File
@@ -117,6 +117,7 @@
;;;;Blur
(def white-70-blur (alpha white 0.7))
(def neutral-80-opa-1-blur (alpha "#192438" 0.1))
(def neutral-5-opa-70-blur (alpha neutral-5 0.7))
(def neutral-80-opa-80-blur (alpha "#192438" 0.8))
(def neutral-90-opa-70-blur (alpha neutral-90 0.7))
@@ -127,6 +128,7 @@
;;Solid
(def black "#000000")
(def onboarding-header-black "#000716")
;;;;Primary
+6 -1
View File
@@ -1,5 +1,10 @@
(ns react-native.blur
(:require ["@react-native-community/blur" :as blur]
[reagent.core :as reagent]))
[react-native.platform :as platform]
[reagent.core :as reagent]
[react-native.core :as rn]))
(def view (reagent/adapt-react-class (.-BlurView blur)))
;; blur view is currently not working correctly on Android.
(def ios-view (if platform/ios? view rn/view))
+4 -1
View File
@@ -9,6 +9,7 @@
withDelay
withSpring
withRepeat
withSequence
withDecay
Easing
Keyframe
@@ -17,8 +18,8 @@
SlideOutUp
LinearTransition)]
[reagent.core :as reagent]
["react-native-redash" :refer (withPause)]
[react-native.flat-list :as rn-flat-list]
[utils.collection]
[utils.worklets.core :as worklets.core]))
(def ^:const default-duration 300)
@@ -59,6 +60,8 @@
(def with-decay withDecay)
(def key-frame Keyframe)
(def with-repeat withRepeat)
(def with-sequence withSequence)
(def with-pause withPause)
(def cancel-animation cancelAnimation)
;; Easings
@@ -125,6 +125,28 @@
(fn [[cb options]]
(authenticate-fx #(cb %) options)))
(re-frame/reg-fx
:biometric/enable-and-save-password
(fn [{:keys [key-uid
masked-password
on-success
on-error]}]
(-> (keychain/save-user-password!
key-uid
masked-password)
(.then
(fn [_]
(keychain/save-auth-method!
key-uid
keychain/auth-method-biometric)))
(.then
(fn [_]
(when on-success
(on-success))))
(.catch (fn [error]
(when on-error
(on-error error)))))))
(rf/defn update-biometric
[{db :db :as cofx} biometric-auth?]
(let [key-uid (or (get-in db [:multiaccount :key-uid])
+1
View File
@@ -44,6 +44,7 @@
(let [me? (= (:public-key current-multiaccount) identity)]
(if me?
[(or (:preferred-name current-multiaccount)
(:primary-name contact)
(gfycat/generate-gfy identity))]
[(:primary-name contact) (:secondary-name contact)])))
+22 -19
View File
@@ -365,6 +365,25 @@
[_]
(status/get-node-config #(re-frame/dispatch [::get-node-config-callback %])))
(rf/defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
[{:keys [db] :as cofx}]
(cond
(get db :local-pairing/completed-pairing?)
{:dispatch [:syncing/pairing-completed]}
(get db :onboarding-2/new-account?)
{:dispatch [:onboarding-2/finalize-setup]}
(get db :tos/accepted?)
(rf/merge
cofx
(multiaccounts/switch-theme nil :shell-stack)
(navigation/init-root :shell-stack))
:else
{:dispatch [:init-root :tos]}))
(rf/defn get-settings-callback
{:events [::get-settings-callback]}
[{:keys [db] :as cofx} settings]
@@ -397,7 +416,8 @@
(logging/set-log-level (:log-level multiaccount))
(activity-center/notifications-fetch-pending-contact-requests)
(activity-center/update-seen-state)
(activity-center/notifications-fetch-unread-count))))
(activity-center/notifications-fetch-unread-count)
(redirect-to-root))))
(re-frame/reg-fx
::open-last-chat
@@ -472,22 +492,6 @@
keychain/auth-method-biometric
keychain/auth-method-password))))
(defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
[db]
(cond
(get db :local-pairing/completed-pairing?)
(re-frame/dispatch [:syncing/pairing-completed])
(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
[{:keys [db] :as cofx} key-uid password save-password?]
(let [auth-method (:auth-method db)
@@ -499,8 +503,7 @@
{:db (assoc db :chats/loading? true)
:json-rpc/call
[{:method "settings_getSettings"
:on-success #(do (re-frame/dispatch [::get-settings-callback %])
(redirect-to-root db))}]}
:on-success #(re-frame/dispatch [::get-settings-callback %])}]}
(notifications/load-notification-preferences)
(when save-password?
(keychain/save-user-password key-uid password))
+2 -2
View File
@@ -628,6 +628,6 @@
[]
(.keystoreDir ^js (status)))
(defn log-file-path
(defn log-file-directory
[]
(.logFilePath ^js (status)))
(.logFileDirectory ^js (status)))
+1 -1
View File
@@ -165,7 +165,7 @@
:MailserversConfig {:Enabled true}
:EnableNTPSync true
:WakuConfig
{:Enabled true
{:Enabled (not wakuv2-enabled)
:BloomFilterMode waku-bloom-filter-mode
:LightClient true
:MinimumPoW 0.000001}
+29 -21
View File
@@ -155,19 +155,36 @@
(callback nil))))
(callback nil))))))
(defn save-user-password!
[key-uid password]
(save-credentials
key-uid
key-uid
(security/safe-unmask-data password)
#(when-not %
(log/error
(str "Error while saving password."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))
(defn save-auth-method!
[key-uid method]
(save-credentials
(str key-uid "-auth")
key-uid
method
#(when-not %
(log/error
(str "Error while saving auth method."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))
(re-frame/reg-fx
:keychain/save-user-password
(fn [[key-uid password]]
(save-credentials
key-uid
key-uid
(security/safe-unmask-data password)
#(when-not %
(log/error
(str "Error while saving password."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it."))))))
(fn [[key-uid masked-password]]
(save-user-password! key-uid masked-password)))
(re-frame/reg-fx
:keychain/save-auth-method
@@ -178,16 +195,7 @@
"method"
method)
(when-not (empty? key-uid) ; key-uid may be nil after restore from local pairing
(save-credentials
(str key-uid "-auth")
key-uid
method
#(when-not %
(log/error
(str "Error while saving auth method."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))))
(save-auth-method! key-uid method))))
(re-frame/reg-fx
:keychain/save-keycard-keys
+4 -8
View File
@@ -225,12 +225,8 @@
(defn format-members
[count]
(cond
(> count 1000000)
(if (> count 1000000)
(str (with-precision (/ count 1000000) 1) (i18n/label :t/M))
(< 999 count 1000000)
(str (with-precision (/ count 1000) 1) (i18n/label :t/K))
:else
count))
(if (and (> count 999) (< count 1000000))
(str (with-precision (/ count 1000) 1) (i18n/label :t/K))
count)))
+5
View File
@@ -126,6 +126,11 @@
(when (string? s)
(string/replace s m r)))
(defn safe-nth
[coll index]
(when (number? index)
(nth coll index)))
(defn svg?
[some-string]
(string/ends-with? some-string ".svg"))
@@ -7,7 +7,7 @@
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[status-im2.common.bottom-sheet.view :as bottom-sheet]
[status-im2.contexts.chat.messages.pin.list.view :as pin.list]
[status-im2.contexts.chat.menus.pinned-messages.view :as pinned-messages-menu]
[react-native.core :as rn]))
(defn bottom-sheet
@@ -50,7 +50,8 @@
(merge key-storage/migrate-account-password)
(= view :pinned-messages-list)
(merge {:content pin.list/pinned-messages-list}))]
(merge {:content pinned-messages-menu/pinned-messages
:bottom-safe-area-spacing? false}))]
[:f>
(fn []
(rn/use-effect (fn []
+9 -14
View File
@@ -1,20 +1,15 @@
(ns status-im2.common.resources)
(def ui
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
:intro-1 (js/require "../resources/images/ui2/intro-1.png")
:intro-2 (js/require "../resources/images/ui2/intro-2.png")
:intro-3 (js/require "../resources/images/ui2/intro-3.png")
:intro-4 (js/require "../resources/images/ui2/intro-4.png")
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
:music (js/require "../resources/images/ui2/music.png")
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
:onboarding-bg-1 (js/require "../resources/images/ui2/onboarding-bg-1.png")
:onboarding-blur-bg (js/require "../resources/images/ui2/onboarding_blur_bg.png")
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")})
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
:music (js/require "../resources/images/ui2/music.png")
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")})
(def mock-images
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
+21 -25
View File
@@ -89,7 +89,7 @@
(defn display-picture
[scroll-height logo]
[scroll-height cover]
(let [input-range (if platform/ios? [-67 10] [0 150])
y (reanimated/use-shared-value scroll-height)
animation (reanimated/interpolate y
@@ -104,7 +104,7 @@
[reanimated/view
{:style (style/display-picture-container animation)}
[rn/image
{:source logo
{:source cover
:style style/display-picture}]]))
(defn scroll-page
@@ -117,7 +117,7 @@
[:<>
[:f> scroll-page-header @scroll-height height name page-nav-right-section-buttons
logo sticky-header top-nav title-colum navigate-back?]
[rn/flat-list
[rn/scroll-view
{:content-container-style (style/scroll-view-container
(diff-with-max-min @scroll-height 16 0))
:shows-vertical-scroll-indicator false
@@ -128,25 +128,21 @@
event
"nativeEvent.contentOffset.y")))
(when on-scroll
(on-scroll @scroll-height)))
:header [rn/view
(when cover-image
[rn/view {:style {:height 151}}
[rn/image
{:source cover-image
;; Using negative margin-bottom as a workaround because
;; on Android,
;; ScrollView clips its children despite setting
;; overflow: 'visible'.
;; Related issue:
;; https://github.com/facebook/react-native/issues/31218
:style {:margin-bottom -16
:flex 1}}]])
(when children
[rn/view
{:flex 1
:border-radius (diff-with-max-min @scroll-height 16 0)
:background-color background-color}
(when cover-image
[:f> display-picture @scroll-height logo])
children])]}]])))
(on-scroll @scroll-height)))}
(when cover-image
[rn/view {:style {:height 151}}
[rn/image
{:source cover-image
;; Using negative margin-bottom as a workaround because on Android,
;; ScrollView clips its children despite setting overflow: 'visible'.
;; Related issue: https://github.com/facebook/react-native/issues/31218
:style {:margin-bottom -16
:flex 1}}]])
(when children
[rn/view
{:flex 1
:border-radius (diff-with-max-min @scroll-height 16 0)
:background-color background-color}
(when cover-image
[:f> display-picture @scroll-height logo])
children])]])))
+6
View File
@@ -138,6 +138,12 @@
:url "#"
:icons ["https://statusnetwork.com/img/press-kit-status-logo.svg"]})
(def default-network-id
(get-in default-networks-by-id [default-network :config :NetworkId]))
(def default-network-rpc-url
(get-in default-networks-by-id [default-network :config :UpstreamConfig :URL]))
(def wallet-connect-project-id "87815d72a81d739d2a7ce15c2cfdefb3")
(def delete-message-undo-time-limit-ms 4000)
@@ -552,7 +552,7 @@
{:icon :placeholder
:icon-color colors/primary-50-opa-40
:title (i18n/label :t/contact-request-accepted-toast
{:name (:alias message)})})
{:name (or name (:alias message))})})
:else
cofx))
@@ -130,7 +130,7 @@
;; The initial value of data is the image that was pressed (and not the whole album) in order
;; for the transition animation to execute properly, otherwise it would animate towards
;; outside the screen (even if we have `initialScrollIndex` set).
data (reagent/atom [(nth messages index)])
data (reagent/atom (if (number? index) [(nth messages index)] []))
scroll-index (reagent/atom index)
transparent? (reagent/atom false)
set-full-height? (reagent/atom false)
@@ -13,3 +13,5 @@
(def ^:const velocity-factor 0.5)
(def ^:const default-duration 300)
(def ^:const default-dimension 300)
@@ -216,10 +216,11 @@
curr-orientation (or (rf/sub [:lightbox/orientation])
orientation/portrait)
portrait? (= curr-orientation orientation/portrait)
dimensions (utils/get-dimensions image-width
image-height
curr-orientation
args)
dimensions (utils/get-dimensions
(or image-width c/default-dimension)
(or image-height c/default-duration)
curr-orientation
args)
animations {:scale (anim/use-val c/min-scale)
:saved-scale (anim/use-val c/min-scale)
:pan-x-start (anim/use-val c/init-offset)
@@ -0,0 +1,44 @@
(ns status-im2.contexts.chat.menus.pinned-messages.style
(:require [quo2.foundations.colors :as colors]))
(def heading
{:margin-horizontal 20})
(def heading-container
{:flex-direction :row
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:border-radius 20
:align-items :center
:align-self :flex-start
:margin-horizontal 20
:padding 4
:margin-top 8})
(def heading-text
{:margin-left 6
:margin-right 4})
(def chat-name-text
{:margin-left 4
:margin-right 8})
(defn list-footer
[bottom-inset]
{:height bottom-inset})
(defn no-pinned-messages-container
[bottom-inset]
{:justify-content :center
:align-items :center
:margin-top 20
:margin-bottom bottom-inset})
(def no-pinned-messages-icon
{:width 120
:height 120
:justify-content :center
:align-items :center
:border-width 1})
(def no-pinned-messages-text
{:margin-top 20})
@@ -0,0 +1,73 @@
(ns status-im2.contexts.chat.menus.pinned-messages.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im2.contexts.chat.messages.content.deleted.view :as content.deleted]
[status-im2.contexts.chat.messages.content.view :as message]
[status-im2.contexts.chat.menus.pinned-messages.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def list-key-fn #(or (:message-id %) (:value %)))
(defn message-render-fn
[{:keys [deleted? deleted-for-me?] :as message} _ _ context]
;; TODO (flexsurfer) probably we don't want reactions here
(if (or deleted? deleted-for-me?)
[content.deleted/deleted-message message context]
[message/message-with-reactions message context]))
(defn pinned-messages
[chat-id]
(let [pinned-messages (rf/sub [:chats/pinned-sorted-list chat-id])
render-data (rf/sub [:chats/current-chat-message-list-view-context :in-pinned-view])
current-chat (rf/sub [:chat-by-id chat-id])
{:keys [community-id]} current-chat
community (rf/sub [:communities/community community-id])]
[safe-area/consumer
(fn [insets]
[:f>
(fn []
(let [{window-height :height} (rn/use-window-dimensions)
bottom-inset (:bottom insets)]
[rn/scroll-view
{:style {:max-height (- window-height (:top insets))}
:accessibility-label :pinned-messages-menu}
[:<>
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/heading}
(i18n/label :t/pinned-messages)]
(when community
[rn/view
{:style style/heading-container}
[rn/text {:style style/heading-text} (:name community)]
[quo/icon
:i/chevron-right
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:size 12}]
[rn/text
{:style style/chat-name-text}
(str "# " (:chat-name current-chat))]])]
(if (pos? (count pinned-messages))
[rn/flat-list
{:data pinned-messages
:render-data render-data
:render-fn message-render-fn
:footer [rn/view {:style (style/list-footer bottom-inset)}]
:key-fn list-key-fn
:separator quo/separator}]
[rn/view {:style (style/no-pinned-messages-container bottom-inset)}
[rn/view {:style style/no-pinned-messages-icon}
[quo/icon :i/placeholder]]
[quo/text
{:weight :semi-bold
:style style/no-pinned-messages-text}
(i18n/label :t/no-pinned-messages)]
[quo/text {:size :paragraph-2}
(i18n/label
(if community
:t/no-pinned-messages-community-desc
:t/no-pinned-messages-desc))]])]))])]))
@@ -46,8 +46,7 @@
{:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed #(rf/dispatch
[:open-modal :photo-selector {:insets insets}])
:on-allowed #(rf/dispatch [:open-modal :photo-selector {:insets insets}])
:on-denied (fn []
(background-timer/set-timeout
#(utils-old/show-popup (i18n/label :t/error)
@@ -13,7 +13,7 @@
[units {:keys [type literal destination]} chat-id]
(case (keyword type)
:code
(conj units [rn/view {:style (merge style/block (style/code))} [quo/text {:weight :code} literal]])
(conj units [quo/text {:style (merge style/block (style/code)) :weight :code} literal])
:emph
(conj units [quo/text {:style {:font-style :italic}} literal])
@@ -1,77 +0,0 @@
(ns status-im2.contexts.chat.messages.pin.list.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[status-im2.contexts.chat.messages.content.deleted.view :as content.deleted]
[status-im2.contexts.chat.messages.content.view :as message]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def list-key-fn #(or (:message-id %) (:value %)))
(defn message-render-fn
[{:keys [deleted? deleted-for-me?] :as message} _ _ context]
;; TODO (flexsurfer) probably we don't want reactions here
(if (or deleted? deleted-for-me?)
[content.deleted/deleted-message message context]
[message/message-with-reactions message context]))
(defn pinned-messages-list
[chat-id]
(let [pinned-messages (rf/sub [:chats/pinned-sorted-list chat-id])
render-data (rf/sub [:chats/current-chat-message-list-view-context :in-pinned-view])
current-chat (rf/sub [:chat-by-id chat-id])
{:keys [community-id]} current-chat
community (rf/sub [:communities/community community-id])]
[rn/view {:accessibility-label :pinned-messages-list}
;; TODO (flexsurfer) this should be a component in quo2
;; https://github.com/status-im/status-mobile/issues/14529
[:<>
[quo/text
{:size :heading-1
:weight :semi-bold
:style {:margin-horizontal 20}}
(i18n/label :t/pinned-messages)]
(when community
[rn/view
{:style {:flex-direction :row
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:border-radius 20
:align-items :center
:align-self :flex-start
:margin-horizontal 20
:padding 4
:margin-top 8}}
[rn/text {:style {:margin-left 6 :margin-right 4}} (:name community)]
[quo/icon
:i/chevron-right
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:size 12}]
[rn/text
{:style {:margin-left 4
:margin-right 8}}
(str "# " (:chat-name current-chat))]])]
(if (pos? (count pinned-messages))
[rn/flat-list
{:data pinned-messages
:render-data render-data
:render-fn message-render-fn
:key-fn list-key-fn
:separator quo/separator}]
[rn/view
{:style {:justify-content :center
:align-items :center
:margin-top 20}}
[rn/view
{:style {:width 120
:height 120
:justify-content :center
:align-items :center
:border-width 1}} [quo/icon :i/placeholder]]
[quo/text
{:weight :semi-bold
:style {:margin-top 20}}
(i18n/label :t/no-pinned-messages)]
[quo/text {:size :paragraph-2}
(i18n/label
(if community :t/no-pinned-messages-community-desc :t/no-pinned-messages-desc))]])]))
@@ -3,10 +3,10 @@
[react-native.platform :as platform]))
(defn gradient-container
[insets]
[bottom-inset]
{:left 0
:right 0
:height (+ (:bottom insets) (if platform/ios? 65 85))
:height (+ bottom-inset (if platform/ios? 65 85))
:position :absolute
:bottom 0})
@@ -31,7 +31,7 @@
{:colors [:black :transparent]
:start {:x 0 :y 1}
:end {:x 0 :y 0}
:style (style/gradient-container insets)}
:style (style/gradient-container (:bottom insets))}
[quo/button
{:style {:align-self :stretch
:margin-horizontal 20
@@ -4,11 +4,12 @@
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.communities.menus.community-options.view :as options]
[status-im.ui.screens.communities.community :as community]
[status-im.ui.components.react :as react]
[react-native.platform :as platform]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.contexts.communities.discover.style :as style]
[utils.re-frame :as rf]))
@@ -22,27 +23,22 @@
:token-icon (resources/get-mock-image :status-logo)}]}]}})
(defn community-list-item
[{:keys [id] :as community} _ _ {:keys [width view-type]}]
(let [community-item (merge
community
(get mock-community-item-data :data))
cover {:uri (get-in (:images community) [:banner :uri])}]
[community-item _ _ {:keys [width view-type]}]
(let [item (merge community-item
(get mock-community-item-data :data))
cover {:uri (get-in (:images item) [:banner :uri])}]
(if (= view-type :card-view)
[quo/community-card-view-item (assoc community-item :width width :cover cover)
#(rf/dispatch [:navigate-to :community-overview (:id community)])]
[quo/community-card-view-item (assoc item :width width :cover cover)
#(rf/dispatch [:navigate-to :community-overview (:id item)])]
[quo/communities-list-view-item
{:on-press (fn []
(rf/dispatch [:communities/load-category-states id])
(rf/dispatch [:communities/load-category-states (:id item)])
(rf/dispatch [:dismiss-keyboard])
<<<<<<< HEAD
(rf/dispatch [:navigate-to :community-overview (:id item)]))
=======
(rf/dispatch [:navigate-to :community {:community-id id}]))
>>>>>>> 1675fef63 (Fix: community data not displayed)
:on-long-press #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
[options/community-options-bottom-sheet id])}])}])))
[options/community-options-bottom-sheet (:id item)])}])}])))
(defn screen-title
[]
@@ -93,6 +89,7 @@
:label (i18n/label :t/gated)
:accessibility-label :gated-communities-tab}]}]])
(defn featured-list
[communities view-type]
(let [view-size (reagent/atom 0)]
@@ -108,24 +105,13 @@
:horizontal true
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:nestedScrollEnabled true
:separator [rn/view {:width 12}]
:data communities
:render-fn community-list-item
:render-data {:width @view-size
:view-type view-type}
:contentContainerStyle style/flat-list-container}])])))
(defn other-communities-list
[{:keys [communities view-type]}]
[rn/view style/other-communities-container
[rn/flat-list
{:key-fn :id
:keyboard-should-persist-taps :always
:separator [rn/view {:height 16}]
:data communities
:render-fn community-list-item
:contentContainerStyle style/flat-list-container
:render-data {:view-type view-type}}]])
:content-container-style style/flat-list-container}])])))
(defn discover-communities-header
[{:keys [featured-communities-count
@@ -136,10 +122,41 @@
[screen-title]
[featured-communities-header featured-communities-count]
[featured-list featured-communities view-type]
[rn/view {:style {:margin-horizontal 20}}
[quo/separator]]
[quo/separator {:style {:margin-horizontal 20}}]
[discover-communities-segments selected-tab false]])
(defn other-communities-list
[{:keys [communities communities-ids view-type]}]
[rn/view {:style style/other-communities-container}
(map-indexed
(fn [inner-index item]
(let [community-id (when communities-ids item)
community (if communities
item
(rf/sub [:communities/home-item community-id]))
cover {:uri (get-in (:images item) [:banner :uri])}]
[rn/view
{:key (str inner-index (:id community))
:margin-bottom 16}
(if (= view-type :card-view)
[quo/community-card-view-item
(merge community
(get mock-community-item-data :data)
{:cover cover})
#(rf/dispatch [:navigate-to :community-overview (:id community)])]
[quo/communities-list-view-item
{:on-press (fn []
(rf/dispatch [:communities/load-category-states (:id community)])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview (:id community)]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
;; TODO implement with quo2
[community/community-actions community])}])}
(merge community
(get mock-community-item-data :data))])]))
(if communities communities communities-ids))])
(defn communities-lists
[selected-tab view-type]
[rn/view {:style {:flex 1}}
@@ -5,20 +5,12 @@
{:background-color colors/neutral-95
:flex-direction :row
:position :absolute
:overflow :hidden
:top 0
:bottom 0
:left 0
:right 0})
(defn background-gradient-overlay
[dark-overlay?]
{:position :absolute
:height (if dark-overlay? 240 136)
:top 0
:left 0
:right 0
:bottom 0})
(def background-blur-overlay
{:position :absolute
:left 0
@@ -1,26 +1,22 @@
(ns status-im2.contexts.onboarding.common.background.view
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[status-im2.common.resources :as resources]
[react-native.linear-gradient :as linear-gradient]
[status-im2.contexts.onboarding.common.background.style :as style]))
[react-native.blur :as blur]
[status-im2.contexts.onboarding.common.carousel.view :as carousel]
[status-im2.contexts.onboarding.common.background.style :as style]
[status-im2.contexts.onboarding.common.carousel.animation :as carousel.animation]))
(defn view
[dark-overlay?]
[rn/view
{:style style/background-container}
[rn/image
{:blur-radius (if dark-overlay? 13 0)
:style {:height "100%"
:width "100%"}
;; Todo - get background image from sub using carousel index on landing page
:source (resources/get-image :onboarding-bg-1)}]
[linear-gradient/linear-gradient
{:colors [(if dark-overlay? (colors/custom-color :yin 50) "#000716")
(if dark-overlay? (colors/custom-color :yin 50 0) "#000716")]
:start {:x 0 :y 0}
:end {:x 0 :y 1}
:style (style/background-gradient-overlay dark-overlay?)}]
(when dark-overlay?
[:f>
(fn []
(carousel.animation/initialize-animation)
[rn/view
{:style style/background-blur-overlay}])])
{:style style/background-container}
[carousel/view dark-overlay?]
(when dark-overlay?
[blur/view
{:style style/background-blur-overlay
:blur-amount 30
:blur-radius 25
:blur-type :transparent
:overlay-color :transparent}])])])
@@ -0,0 +1,50 @@
(ns status-im2.contexts.onboarding.common.carousel.animation
(:require
[react-native.reanimated :as reanimated]
[utils.worklets.onboarding-carousel :as worklets.onboarding-carousel]))
(def progress (atom nil))
(def paused (atom nil))
(def ^:const progress-bar-animation-delay 300)
(def ^:const progress-bar-animation-duration 4000)
(defn slide-animation
[progress-percentage & [delay duration]]
(reanimated/with-delay
(or delay progress-bar-animation-delay)
(reanimated/with-timing
progress-percentage
(js-obj "duration" (or duration progress-bar-animation-duration)
"easing" (:linear reanimated/easings)))))
(defn animate-progress
[progress paused]
(reanimated/set-shared-value
progress
(reanimated/with-pause
(reanimated/with-repeat
(reanimated/with-sequence
(slide-animation 25)
(slide-animation 50)
(slide-animation 75)
(slide-animation 100)
(slide-animation 0 300 0))
-1)
paused)))
(defn initialize-animation
[]
(when-not @progress
(reset! progress (reanimated/use-shared-value 0))
(reset! paused (reanimated/use-shared-value false))
(animate-progress @progress @paused)))
;; Derived Values
(defn carousel-left-position
[window-width]
(worklets.onboarding-carousel/carousel-left-position window-width @progress))
(defn dynamic-progress-bar-width
[progress-bar-width]
(worklets.onboarding-carousel/dynamic-progress-bar-width progress-bar-width @progress))
@@ -0,0 +1,73 @@
(ns status-im2.contexts.onboarding.common.carousel.style
(:require
[quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(defn header-container
[status-bar-height content-width index]
{:position :absolute
:top 0
:left (* content-width index)
:padding-top (+ 30 status-bar-height)
:width content-width
:height (+ 96 status-bar-height)
:flex-direction :row
:background-color colors/onboarding-header-black})
(defn header-text-view
[window-width]
{:flex-direction :column
:width window-width
:padding-left 20})
(def carousel-text
{:color colors/white})
(def carousel-sub-text
{:color colors/white
:margin-top 2})
(defn background-image
[content-width]
{:resize-mode :stretch
:width content-width})
(defn progress-bar-item
[static? end?]
{:height 2
:flex 1
:background-color (if static? colors/white-opa-10 colors/white)
:margin-right (if end? 0 8)
:border-radius 4})
(defn progress-bar
[width]
{:position :absolute
:top 0
:width width
:flex-direction :row})
(defn dynamic-progress-bar
[width]
(reanimated/apply-animations-to-style
{:width width}
{:height 2
:border-radius 4
:overflow :hidden}))
(defn progress-bar-container
[progress-bar-width status-bar-height]
{:position :absolute
:width progress-bar-width
:margin-left 20
:top (+ 12 status-bar-height)})
(defn carousel-container
[left]
(reanimated/apply-animations-to-style
{:left left}
{:position :absolute
:right 0
:top 0
:bottom 0
:flex-direction :row}))
@@ -0,0 +1,95 @@
(ns status-im2.contexts.onboarding.common.carousel.view
(:require [quo2.core :as quo]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[react-native.core :as rn]
[react-native.navigation :as navigation]
[react-native.reanimated :as reanimated]
[status-im2.common.resources :as resources]
[status-im2.contexts.onboarding.common.carousel.style :as style]
[status-im2.contexts.onboarding.common.carousel.animation :as animation]))
(def header-text
[{:text (i18n/label :t/join-decentralised-communities)
:sub-text (i18n/label :t/participate-in-the-metaverse)}
{:text (i18n/label :t/chat-with-friends)
:sub-text (i18n/label :t/with-full-encryption)}
{:text (i18n/label :t/own-your-crypto)
:sub-text (i18n/label :t/use-the-multichain-wallet)}
{:text (i18n/label :t/discover-web3)
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
(defn header-text-view
[index window-width]
[rn/view {:style (style/header-text-view window-width)}
[quo/text
{:style style/carousel-text
:weight :semi-bold
:size :heading-2}
(get-in header-text [index :text])]
[quo/text
{:style style/carousel-sub-text
:size :paragraph-1}
(get-in header-text [index :sub-text])]])
(defn content-view
[{:keys [window-width status-bar-height index]}]
(let [content-width (* 4 window-width)]
[:<>
[rn/image
{:style (style/background-image content-width)
:source (resources/get-image :onboarding-illustration)}]
[rn/view {:style (style/header-container status-bar-height content-width index)}
(for [index (range 4)]
^{:key index}
[header-text-view index window-width])]]))
(defn progress-bar
[{:keys [static? progress-bar-width]}]
[rn/view
{:style (style/progress-bar progress-bar-width)}
[rn/view {:style (style/progress-bar-item static? false)}]
[rn/view {:style (style/progress-bar-item static? false)}]
[rn/view {:style (style/progress-bar-item static? false)}]
[rn/view {:style (style/progress-bar-item static? true)}]])
(defn dynamic-progress-bar
[progress-bar-width]
[:f>
(fn []
(let [width (animation/dynamic-progress-bar-width progress-bar-width)]
[reanimated/view {:style (style/dynamic-progress-bar width)}
[progress-bar
{:static? false
:progress-bar-width progress-bar-width}]]))])
(defn view
[]
[:f>
(fn []
(let [window-width (rf/sub [:dimensions/window-width])
view-id (rf/sub [:view-id])
status-bar-height (:status-bar-height @navigation/constants)
progress-bar-width (- window-width 40)
carousel-left (animation/carousel-left-position window-width)]
(rn/use-effect
(fn []
(reanimated/set-shared-value @animation/paused (not= view-id :intro)))
[view-id])
[:<>
[reanimated/view {:style (style/carousel-container carousel-left)}
(for [index (range 2)]
^{:key index}
[content-view
{:window-width window-width
:status-bar-height status-bar-height
:index index}])]
[rn/view
{:style (style/progress-bar-container
progress-bar-width
status-bar-height)}
[progress-bar
{:static? true
:progress-bar-width progress-bar-width}]
[dynamic-progress-bar progress-bar-width]]]))])
@@ -1,88 +0,0 @@
(ns status-im2.contexts.onboarding.common.intro.view
(:require [utils.i18n :as i18n]
[quo2.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[utils.re-frame :as rf]
[status-im2.contexts.onboarding.common.intro.style :as style]
[status-im2.common.resources :as resources]))
(def carousels
[{:image (resources/get-image :intro-1)
:text (i18n/label :t/join-decentralised-communities)
:sub-text (i18n/label :t/participate-in-the-metaverse)}
{:image (resources/get-image :intro-2)
:text (i18n/label :t/chat-with-friends)
:sub-text (i18n/label :t/with-full-encryption)}
{:image (resources/get-image :intro-3)
:text (i18n/label :t/own-your-crypto)
:sub-text (i18n/label :t/use-the-multichain-wallet)}
{:image (resources/get-image :intro-4)
:text (i18n/label :t/discover-web3)
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
(defn progress-bar
[index]
[rn/view style/progress-bar-container
[rn/view {:style (style/progress-bar-item index 0 false)}]
[rn/view {:style (style/progress-bar-item index 1 false)}]
[rn/view {:style (style/progress-bar-item index 2 false)}]
[rn/view {:style (style/progress-bar-item index 3 true)}]])
;; TODO: carousel component is to be correctly implemented as quo2 component with animations etc in:
;; https://github.com/status-im/status-mobile/issues/15012
(defn carousel
[index]
[rn/view {:style style/carousel}
[progress-bar index]
[quo/text
{:style style/carousel-text
:weight :semi-bold
:size :heading-2}
(get-in carousels [index :text])]
[quo/text
{:style style/carousel-text
:size :paragraph-1}
(get-in carousels [index :sub-text])]])
(defn set-index
[old-index]
(mod (inc old-index) 4))
(defn view
[]
(reagent/with-let [carousel-index (reagent/atom 0)
interval-id (js/setInterval #(swap! carousel-index set-index)
1500)]
[rn/view {:style style/page-container}
[carousel @carousel-index]
[rn/image
{:style style/page-image
:source (get-in carousels [@carousel-index :image])}]
[quo/drawer-buttons
{:top-card {:on-press (fn []
(rf/dispatch [:navigate-to :sign-in])
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
:heading (i18n/label :t/sign-in)
:accessibility-label :already-use-status-button}
:bottom-card {:on-press (fn []
(rf/dispatch [:navigate-to :new-to-status])
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
:heading (i18n/label :t/new-to-status)
:accessibility-label :new-to-status-button}}
(i18n/label :t/you-already-use-status)
[quo/text
{:style style/text-container}
[quo/text
{:size :paragraph-2
:style style/plain-text
:weight :semi-bold}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:open-modal :privacy-policy])
:size :paragraph-2
:style style/highlighted-text
:weight :semi-bold}
(i18n/label :t/terms-of-service)]]]]
(finally
(js/clearInterval interval-id))))
@@ -1,25 +1,59 @@
(ns status-im2.contexts.onboarding.create-profile.style
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(:require [react-native.platform :as platform]
[quo2.foundations.colors :as colors]))
(def continue-button
{:width "100%"
:margin-left :auto
:margin-top (if platform/android? :auto 0)
:margin-right :auto})
(def button-container
{:width "100%"
:margin-top :auto
:margin-bottom 72
:margin-left :auto
:margin-right :auto
:align-self :flex-end})
:padding-left 20
:padding-right 20
:padding-top (if platform/android? 0 12)
:align-self :flex-end
:height 64})
(def blur-button-container
(merge button-container
{:background-color colors/neutral-80-opa-1-blur}))
(def view-button-container
(merge button-container {:margin-bottom 24}))
(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})
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(def navigation-bar {:height 56})
(def info-message
{:margin-top 8})
(def title
{:color colors/white
:margin-top 12
:margin-bottom 20})
(def color-title
{:color colors/white-70-blur
:margin-top 20
:margin-bottom 16})
(def content-container
{:flex 1
:padding-horizontal 20})
(def input-container
{:flex 1
:align-items :flex-start
:margin-bottom 24})
(def profile-input-container
{:flex-direction :row
:justify-content :center})
@@ -9,18 +9,21 @@
[status-im2.contexts.onboarding.common.background.view :as background]
[status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu]
[utils.re-frame :as rf]
[oops.core :as oops]
[react-native.blur :as blur]
[status-im2.constants :as c]))
(defn navigation-bar
[]
[rn/view {:style style/navigation-bar}
[quo/page-nav
{:align-mid? true
:mid-section {:type :text-only :main-text ""}
:left-section {:type :blur-bg
:icon :i/arrow-left
:icon-override-theme :dark
:on-press #(rf/dispatch [:navigate-back])}}]])
{:container-style {:padding-horizontal 0}
:align-mid? true
:mid-section {:type :text-only :main-text ""}
:left-section {:type :blur-bg
:icon :i/arrow-left
:icon-override-theme :dark
:on-press #(rf/dispatch [:navigate-back])}}]])
(def emoji-regex
(new
@@ -30,96 +33,131 @@
(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"))
(def special-characters-regex (new js/RegExp #"[^a-zA-Z\d\s-._]" "i"))
(defn has-special-characters [s] (re-find special-characters-regex s))
(def min-length 5)
(defn length-not-valid [s] (< (count (string/trim s)) min-length))
(def valid-regex (new js/RegExp #"^[\w-\s]{5,24}$" "i"))
(defn valid-name [s] (re-find valid-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"})
(string/ends-with? s "_eth") (i18n/label :t/ending-not-allowed {:ending "_eth"})
(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)})
(has-emojis s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)})
(length-not-valid s) (i18n/label :t/name-must-have-at-least-characters
{:min-chars min-length})
(not (valid-name s)) (i18n/label :t/name-is-not-valid)
:else nil))
(defn button-container
[keyboard-shown? children]
(if keyboard-shown?
[blur/ios-view
{:style style/blur-button-container}
children]
[rn/view {:style style/view-button-container}
children]))
(defn page
[{: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-background-color (colors/custom-color @custom-color 60)
: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)]]])))
[:f>
(fn []
(let [full-name (reagent/atom display-name)
keyboard-shown? (reagent/atom false)
validation-msg (reagent/atom (validation-message @full-name))
on-change-text (fn [s]
(reset! validation-msg (validation-message s))
(reset! full-name (string/trim 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/use-effect
(let [will-show-listener (oops/ocall rn/keyboard
"addListener"
"keyboardWillShow"
#(swap! keyboard-shown? (fn [] true)))
will-hide-listener (oops/ocall rn/keyboard
"addListener"
"keyboardWillHide"
#(swap! keyboard-shown? (fn [] false)))]
(fn []
(fn []
(oops/ocall will-show-listener "remove")
(oops/ocall will-hide-listener "remove"))))
[])
[rn/view {:style style/page-container}
[rn/scroll-view
{:keyboard-should-persist-taps :always
:content-container-style {:flex-grow 1}}
[rn/view {:style style/page-container}
[rn/view
{:style style/content-container}
[navigation-bar]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title} (i18n/label :t/create-profile)]
[rn/view
{:style style/input-container}
[rn/view
{:style style/profile-input-container}
[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 {:default-value @full-name
: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 style/color-title}
(i18n/label :t/accent-colour)]
[quo/color-picker
{:blur? true
:default-selected? :blue
:selected @custom-color
:on-change on-change}]]]]]
[rn/keyboard-avoiding-view {}
[button-container @keyboard-shown?
[quo/button
{:accessibility-label :submit-create-profile-button
:type :primary
:override-background-color (colors/custom-color @custom-color 60)
:on-press (fn []
(rf/dispatch [:onboarding-2/profile-data-set
{:image-path @profile-pic
:display-name @full-name
:color @custom-color}]))
:style style/continue-button
:disabled (or (not (seq @full-name)) @validation-msg)}
(i18n/label :t/continue)]]]])))])
(defn create-profile
[]
[rn/view {:style {:flex 1}}
(let [onboarding-profile-data (rf/sub [:onboarding-2/profile])]
(let [onboarding-profile-data (rf/sub [:onboarding-2/profile])]
[:<>
[background/view true]
[page onboarding-profile-data])])
[page onboarding-profile-data]]))
+48 -12
View File
@@ -1,15 +1,17 @@
(ns status-im2.contexts.onboarding.events
(:require
[utils.re-frame :as rf]
[taoensso.timbre :as log]
[re-frame.core :as re-frame]
[status-im.utils.types :as types]
[status-im2.config :as config]
[clojure.string :as string]
[utils.i18n :as i18n]
[utils.security.core :as security]
[status-im.native-module.core :as status]
[status-im.ethereum.core :as ethereum]
[status-im2.constants :as constants]
[utils.i18n :as i18n]))
[status-im2.contexts.onboarding.profiles.view :as profiles.view]))
(re-frame/reg-fx
:multiaccount/create-account-and-login
@@ -22,10 +24,10 @@
(status/validate-mnemonic
(security/safe-unmask-data mnemonic)
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
(let [{:keys [error keyUID]} (types/json->clj result)]
(if (seq error)
(when on-error (on-error error))
(on-success mnemonic)))))))
(on-success mnemonic keyUID)))))))
(re-frame/reg-fx
:multiaccount/restore-account-and-login
@@ -91,18 +93,19 @@
:wakuV2Nameserver "1.1.1.1"
:logLevel (when log-enabled? config/log-level)
:logEnabled log-enabled?
:logFilePath (status/log-file-path)
:logFilePath (status/log-file-directory)
: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
:upstreamConfig config/default-network-rpc-url
:networkId config/default-network-id
:currentNetwork config/default-network
:previewPrivacy config/blank-preview?}]
{effect request
:dispatch [:navigate-to :generating-keys]
:db (-> db
(dissoc :onboarding-2/profile)
(assoc :onboarding-2/new-account? true))}))
:db (assoc db :onboarding-2/new-account? true)}))
(rf/defn on-delete-profile-success
{:events [:onboarding-2/on-delete-profile-success]}
@@ -121,15 +124,28 @@
{:events [:onboarding-2/seed-phrase-entered]}
[_ seed-phrase on-error]
{:multiaccount/validate-mnemonic [seed-phrase
#(re-frame/dispatch [:onboarding-2/seed-phrase-validated
seed-phrase])
(fn [mnemonic key-uid]
(re-frame/dispatch [:onboarding-2/seed-phrase-validated
mnemonic key-uid]))
on-error]})
(rf/defn seed-phrase-validated
{:events [:onboarding-2/seed-phrase-validated]}
[{:keys [db]} seed-phrase]
{:db (assoc-in db [:onboarding-2/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to :create-profile]})
[{:keys [db]} seed-phrase key-uid]
(if (contains? (:multiaccounts/multiaccounts db) key-uid)
{:utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept #(do
(re-frame/dispatch [:pop-to-root :profiles])
;; FIXME(rasom): obviously not cool
(reset! profiles.view/show-profiles? false)
(re-frame/dispatch
[:multiaccounts.login.ui/multiaccount-selected key-uid]))
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (assoc-in db [:onboarding-2/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to :create-profile]}))
(rf/defn navigate-to-create-profile
{:events [:onboarding-2/navigate-to-create-profile]}
@@ -137,3 +153,23 @@
;; Restart the flow
{:db (dissoc db :onboarding-2/profile)
:dispatch [:navigate-to :create-profile]})
(rf/defn onboarding-new-account-finalize-setup
{:events [:onboarding-2/finalize-setup]}
[{:keys [db]}]
(let [masked-password (get-in db [:onboarding-2/profile :password])
key-uid (get-in db [:multiaccount :key-uid])
biometric-enabled? (=
constants/auth-method-biometric
(get-in db [:onboarding-2/profile :auth-method]))]
(cond-> {:db (dissoc db :onboarding-2/profile)
:dispatch [:navigate-to :enable-notifications]}
biometric-enabled?
(assoc :biometric/enable-and-save-password
{:key-uid key-uid
:masked-password masked-password
:on-success #(log/debug "successfully saved biometric")
:on-error #(log/error "failed to save biometrics"
{:key-uid key-uid
:error %})}))))
@@ -1,10 +1,10 @@
(ns status-im2.contexts.onboarding.common.intro.style
(ns status-im2.contexts.onboarding.intro.style
(:require
[react-native.platform :as platform]
[quo2.foundations.colors :as colors]))
(def progress-bar-container
{:background-color colors/neutral-100
{:background-color :transparent
:flex-direction :row
:margin-vertical 16})
@@ -26,12 +26,12 @@
:left 0
:right 0
:z-index 2
:background-color colors/neutral-100
:background-color :transparent
:padding-vertical 12
:padding-horizontal 20})
(def carousel-text
{:background-color colors/neutral-100
{:background-color :transparent
:color colors/white})
(def page-container
@@ -39,14 +39,13 @@
:justify-content :flex-end})
(def page-image
{:position :absolute
:background-color colors/neutral-100
:top 0
:bottom 0
:left 0
:right 0
:width "100%"
:aspect-ratio 1})
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0
:width "100%"
:aspect-ratio 1})
(def text-container
{:flex 1
@@ -0,0 +1,37 @@
(ns status-im2.contexts.onboarding.intro.view
(:require [quo2.core :as quo]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[react-native.core :as rn]
[status-im2.contexts.onboarding.intro.style :as style]
[status-im2.contexts.onboarding.common.background.view :as background]))
(defn view
[]
[rn/view {:style style/page-container}
[background/view false]
[quo/drawer-buttons
{:top-card {:on-press (fn []
(rf/dispatch [:navigate-to :sign-in])
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
:heading (i18n/label :t/sign-in)
:accessibility-label :already-use-status-button}
:bottom-card {:on-press (fn []
(rf/dispatch [:navigate-to :new-to-status])
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
:heading (i18n/label :t/new-to-status)
:accessibility-label :new-to-status-button}}
(i18n/label :t/you-already-use-status)
[quo/text
{:style style/text-container}
[quo/text
{:size :paragraph-2
:style style/plain-text
:weight :semi-bold}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:open-modal :privacy-policy])
:size :paragraph-2
:style style/highlighted-text
:weight :semi-bold}
(i18n/label :t/terms-of-service)]]]])
@@ -4,20 +4,13 @@
(def full-screen {:flex 1})
(def image-background
{:height "100%"
:width "100%"})
(def layer-background
{: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})
(def content-container
{:padding-top (if platform/ios? 44 0)
:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(def options-container
{:padding-top 12
@@ -3,20 +3,13 @@
[quo2.core :as quo]
[react-native.core :as rn]
[status-im.keycard.recovery :as keycard]
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
[status-im2.common.resources :as resources]
[status-im2.contexts.onboarding.new-to-status.style :as style]
[status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
[status-im2.contexts.onboarding.common.background.view :as background]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn background-image
[]
[rn/image
{:style style/image-background
:blur-radius 13
:source (resources/get-image :onboarding-blur-bg)}])
(defn sign-in-options
[]
(let [window (rf/sub [:dimensions/window])]
@@ -46,21 +39,6 @@
(i18n/label :t/experienced-web3)]]
[rn/view {:style style/suboptions}
[quo/small-option-card
{:variant :icon
:title "Temporary (old) generate keys flow"
:subtitle "generate keys"
:image (resources/get-image :use-keycard)
:accessibility-label :generate-old-key
:on-press #(rf/dispatch [:generate-and-derive-addresses])}]
[rn/view {:style style/space-between-suboptions}]
[quo/small-option-card
{:variant :icon
:title "Temporary (old) recover phrase flow"
:subtitle (i18n/label :t/use-recovery-phrase-subtitle)
:image (resources/get-image :ethereum-address)
:on-press #(rf/dispatch [::multiaccounts.recover/enter-phrase-pressed])}]
[rn/view {:style style/space-between-suboptions}]
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-recovery-phrase)
@@ -78,7 +56,7 @@
(defn new-to-status
[]
[rn/view {:style style/full-screen}
[background-image]
[rn/view {:style style/layer-background}
[background/view true]
[rn/view {:style style/content-container}
[navigation-bar/navigation-bar {:on-press-info #(js/alert "Info pressed")}]
[sign-in-options]]])
@@ -5,7 +5,7 @@
[taoensso.timbre :as log]
[reagent.core :as reagent]
[react-native.core :as rn]
[status-im.utils.types :as types]
[utils.transforms :as types]
[utils.security.core :as security]
[status-im.native-module.core :as status]
[status-im2.contexts.onboarding.profiles.style :as style]
@@ -31,7 +31,7 @@
:label (i18n/label :t/add-existing-status-profile)
:on-press #(do
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch [:navigate-to :new-to-status]))
(rf/dispatch [:navigate-to :sign-in]))
:accessibility-label :multi-profile}]]])
(defn show-new-account-options
@@ -181,7 +181,7 @@
:accessibility-label :forget-password-button
:override-theme :dark
:style style/forget-password-button}
(i18n/label :t/forget-password)]
(i18n/label :t/forgot-password)]
[quo/button
{:size 40
:type :primary
@@ -202,4 +202,4 @@
[background/view true]
(if @show-profiles?
[profiles-section]
[login-section show-profiles?])]))
[login-section])]))
@@ -11,8 +11,8 @@
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.constants :as constants]
[status-im2.contexts.onboarding.common.background.view :as background]
[status-im2.contexts.onboarding.sign-in.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -216,9 +216,7 @@
:camera-options {:zoomMode :off}
:scan-barcode true
:on-read-code on-read-code}]
[rn/image
{:style (merge style/absolute-fill {:height height :width width})
:source (resources/get-image :intro-4)}])
[background/view true])
(conj hole-view-wrapper
[blur/view
{:style style/absolute-fill
@@ -83,7 +83,7 @@
(:labelled? @state))
:resource (if (= :emoji (:type @state))
(resources/get-image :music)
:main-icons2/placeholder)})]]]]])))
:i/placeholder)})]]]]])))
(defn preview-tag
[]
[rn/view
+24 -17
View File
@@ -8,7 +8,8 @@
[status-im.node.core :as node]
[re-frame.core :as re-frame]
[status-im.data-store.settings :as data-store.settings]
[status-im.utils.platform :as utils.platform]))
[status-im.utils.platform :as utils.platform]
[status-im2.constants :as constants]))
(rf/defn local-pairing-completed
{:events [:syncing/pairing-completed]}
@@ -54,19 +55,25 @@
(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 {:senderConfig {:keyUID key-uid
:keystorePath ""
:password sha3-pwd
:deviceType utils.platform/os}
:serverConfig {:timeout 0}}))]
(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])}])))))
(let [valid-password? (>= (count entered-password) constants/min-password-length)
show-sheet (fn [connection-string]
(rf/dispatch
[:bottom-sheet/show-sheet
{:show-handle? false
:content (fn []
[sheet/qr-code-view-with-connection-string
connection-string])}]))]
(if valid-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 {:senderConfig {:keyUID key-uid
:keystorePath ""
:password sha3-pwd
:deviceType utils.platform/os}
:serverConfig {:timeout 0}}))]
(status/get-connection-string-for-bootstrapping-another-device
config-map
#(show-sheet %)))
(show-sheet ""))))
+5 -4
View File
@@ -6,16 +6,16 @@
[status-im2.navigation.state :as state]))
(defn status-bar-options
[]
[& [status-bar-theme]]
;; dark-mode? = After login we are going to use theme as per user's choice (colors/dark?)
;; but before login we only have dark mode (dark-mode? = true)
(let [dark-mode? (if (= @state/root-id :shell-stack) (colors/dark?) true)]
(if platform/android?
{:navigationBar {:backgroundColor colors/neutral-100}
:statusBar {:backgroundColor :transparent
:style (if dark-mode? :light :dark)
:style (or status-bar-theme (if dark-mode? :light :dark))
:drawBehind true}}
{:statusBar {:style (if dark-mode? :light :dark)}})))
{:statusBar {:style (or status-bar-theme (if dark-mode? :light :dark))}})))
(defn topbar-options
[]
@@ -155,7 +155,8 @@
{:stack {:id :shell-stack
:children [{:component {:name :shell-stack
:id :shell-stack
:options (merge (status-bar-options)
:options (merge (status-bar-options
(if (colors/dark?) :light :dark))
{:topBar {:visible false}})}}]}}}
:profiles
{:root
+1 -1
View File
@@ -13,7 +13,7 @@
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
[status-im2.contexts.communities.discover.view :as communities.discover]
[status-im2.contexts.communities.overview.view :as communities.overview]
[status-im2.contexts.onboarding.common.intro.view :as intro]
[status-im2.contexts.onboarding.intro.view :as intro]
[status-im2.contexts.onboarding.create-password.view :as create-password]
[status-im2.contexts.onboarding.create-profile.view :as create-profile]
[status-im2.contexts.onboarding.enable-biometrics.view :as enable-biometrics]
+4 -4
View File
@@ -3,10 +3,10 @@
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.tokens :as tokens]
[utils.i18n :as i18n]
[status-im2.config :as config]
[status-im.utils.currency :as currency]
[status-im.utils.money :as money]))
[status-im.utils.money :as money]
[status-im2.config :as config]
[utils.i18n :as i18n]))
(re-frame/reg-sub
:balance
@@ -253,7 +253,7 @@
:wallet/currency
:<- [:wallet.settings/currency]
(fn [currency-id]
(get currency/currencies currency-id)))
(get currency/currencies currency-id (get currency/currencies :usd))))
(defn filter-recipient-favs
[search-filter {:keys [name]}]
@@ -0,0 +1,11 @@
(ns utils.worklets.onboarding-carousel)
(def worklets (js/require "../src/js/worklets/onboarding_carousel.js"))
(defn dynamic-progress-bar-width
[static-progress-bar-width progress]
(.dynamicProgressBarWidth ^js worklets static-progress-bar-width progress))
(defn carousel-left-position
[window-width progress]
(.carouselLeftPosition ^js worklets window-width progress))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.141.1",
"commit-sha1": "458f28178ca15732df8e6c806ef5326fad44427c",
"src-sha256": "1hhfswn17dja62rxkb572afd6fsx86wfxs4j666lhscdz7zzs4gx"
"version": "v0.142.5",
"commit-sha1": "7c2b5a39b370ceb9276a01b53cf9fb966bfe9d5b",
"src-sha256": "0rppkkkhhjzq6sykv34r3y3sslv821jjzd319f9bh3lybqqy5jp3"
}
+1 -1
View File
@@ -50,7 +50,7 @@ pytest_config_global = dict()
test_suite_data = TestSuiteData()
appium_container = AppiumContainer()
common_password = 'qwerty'
common_password = 'qwerty1234'
unique_password = 'unique' + get_current_time()
pin = '121212'
puk = '000000000000'
+1 -1
View File
@@ -212,7 +212,7 @@ def pytest_configure(config):
sauce.storage.upload(file_path)
os.remove(file_path)
break
except ConnectionError:
except (ConnectionError, RemoteDisconnected):
sleep(10)
else:
sauce.storage.upload(config.getoption('apk'))
@@ -154,8 +154,8 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
run_in_parallel(
(
(sign_in_views[0].create_user, {'enable_notifications': True}),
(sign_in_views[1].create_user, {'enable_notifications': True}),
(sign_in_views[2].create_user, {'enable_notifications': True})
(sign_in_views[1].create_user, {'enable_notifications': True, 'username': "test user1"}),
(sign_in_views[2].create_user, {'enable_notifications': True, 'username': "test user2"})
)
)
)
@@ -494,7 +494,12 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase):
'yotube_full': {
'url': 'https://www.youtube.com/watch?v=XN-SVmuJH2g&list=PLbrz7IuP1hrgNtYe9g6YHwHO6F3OqNMao',
'txt': 'Status & Keycard Hardware-Enforced Security',
'subtitle': 'YouTube'}
'subtitle': 'YouTube'},
'yotube_mobile': {
'url': 'https://m.youtube.com/watch?v=Je7yErjEVt4',
'txt': 'Status, your gateway to Ethereum',
'subtitle': 'YouTube'},
# twitter link is temporary removed from check as current xpath locator in message.preview_title is not applicable for this type of links
# 'twitter': {
# 'url': 'https://twitter.com/ethdotorg/status/1445161651771162627?s=20',
@@ -95,6 +95,7 @@ class TestActivityCenterContactRequestMultipleDevicePR(MultipleSharedDeviceTestC
[home.chats_tab.click() for home in [self.home_1, self.home_2]]
@marks.testrail_id(702850)
@marks.xfail(reason="Blocked by 15500")
def test_activity_center_contact_request_decline(self):
self.device_1.put_app_to_background()
self.device_2.just_fyi('Device2 sends a contact request to Device1 via Paste button and check user details')
@@ -183,8 +184,8 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
self.drivers, self.loop = create_shared_drivers(2)
self.device_1, self.device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
self.loop.run_until_complete(
run_in_parallel(((self.device_1.create_user, ),
(self.device_2.create_user,))))
run_in_parallel(((self.device_1.create_user, {'username': 'user1'}),
(self.device_2.create_user, {'username': 'user2'}))))
self.home_1, self.home_2 = self.device_1.get_home_view(), self.device_2.get_home_view()
self.profile_1, self.profile_2 = self.home_1.get_profile_view(), self.home_2.get_profile_view()
users = self.loop.run_until_complete(run_in_parallel(
@@ -331,6 +332,7 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@marks.testrail_id(702957)
@marks.xfail(reason="Blocked by 15500")
def test_activity_center_mentions(self):
self.home_1.jump_to_communities_home()
self.home_2.jump_to_card_by_text('# %s' % self.channel_name)
@@ -365,6 +367,7 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@marks.testrail_id(702958)
@marks.xfail(reason="Blocked by 15500")
def test_activity_center_admin_notification_accept_swipe(self):
self.home_2.just_fyi("Clearing history")
self.home_2.jump_to_messages_home()
@@ -380,7 +383,7 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
community_element = self.home_1.get_chat(community_name, community=True)
self.community_1.share_community(community_element, self.default_username_2)
self.home_1.just_fyi("Request access to community")
self.home_2.just_fyi("Request access to community")
self.home_2.jump_to_messages_home()
self.chat_2 = self.home_2.get_chat(self.default_username_1).click()
self.chat_2.element_by_text_part('View').click()
+2 -2
View File
@@ -595,11 +595,11 @@ class BaseView(object):
def jump_to_messages_home(self):
self.jump_to_button.click()
self.chats_tab.click()
self.chats_tab.click_until_presence_of_element(self.jump_to_button)
def jump_to_communities_home(self):
self.jump_to_button.click()
self.communities_tab.click()
self.communities_tab.click_until_presence_of_element(self.jump_to_button)
def jump_to_card_by_text(self, text: str):
self.jump_to_button.click()
+1 -1
View File
@@ -637,7 +637,7 @@ class UnpinMessagePopUp(BaseElement):
class PinnedMessagesList(BaseElement):
def __init__(self, driver):
super().__init__(driver, xpath="//*[@content-desc='pinned-messages-list']")
super().__init__(driver, xpath="//*[@content-desc='pinned-messages-menu']")
def get_pinned_messages_number(self):
self.driver.info("Getting number of pinned messages inside pinned messages list element")
+56 -38
View File
@@ -140,11 +140,8 @@ class SignInView(BaseView):
xpath="(//android.widget.EditText[@content-desc='password-input'])[1]")
self.confirm_your_password_input = EditBox(self.driver,
xpath="(//android.widget.EditText[@content-desc='password-input'])[2]")
self.enable_notifications_button = Button(self.driver, accessibility_id="enable-notifications-button")
self.maybe_later_button = Button(self.driver, accessibility_id="enable-notifications-later-button")
self.privacy_policy_link = PrivacyPolicyLink(self.driver)
self.terms_of_use_link = TermsOfUseLink(self.driver)
self.start_button = Button(self.driver, accessibility_id="welcome-button")
self.keycard_storage_button = KeycardKeyStorageButton(self.driver)
self.first_username_on_choose_chat_name = Text(self.driver,
xpath="//*[@content-desc='select-account-button-0']//android.widget.TextView[1]")
@@ -177,60 +174,81 @@ class SignInView(BaseView):
self.continue_custom_seed_phrase_button = Button(self.driver, accessibility_id="continue-custom-seed-phrase")
self.cancel_custom_seed_phrase_button = Button(self.driver, accessibility_id="cancel-custom-seed-phrase")
def create_user(self, password=common_password, keycard=False, enable_notifications=False, second_user=False):
# New onboarding
self.generate_keys_button = Button(self.driver, translation_id="create-multiaccount")
self.profile_your_name_edit_box = EditBox(self.driver, accessibility_id="profile-title-input")
self.profile_continue_button = Button(self.driver, accessibility_id="submit-create-profile-button")
self.profile_password_edit_box = EditBox(self.driver, translation_id="password-creation-placeholder-1")
self.profile_repeat_password_edit_box = EditBox(self.driver, translation_id="password-creation-placeholder-2")
self.profile_confirm_password_button = Button(self.driver, translation_id="password-creation-confirm")
self.enable_biometric_maybe_later_button = Button(self.driver, translation_id="maybe-later")
self.enable_notifications_button = Button(self.driver, accessibility_id="enable-notifications-button")
self.maybe_later_button = Button(self.driver, accessibility_id="enable-notifications-later-button")
self.start_button = Button(self.driver, accessibility_id="welcome-button")
self.use_recovery_phrase_button = Button(self.driver, translation_id="use-recovery-phrase")
self.passphrase_edit_box = EditBox(self.driver, accessibility_id="use-recovery-phrase")
def set_password(self, password: str):
self.profile_password_edit_box.set_value(password)
self.profile_repeat_password_edit_box.click()
self.profile_repeat_password_edit_box.send_keys(password)
self.checkbox_button.scroll_to_element()
self.checkbox_button.double_click()
self.profile_confirm_password_button.click()
def set_profile(self, username: str, set_image=False):
self.profile_your_name_edit_box.set_value(username)
self.profile_continue_button.click_until_presence_of_element(self.profile_password_edit_box)
if set_image:
pass
def create_user(self, password=common_password, keycard=False, enable_notifications=False, second_user=False,
username="test user"):
self.driver.info("## Creating new multiaccount (password:'%s', keycard:'%s', enable_notification: '%s')" %
(password, str(keycard), str(enable_notifications)), device=False)
if not second_user:
self.i_m_new_in_status_button.click_until_presence_of_element(self.generate_key_button)
self.generate_key_button.click()
self.next_button.click_until_absense_of_element(self.element_by_translation_id("intro-wizard-title2"))
if keycard:
keycard_flow = self.keycard_storage_button.click()
keycard_flow.confirm_pin_and_proceed()
keycard_flow.backup_seed_phrase()
else:
self.next_button.click()
self.create_password_input.set_value(password)
self.confirm_your_password_input.set_value(password)
self.next_button.click()
self.i_m_new_in_status_button.click_until_presence_of_element(self.generate_keys_button)
self.generate_keys_button.click_until_presence_of_element(self.profile_your_name_edit_box)
self.set_profile(username)
self.set_password(password)
self.enable_biometric_maybe_later_button.wait_and_click(30)
# self.next_button.click_until_absense_of_element(self.element_by_translation_id("intro-wizard-title2"))
# if keycard:
# keycard_flow = self.keycard_storage_button.click()
# keycard_flow.confirm_pin_and_proceed()
# keycard_flow.backup_seed_phrase()
# else:
# self.next_button.click()
# self.create_password_input.set_value(password)
# self.confirm_your_password_input.set_value(password)
# self.next_button.click()
if enable_notifications:
self.enable_notifications_button.click_until_presence_of_element(self.start_button)
else:
self.maybe_later_button.click_until_presence_of_element(self.start_button)
self.start_button.click()
self.chats_tab.wait_for_visibility_of_element(30)
self.driver.info("## New multiaccount is created successfully!", device=False)
return self.get_home_view()
def recover_access(self, passphrase: str, password: str = common_password, keycard=False,
enable_notifications=False, second_user=False):
def recover_access(self, passphrase: str, password: str = common_password+'1234', keycard=False,
enable_notifications=False, second_user=False, username='Restore user', set_image=False):
self.driver.info("## Recover access(password:%s, keycard:%s)" % (password, str(keycard)), device=False)
if not second_user:
self.accept_tos_checkbox.enable()
self.get_started_button.click_until_presence_of_element(self.access_key_button)
self.access_key_button.click()
self.enter_seed_phrase_button.click()
self.seedphrase_input.click()
self.seedphrase_input.set_value(passphrase)
self.next_button.click()
self.reencrypt_your_key_button.click()
if keycard:
keycard_flow = self.keycard_storage_button.click()
keycard_flow.confirm_pin_and_proceed()
else:
self.next_button.click()
self.create_password_input.set_value(password)
self.confirm_your_password_input.set_value(password)
self.next_button.click_until_presence_of_element(self.maybe_later_button)
self.maybe_later_button.wait_for_element(30)
self.i_m_new_in_status_button.click_until_presence_of_element(self.generate_keys_button)
self.use_recovery_phrase_button.click()
self.passphrase_edit_box.set_value(passphrase)
self.continue_button.click_until_presence_of_element(self.profile_your_name_edit_box)
self.set_profile(username, set_image)
self.set_password(password)
self.enable_biometric_maybe_later_button.wait_and_click(30)
if enable_notifications:
self.enable_notifications_button.click_until_presence_of_element(self.start_button)
else:
self.maybe_later_button.click_until_presence_of_element(self.start_button)
self.start_button.click()
self.profile_button.wait_for_visibility_of_element(30)
self.chats_tab.wait_for_visibility_of_element(30)
self.driver.info("## Multiaccount is recovered successfully!", device=False)
return self.get_home_view()
+4 -2
View File
@@ -2030,7 +2030,7 @@
"logged-in": "Logged in",
"profiles-on-device": "Profiles on device",
"profile-password": "Profile password",
"forget-password": "Forgot password?",
"forgot-password": "Forgot password?",
"log-in": "Log in",
"type-your-password": "Type your password",
"oops-wrong-password": "Oops, wrong password!",
@@ -2054,5 +2054,7 @@
"error-syncing-connection-failed": "Oops! Connection failed. Try again",
"camera-permission-denied": "Permission denied",
"enable-biometrics": "Enable biometrics",
"use-biometrics": "Use biometrics to fill in your password"
"use-biometrics": "Use biometrics to fill in your password",
"name-must-have-at-least-characters": "Name must have at least {{min-chars}} characters",
"name-is-not-valid": "Name is not valid"
}