Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99ccf59b0a | ||
|
|
4efa75b758 | ||
|
|
81a8ed95a7 | ||
|
|
2a81814992 | ||
|
|
bcdb3c4194 | ||
|
|
54c3030971 | ||
|
|
d765dd1f60 | ||
|
|
777d0581ce | ||
|
|
6f45b5c8e8 | ||
|
|
e219aaf2b0 | ||
|
|
44a449660a | ||
|
|
9891469c6f | ||
|
|
5e9738bb7d | ||
|
|
39e3a82228 | ||
|
|
23a3825237 | ||
|
|
98f78ba50b | ||
|
|
1b5f08d680 | ||
|
|
411fd843ca | ||
|
|
1e8d85983e | ||
|
|
960e338f48 | ||
|
|
8ac0823eef | ||
|
|
1964200332 |
@@ -34,3 +34,4 @@ COLLECTIBLES_ENABLED=1
|
|||||||
COMMANDS_ENABLED=1
|
COMMANDS_ENABLED=1
|
||||||
TWO_MINUTES_SYNCING=1
|
TWO_MINUTES_SYNCING=1
|
||||||
SWAP_ENABLED=1
|
SWAP_ENABLED=1
|
||||||
|
STICKERS_TEST_ENABLED=1
|
||||||
|
|||||||
@@ -34,3 +34,4 @@ COMMUNITIES_MANAGEMENT_ENABLED=1
|
|||||||
METRICS_ENABLED=0
|
METRICS_ENABLED=0
|
||||||
DELETE_MESSAGE_ENABLED=1
|
DELETE_MESSAGE_ENABLED=1
|
||||||
TWO_MINUTES_SYNCING=1
|
TWO_MINUTES_SYNCING=1
|
||||||
|
STICKERS_TEST_ENABLED=1
|
||||||
@@ -37,3 +37,4 @@ METRICS_ENABLED=0
|
|||||||
DELETE_MESSAGE_ENABLED=1
|
DELETE_MESSAGE_ENABLED=1
|
||||||
TWO_MINUTES_SYNCING=1
|
TWO_MINUTES_SYNCING=1
|
||||||
ENABLE_QUO_PREVIEW=1
|
ENABLE_QUO_PREVIEW=1
|
||||||
|
STICKERS_TEST_ENABLED=1
|
||||||
@@ -17,12 +17,12 @@ buildscript {
|
|||||||
repositories {
|
repositories {
|
||||||
flatDir { dirs "libs", "${rootDir}/app/libs" }
|
flatDir { dirs "libs", "${rootDir}/app/libs" }
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
|
||||||
classpath "com.android.tools.build:gradle:${project.ext.gradlePluginVersion}"
|
classpath "com.android.tools.build:gradle:${project.ext.gradlePluginVersion}"
|
||||||
classpath "com.google.gms:google-services:4.3.10"
|
classpath "com.google.gms:google-services:4.3.10"
|
||||||
// WARNING: Do not place your application dependencies here!
|
// WARNING: Do not place your application dependencies here!
|
||||||
// They belong in the individual module build.gradle files.
|
// They belong in the individual module build.gradle files.
|
||||||
}
|
}
|
||||||
@@ -45,27 +45,22 @@ subprojects {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
beforeEvaluate {
|
beforeEvaluate {
|
||||||
if (System.env.STATUS_GO_ANDROID_LIBDIR == null || System.env.STATUS_GO_ANDROID_LIBDIR == "") {
|
if (System.env.STATUS_GO_ANDROID_LIBDIR == null || System.env.STATUS_GO_ANDROID_LIBDIR == "") {
|
||||||
throw new GradleException('STATUS_GO_ANDROID_LIBDIR environment variable is not valid!')
|
throw new GradleException('STATUS_GO_ANDROID_LIBDIR environment variable is not valid!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
maven { url("$rootDir/../node_modules/react-native/android") }
|
||||||
url("$rootDir/../node_modules/react-native/android")
|
// Android JSC is installed from npm
|
||||||
}
|
maven { url("$rootDir/../node_modules/jsc-android/dist") }
|
||||||
maven {
|
// For geth, function, and status-go
|
||||||
// Android JSC is installed from npm
|
|
||||||
url("$rootDir/../node_modules/jsc-android/dist")
|
|
||||||
}
|
|
||||||
|
|
||||||
google()
|
|
||||||
jcenter()
|
|
||||||
|
|
||||||
// for geth, function, and status-go
|
|
||||||
flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR }
|
flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR }
|
||||||
|
// Everything Else
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
maven { url "https://www.jitpack.io" }
|
maven { url "https://www.jitpack.io" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
library 'status-jenkins-lib@v1.4.1'
|
library 'status-jenkins-lib@v1.4.1'
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
agent { label 'linux && x86_64 && nix-2.6' }
|
agent { label 'linux && x86_64 && nix-2.8' }
|
||||||
|
|
||||||
options {
|
options {
|
||||||
timestamps()
|
timestamps()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
library 'status-jenkins-lib@v1.4.1'
|
library 'status-jenkins-lib@v1.4.1'
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
agent { label 'macos && x86_64 && nix-2.6 && xcode-12.5' }
|
agent { label 'macos && x86_64 && nix-2.8 && xcode-13.3' }
|
||||||
|
|
||||||
parameters {
|
parameters {
|
||||||
string(
|
string(
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ pipeline {
|
|||||||
nix.shell("""
|
nix.shell("""
|
||||||
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
|
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
|
||||||
-not -name '*.links' -and -not -name '*-status-react-*' \
|
-not -name '*.links' -and -not -name '*-status-react-*' \
|
||||||
| xargs nix-copy-closure -v \
|
| xargs nix copy \
|
||||||
--to ${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
|
--to ssh-ng://${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
|
||||||
""",
|
""",
|
||||||
pure: false
|
pure: false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pipeline {
|
|||||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||||
sh """
|
sh """
|
||||||
python3 -m pytest \
|
python3 -m pytest \
|
||||||
--numprocesses 15 \
|
--numprocesses 9 \
|
||||||
--rerun_count=2 \
|
--rerun_count=2 \
|
||||||
--testrail_report=True \
|
--testrail_report=True \
|
||||||
-m testrail_id \
|
-m testrail_id \
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Modules provided by `yarn2nix` are normally fine, but we use `react-native-*` pa
|
|||||||
```js
|
```js
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven { url "https://www.jitpack.io" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
And these need to be patched and replaced with `mavenLocal()` to make sure Gradle doesn't try to fetch dependencies from remote repos.
|
And these need to be patched and replaced with `mavenLocal()` to make sure Gradle doesn't try to fetch dependencies from remote repos.
|
||||||
|
|||||||
@@ -11,3 +11,5 @@ keep-derivations = true
|
|||||||
keep-outputs = true
|
keep-outputs = true
|
||||||
# Extra isolation for network and filesystem, doesn't work on MacOS
|
# Extra isolation for network and filesystem, doesn't work on MacOS
|
||||||
build-use-sandbox = false
|
build-use-sandbox = false
|
||||||
|
# Enable Nix v2 interface.
|
||||||
|
experimental-features = nix-command
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ in {
|
|||||||
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
|
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
|
||||||
|
|
||||||
# Package version adjustments
|
# Package version adjustments
|
||||||
go = super.pkgs.go_1_16;
|
go = super.pkgs.go_1_17;
|
||||||
gradle = super.pkgs.gradle_5;
|
gradle = super.pkgs.gradle_5;
|
||||||
nodejs = super.pkgs.nodejs-12_x;
|
nodejs = super.pkgs.nodejs-16_x;
|
||||||
openjdk = super.pkgs.openjdk8_headless;
|
openjdk = super.pkgs.openjdk8_headless;
|
||||||
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
|
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
|
||||||
version = "11.5";
|
version = "13.3";
|
||||||
allowHigher = true;
|
allowHigher = true;
|
||||||
};
|
};
|
||||||
gomobile = super.gomobile.override {
|
gomobile = super.gomobile.override {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ let
|
|||||||
name = "nixpkgs-source";
|
name = "nixpkgs-source";
|
||||||
owner = "status-im";
|
owner = "status-im";
|
||||||
repo = "nixpkgs";
|
repo = "nixpkgs";
|
||||||
rev = "15111f8a9ad423d300886b537647691c2faa28cd";
|
rev = "4ba5f26780e7a27aa2e97676603cd9ef04f11e74";
|
||||||
sha256 = "05ny644x3dpxigljnb4rmams5vrs5gkbcyqjfamvlqm8rdmsi0kn";
|
sha256 = "sha256-ZpHXUuF9bvHooKwGuR1Mr/n2mE/LJ6/MCdCk2AfdD9M=";
|
||||||
# To get the compressed Nix sha256, use:
|
# To get the compressed Nix sha256, use:
|
||||||
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
|
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
|
|||||||
source "${GIT_ROOT}/nix/scripts/lib.sh"
|
source "${GIT_ROOT}/nix/scripts/lib.sh"
|
||||||
source "${GIT_ROOT}/scripts/colors.sh"
|
source "${GIT_ROOT}/scripts/colors.sh"
|
||||||
|
|
||||||
NIX_VERSION="2.6.1"
|
NIX_VERSION="2.8.0"
|
||||||
NIX_INSTALL_URL="https://nixos.org/releases/nix/nix-${NIX_VERSION}/install"
|
NIX_INSTALL_URL="https://nixos.org/releases/nix/nix-${NIX_VERSION}/install"
|
||||||
NIX_INSTALL_SHA256="a63732b4f3628ce97e096dbda88e3cb9851ff6b4f94b5cd43feb257126437b9d"
|
NIX_INSTALL_SHA256="f43bfedfca9151479462d8bc11f238615a2d52f19b14894d8e2b59980e75ef72"
|
||||||
NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}"
|
NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}"
|
||||||
|
|
||||||
install_nix() {
|
install_nix() {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
"react-native-safe-area-context": "^2.0.0",
|
"react-native-safe-area-context": "^2.0.0",
|
||||||
"react-native-shake": "^3.3.1",
|
"react-native-shake": "^3.3.1",
|
||||||
"react-native-share": "^7.0.1",
|
"react-native-share": "^7.0.1",
|
||||||
"react-native-splash-screen": "^3.2.0",
|
"react-native-splash-screen": "3.3.0",
|
||||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.37",
|
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.37",
|
||||||
"react-native-svg": "^9.8.4",
|
"react-native-svg": "^9.8.4",
|
||||||
"react-native-touch-id": "^4.4.1",
|
"react-native-touch-id": "^4.4.1",
|
||||||
|
|||||||
|
After Width: | Height: | Size: 396 B |
|
After Width: | Height: | Size: 608 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 679 B |
|
After Width: | Height: | Size: 610 B |
|
After Width: | Height: | Size: 941 B |
|
After Width: | Height: | Size: 836 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 813 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 735 B |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -47,6 +47,7 @@
|
|||||||
:ValueXY (fn [])
|
:ValueXY (fn [])
|
||||||
:View {}
|
:View {}
|
||||||
:FlatList {}
|
:FlatList {}
|
||||||
|
:Image {}
|
||||||
:ScrollView {}
|
:ScrollView {}
|
||||||
:Text {}}
|
:Text {}}
|
||||||
:Easing {:bezier (fn [])
|
:Easing {:bezier (fn [])
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
["@react-native-community/hooks" :as hooks]
|
["@react-native-community/hooks" :as hooks]
|
||||||
["react-native-navigation" :refer (Navigation)]
|
["react-native-navigation" :refer (Navigation)]
|
||||||
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
|
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
|
||||||
["react-native-draggable-flatlist" :default DraggableFlatList]))
|
["react-native-draggable-flatlist" :default DraggableFlatList]
|
||||||
|
[status-im.utils.config :as config]))
|
||||||
|
|
||||||
(def rn-draggable-flatlist (reagent/adapt-react-class DraggableFlatList))
|
(def rn-draggable-flatlist (reagent/adapt-react-class DraggableFlatList))
|
||||||
|
|
||||||
@@ -74,6 +75,9 @@
|
|||||||
(def animated-view
|
(def animated-view
|
||||||
(reagent/adapt-react-class (.-View ^js animated)))
|
(reagent/adapt-react-class (.-View ^js animated)))
|
||||||
|
|
||||||
|
(def animated-image-view
|
||||||
|
(reagent/adapt-react-class (.-Image ^js animated)))
|
||||||
|
|
||||||
(def ui-manager (.-UIManager ^js rn))
|
(def ui-manager (.-UIManager ^js rn))
|
||||||
|
|
||||||
(def layout-animation (.-LayoutAnimation ^js rn))
|
(def layout-animation (.-LayoutAnimation ^js rn))
|
||||||
@@ -103,6 +107,10 @@
|
|||||||
:delete #js {:type (:ease-in-ease-out layout-animation-types)
|
:delete #js {:type (:ease-in-ease-out layout-animation-types)
|
||||||
:property (:opacity layout-animation-properties)}}})
|
:property (:opacity layout-animation-properties)}}})
|
||||||
|
|
||||||
|
(defonce enable-layout-animations
|
||||||
|
(when (and platform/android? config/quo-preview-enabled?)
|
||||||
|
(.setLayoutAnimationEnabledExperimental ^js ui-manager true)))
|
||||||
|
|
||||||
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js rn)))
|
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js rn)))
|
||||||
|
|
||||||
;; Flat-list
|
;; Flat-list
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
[_ _]
|
[_ _]
|
||||||
(let [pressed (reagent/atom false)]
|
(let [pressed (reagent/atom false)]
|
||||||
(fn [{:keys [on-press disabled type size before after above width
|
(fn [{:keys [on-press disabled type size before after above width
|
||||||
on-long-press accessibility-label icon]
|
on-long-press accessibility-label icon style]
|
||||||
:or {type :primary
|
:or {type :primary
|
||||||
size 40}}
|
size 40}}
|
||||||
children]
|
children]
|
||||||
@@ -126,17 +126,19 @@
|
|||||||
{:on-press-out (fn []
|
{:on-press-out (fn []
|
||||||
(reset! pressed nil))})
|
(reset! pressed nil))})
|
||||||
|
|
||||||
[rn/view {:style (style-container
|
[rn/view {:style (merge
|
||||||
type
|
(style-container
|
||||||
size
|
type
|
||||||
disabled
|
size
|
||||||
(get background-color state)
|
disabled
|
||||||
(get border-color state)
|
(get background-color state)
|
||||||
icon
|
(get border-color state)
|
||||||
above
|
icon
|
||||||
width
|
above
|
||||||
before
|
width
|
||||||
after)}
|
before
|
||||||
|
after)
|
||||||
|
style)}
|
||||||
(when above
|
(when above
|
||||||
[rn/view
|
[rn/view
|
||||||
[quo2.icons/icon above {:container-style {:margin-bottom 2}
|
[quo2.icons/icon above {:container-style {:margin-bottom 2}
|
||||||
@@ -168,4 +170,4 @@
|
|||||||
[quo2.icons/icon after {:container-style {:margin-left 4
|
[quo2.icons/icon after {:container-style {:margin-left 4
|
||||||
:margin-right (if (= size 40) 12 8)}
|
:margin-right (if (= size 40) 12 8)}
|
||||||
:color icon-color
|
:color icon-color
|
||||||
:size icon-size}]])]]))))
|
:size icon-size}]])]]))))
|
||||||
|
|||||||
@@ -29,5 +29,6 @@
|
|||||||
(let [this (reagent/current-component)
|
(let [this (reagent/current-component)
|
||||||
props (reagent/props this)
|
props (reagent/props this)
|
||||||
style (text-style props)]
|
style (text-style props)]
|
||||||
(into [rn/text {:style style}]
|
(into [rn/text (merge {:style style}
|
||||||
(reagent/children this))))
|
(dissoc props :style :size :align :weight :color))]
|
||||||
|
(reagent/children this))))
|
||||||
|
|||||||
@@ -34,6 +34,13 @@
|
|||||||
(def neutral-50-opa-30 (alpha neutral-50 0.3))
|
(def neutral-50-opa-30 (alpha neutral-50 0.3))
|
||||||
(def neutral-50-opa-40 (alpha neutral-50 0.4))
|
(def neutral-50-opa-40 (alpha neutral-50 0.4))
|
||||||
|
|
||||||
|
;;70 with transparency
|
||||||
|
(def neutral-70-opa-60 (alpha neutral-70 0.6))
|
||||||
|
(def neutral-70-opa-70 (alpha neutral-70 0.7))
|
||||||
|
(def neutral-70-opa-80 (alpha neutral-70 0.8))
|
||||||
|
(def neutral-70-opa-90 (alpha neutral-70 0.9))
|
||||||
|
(def neutral-70-opa-95 (alpha neutral-70 0.95))
|
||||||
|
|
||||||
;;80 with transparency
|
;;80 with transparency
|
||||||
(def neutral-80-opa-60 (alpha neutral-80 0.6))
|
(def neutral-80-opa-60 (alpha neutral-80 0.6))
|
||||||
(def neutral-80-opa-70 (alpha neutral-80 0.7))
|
(def neutral-80-opa-70 (alpha neutral-80 0.7))
|
||||||
@@ -176,5 +183,15 @@
|
|||||||
(def info-50-opa-30 (alpha info-50 0.3))
|
(def info-50-opa-30 (alpha info-50 0.3))
|
||||||
(def info-50-opa-40 (alpha info-50 0.4))
|
(def info-50-opa-40 (alpha info-50 0.4))
|
||||||
|
|
||||||
|
;;;;Switcher
|
||||||
|
(def switcher-background "#040B14")
|
||||||
|
|
||||||
|
;;switcher-screen with transparency
|
||||||
|
(def switcher-background-opa-60 (alpha switcher-background 0.6))
|
||||||
|
(def switcher-background-opa-70 (alpha switcher-background 0.7))
|
||||||
|
(def switcher-background-opa-80 (alpha switcher-background 0.8))
|
||||||
|
(def switcher-background-opa-90 (alpha switcher-background 0.9))
|
||||||
|
(def switcher-background-opa-95 (alpha switcher-background 0.95))
|
||||||
|
|
||||||
(defn theme-colors [light dark]
|
(defn theme-colors [light dark]
|
||||||
(if (theme/dark?) dark light))
|
(if (theme/dark?) dark light))
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.navigation :as navigation]
|
[status-im.navigation :as navigation]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.utils.http :as http]
|
[status-im.utils.http :as http]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
@@ -182,20 +181,6 @@
|
|||||||
:history new-history
|
:history new-history
|
||||||
:history-index new-index))))))
|
:history-index new-index))))))
|
||||||
|
|
||||||
(defmulti storage-gateway :namespace)
|
|
||||||
|
|
||||||
(defmethod storage-gateway :ipns
|
|
||||||
[{:keys [hash]}]
|
|
||||||
(str "https://" hash))
|
|
||||||
|
|
||||||
(defmethod storage-gateway :ipfs
|
|
||||||
[{:keys [hash]}]
|
|
||||||
(contenthash/ipfs-url hash))
|
|
||||||
|
|
||||||
(defmethod storage-gateway :swarm
|
|
||||||
[{:keys [hash]}]
|
|
||||||
(str "https://gateway.ethswarm.org/bzz/" hash))
|
|
||||||
|
|
||||||
(fx/defn resolve-ens-multihash-success
|
(fx/defn resolve-ens-multihash-success
|
||||||
{:events [:browser.callback/resolve-ens-multihash-success]}
|
{:events [:browser.callback/resolve-ens-multihash-success]}
|
||||||
[{:keys [db] :as cofx} url]
|
[{:keys [db] :as cofx} url]
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.navigation :as navigation]
|
[status-im.navigation :as navigation]
|
||||||
|
[status-im.navigation2 :as navigation2]
|
||||||
[status-im.utils.clocks :as utils.clocks]
|
[status-im.utils.clocks :as utils.clocks]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
@@ -263,6 +264,15 @@
|
|||||||
(navigation/pop-to-root-tab % :chat-stack))
|
(navigation/pop-to-root-tab % :chat-stack))
|
||||||
(navigation/navigate-to-cofx :chat nil))))
|
(navigation/navigate-to-cofx :chat nil))))
|
||||||
|
|
||||||
|
(fx/defn navigate-to-chat-nav2
|
||||||
|
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||||
|
{:events [:chat.ui/navigate-to-chat-nav2]}
|
||||||
|
[{db :db :as cofx} chat-id from-switcher?]
|
||||||
|
(fx/merge cofx
|
||||||
|
{:db (assoc db :current-chat-id chat-id)}
|
||||||
|
(preload-chat-data chat-id)
|
||||||
|
(navigation2/navigate-to-nav2 :chat chat-id nil from-switcher?)))
|
||||||
|
|
||||||
(fx/defn handle-clear-history-response
|
(fx/defn handle-clear-history-response
|
||||||
{:events [::history-cleared]}
|
{:events [::history-cleared]}
|
||||||
[{:keys [db]} chat-id response]
|
[{:keys [db]} chat-id response]
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
["emojilib" :as emojis]
|
["emojilib" :as emojis]
|
||||||
[status-im.chat.models.mentions :as mentions]
|
[status-im.chat.models.mentions :as mentions]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]))
|
||||||
[status-im.multiaccounts.update.core :as multiaccounts.update]))
|
|
||||||
|
|
||||||
(defn text->emoji
|
(defn text->emoji
|
||||||
"Replaces emojis in a specified `text`"
|
"Replaces emojis in a specified `text`"
|
||||||
@@ -230,12 +229,12 @@
|
|||||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})})))
|
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})})))
|
||||||
|
|
||||||
(fx/defn send-sticker-message
|
(fx/defn send-sticker-message
|
||||||
[cofx {:keys [hash pack]} current-chat-id]
|
[cofx {:keys [hash packID]} current-chat-id]
|
||||||
(when-not (string/blank? hash)
|
(when-not (or (string/blank? hash) (string/blank? packID))
|
||||||
(chat.message/send-message cofx {:chat-id current-chat-id
|
(chat.message/send-message cofx {:chat-id current-chat-id
|
||||||
:content-type constants/content-type-sticker
|
:content-type constants/content-type-sticker
|
||||||
:sticker {:hash hash
|
:sticker {:hash hash
|
||||||
:pack pack}
|
:pack (int packID)}
|
||||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||||
|
|
||||||
(fx/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id]}]
|
(fx/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id]}]
|
||||||
@@ -265,13 +264,16 @@
|
|||||||
|
|
||||||
(fx/defn chat-send-sticker
|
(fx/defn chat-send-sticker
|
||||||
{:events [:chat/send-sticker]}
|
{:events [:chat/send-sticker]}
|
||||||
[{{:keys [current-chat-id multiaccount]} :db :as cofx} {:keys [hash] :as sticker}]
|
[{{:keys [current-chat-id] :as db} :db :as cofx} {:keys [hash packID] :as sticker}]
|
||||||
(fx/merge
|
(fx/merge
|
||||||
cofx
|
cofx
|
||||||
(multiaccounts.update/multiaccount-update
|
{:db (update db
|
||||||
:stickers/recent-stickers
|
:stickers/recent-stickers
|
||||||
(conj (remove #(= hash %) (:stickers/recent-stickers multiaccount)) hash)
|
(fn [recent]
|
||||||
{})
|
(conj (remove #(= hash (:hash %)) recent) sticker)))
|
||||||
|
::json-rpc/call [{:method "stickers_addRecent"
|
||||||
|
:params [(int packID) hash]
|
||||||
|
:on-success #()}]}
|
||||||
(send-sticker-message sticker current-chat-id)))
|
(send-sticker-message sticker current-chat-id)))
|
||||||
|
|
||||||
(fx/defn chat-send-audio
|
(fx/defn chat-send-audio
|
||||||
|
|||||||
@@ -171,4 +171,8 @@
|
|||||||
(def ^:const visibility-status-inactive 4)
|
(def ^:const visibility-status-inactive 4)
|
||||||
|
|
||||||
(def ^:const wallet-connect-version-1 1)
|
(def ^:const wallet-connect-version-1 1)
|
||||||
(def ^:const wallet-connect-version-2 2)
|
(def ^:const wallet-connect-version-2 2)
|
||||||
|
|
||||||
|
(def ^:const sticker-pack-status-installed 1)
|
||||||
|
(def ^:const sticker-pack-status-pending 2)
|
||||||
|
(def ^:const sticker-pack-status-owned 3)
|
||||||
@@ -46,8 +46,6 @@
|
|||||||
config/default-network))
|
config/default-network))
|
||||||
(update :wallet/visible-tokens rpc->visible-tokens)
|
(update :wallet/visible-tokens rpc->visible-tokens)
|
||||||
(update :pinned-mailservers rpc->pinned-mailservers)
|
(update :pinned-mailservers rpc->pinned-mailservers)
|
||||||
(update :stickers/packs-installed rpc->stickers-packs)
|
|
||||||
(update :stickers/packs-pending set)
|
|
||||||
(update :link-previews-enabled-sites set)
|
(update :link-previews-enabled-sites set)
|
||||||
(update :custom-bootnodes rpc->custom-bootnodes)
|
(update :custom-bootnodes rpc->custom-bootnodes)
|
||||||
(update :custom-bootnodes-enabled? rpc->custom-bootnodes)
|
(update :custom-bootnodes-enabled? rpc->custom-bootnodes)
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
:dimensions/window (dimensions/window)
|
:dimensions/window (dimensions/window)
|
||||||
:registry {}
|
:registry {}
|
||||||
:visibility-status-updates {}
|
:visibility-status-updates {}
|
||||||
:stickers/packs-owned #{}
|
|
||||||
:stickers/packs-pending #{}
|
:stickers/packs-pending #{}
|
||||||
:keycard {:nfc-enabled? false
|
:keycard {:nfc-enabled? false
|
||||||
:pin {:original []
|
:pin {:original []
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
#(re-frame/dispatch [::name-resolved username
|
#(re-frame/dispatch [::name-resolved username
|
||||||
(cond
|
(cond
|
||||||
(not public-key) :owned
|
(not public-key) :owned
|
||||||
(string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000")
|
(and (string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000") (not custom-domain?))
|
||||||
:invalid-ens
|
:invalid-ens
|
||||||
(= % public-key) :connected
|
(= % public-key) :connected
|
||||||
:else :connected-with-different-key)
|
:else :connected-with-different-key)
|
||||||
|
|||||||
@@ -209,6 +209,7 @@
|
|||||||
"wallet_loadTransferByHash" {}
|
"wallet_loadTransferByHash" {}
|
||||||
"wallet_getTokens" {};, %* [chainId]}
|
"wallet_getTokens" {};, %* [chainId]}
|
||||||
"wallet_getTokensBalancesForChainIDs" {};, %* [@[chainId], accounts, tokens]
|
"wallet_getTokensBalancesForChainIDs" {};, %* [@[chainId], accounts, tokens]
|
||||||
|
"wallet_fetchPrices" {}
|
||||||
"browsers_getBrowsers" {}
|
"browsers_getBrowsers" {}
|
||||||
"browsers_addBrowser" {}
|
"browsers_addBrowser" {}
|
||||||
"browsers_deleteBrowser" {}
|
"browsers_deleteBrowser" {}
|
||||||
@@ -241,7 +242,16 @@
|
|||||||
"mailservers_getChatRequestRanges" {}
|
"mailservers_getChatRequestRanges" {}
|
||||||
"mailservers_deleteChatRequestRange" {}
|
"mailservers_deleteChatRequestRange" {}
|
||||||
"appmetrics_saveAppMetrics" {}
|
"appmetrics_saveAppMetrics" {}
|
||||||
"appmetrics_getAppMetrics" {}})
|
"appmetrics_getAppMetrics" {}
|
||||||
|
"stickers_market" {}
|
||||||
|
"stickers_installed" {}
|
||||||
|
"stickers_install" {}
|
||||||
|
"stickers_addRecent" {}
|
||||||
|
"stickers_recent" {}
|
||||||
|
"stickers_buyPrepareTx" {}
|
||||||
|
"stickers_processPending" {}
|
||||||
|
"stickers_addPending" {}
|
||||||
|
"stickers_pending" {}})
|
||||||
|
|
||||||
(defn on-error-retry
|
(defn on-error-retry
|
||||||
[call-method {:keys [method number-of-retries delay on-error] :as arg}]
|
[call-method {:keys [method number-of-retries delay on-error] :as arg}]
|
||||||
|
|||||||
@@ -63,7 +63,9 @@
|
|||||||
[status-im.multiaccounts.login.core :as login.core]
|
[status-im.multiaccounts.login.core :as login.core]
|
||||||
[status-im.signing.core :as signing]
|
[status-im.signing.core :as signing]
|
||||||
status-im.wallet-connect.core
|
status-im.wallet-connect.core
|
||||||
status-im.wallet-connect-legacy.core))
|
status-im.wallet-connect-legacy.core
|
||||||
|
status-im.navigation2
|
||||||
|
status-im.navigation2.core))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:dismiss-keyboard
|
:dismiss-keyboard
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
[status-im.popover.core :as popover]
|
[status-im.popover.core :as popover]
|
||||||
[status-im.communities.core :as communities]
|
[status-im.communities.core :as communities]
|
||||||
[status-im.transport.core :as transport]
|
[status-im.transport.core :as transport]
|
||||||
[status-im.stickers.core :as stickers]
|
|
||||||
[status-im.mobile-sync-settings.core :as mobile-network]
|
[status-im.mobile-sync-settings.core :as mobile-network]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.utils.keychain.core :as keychain]
|
[status-im.utils.keychain.core :as keychain]
|
||||||
@@ -445,7 +444,6 @@
|
|||||||
(initialize-transactions-management-enabled)
|
(initialize-transactions-management-enabled)
|
||||||
(check-network-version network-id)
|
(check-network-version network-id)
|
||||||
(contact/initialize-contacts)
|
(contact/initialize-contacts)
|
||||||
(stickers/init-stickers-packs)
|
|
||||||
(initialize-browser)
|
(initialize-browser)
|
||||||
(mobile-network/on-network-status-change)
|
(mobile-network/on-network-status-change)
|
||||||
(get-group-chat-invitations)
|
(get-group-chat-invitations)
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
(ns status-im.navigation2
|
||||||
|
(:require [status-im.utils.fx :as fx]
|
||||||
|
[status-im.utils.datetime :as datetime]))
|
||||||
|
|
||||||
|
(def parent-stack (atom :home-stack))
|
||||||
|
|
||||||
|
(fx/defn init-root-nav2
|
||||||
|
{:events [:init-root-nav2]}
|
||||||
|
[_ root-id]
|
||||||
|
{:init-root-fx-nav2 root-id})
|
||||||
|
|
||||||
|
(fx/defn open-modal-nav2
|
||||||
|
{:events [:open-modal-nav2]}
|
||||||
|
[_ modal]
|
||||||
|
{:open-modal-fx-nav2 modal})
|
||||||
|
|
||||||
|
(fx/defn close-modal-nav2
|
||||||
|
{:events [:close-modal-nav2]}
|
||||||
|
[_ modal]
|
||||||
|
{:close-modal-fx-nav2 modal})
|
||||||
|
|
||||||
|
(defn navigate-from-home-stack [go-to-view-id id db]
|
||||||
|
(reset! parent-stack go-to-view-id)
|
||||||
|
{:navigate-to-fx-nav2 [go-to-view-id id]
|
||||||
|
:db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id
|
||||||
|
:id id
|
||||||
|
:clock (datetime/timestamp)})})
|
||||||
|
|
||||||
|
(defn navigate-from-switcher [go-to-view-id id db from-home?]
|
||||||
|
(reset! parent-stack go-to-view-id)
|
||||||
|
{:navigate-from-switcher-fx [go-to-view-id id from-home?]
|
||||||
|
:db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id
|
||||||
|
:id id
|
||||||
|
:clock (datetime/timestamp)})})
|
||||||
|
|
||||||
|
(fx/defn navigate-to-nav2
|
||||||
|
{:events [:navigate-to-nav2]}
|
||||||
|
[{:keys [db] :as cofx} go-to-view-id id screen-params from-switcher?]
|
||||||
|
(let [view-id (:view-id db)
|
||||||
|
stacks (:navigation2/navigation2-stacks db)
|
||||||
|
from-home? (= view-id :home-stack)]
|
||||||
|
(if from-switcher?
|
||||||
|
(navigate-from-switcher go-to-view-id id db from-home?)
|
||||||
|
(if from-home?
|
||||||
|
(navigate-from-home-stack go-to-view-id id db)
|
||||||
|
;; TODO(parvesh) - new stacks created from other screens should be stacked on current stack, instead of creating new entry
|
||||||
|
(navigate-from-home-stack go-to-view-id id db)))))
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
(ns status-im.navigation2.core
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-im.ui.screens.views :as views]
|
||||||
|
[status-im.navigation2.utils :as nav2-utils]
|
||||||
|
[status-im.navigation2.roots :as roots]
|
||||||
|
[status-im.navigation.roots :as nav-roots]
|
||||||
|
["react-native-navigation" :refer (Navigation)]))
|
||||||
|
|
||||||
|
(def tab-key-idx {:home 0
|
||||||
|
:communities 1
|
||||||
|
:wallet 2
|
||||||
|
:browser 3})
|
||||||
|
|
||||||
|
(defonce set-navigation-default-options
|
||||||
|
(.setDefaultOptions Navigation (clj->js {:options {:topBar {:visible false}}})))
|
||||||
|
|
||||||
|
;; TODO (parvesh) - improve open-modal and close-modal
|
||||||
|
(defn open-modal [comp]
|
||||||
|
(.showModal Navigation
|
||||||
|
(clj->js {:stack {:children
|
||||||
|
[{:component
|
||||||
|
{:name comp
|
||||||
|
:id comp
|
||||||
|
:options {:topBar {:visible false}}}}]}})))
|
||||||
|
|
||||||
|
(defn close-modal [_])
|
||||||
|
|
||||||
|
(defn close-all-modals []
|
||||||
|
(.dismissAllModals Navigation))
|
||||||
|
|
||||||
|
(defn get-id [comp id]
|
||||||
|
(str comp "-" id))
|
||||||
|
|
||||||
|
(defn get-options [show-topbar? options]
|
||||||
|
(if show-topbar?
|
||||||
|
(merge options
|
||||||
|
(nav-roots/status-bar-options)
|
||||||
|
(nav-roots/merge-top-bar (nav-roots/topbar-options) options))
|
||||||
|
{:topBar {:visible false}}))
|
||||||
|
|
||||||
|
(defn change-stack-root [[comp _]]
|
||||||
|
(let [{:keys [options]} (get views/screens comp)]
|
||||||
|
(.setStackRoot Navigation
|
||||||
|
(name comp)
|
||||||
|
(clj->js {:stack {:id comp
|
||||||
|
:children [{:component {:id comp
|
||||||
|
:name comp
|
||||||
|
:options (get-options false options)}}]}}))))
|
||||||
|
|
||||||
|
(defn navigate [[comp _]]
|
||||||
|
(let [{:keys [options]} (get views/screens comp)]
|
||||||
|
(reset! nav2-utils/container-stack-view-id comp)
|
||||||
|
(.push Navigation
|
||||||
|
(name :home-stack)
|
||||||
|
(clj->js {:stack {:id comp
|
||||||
|
:children [{:component {:id comp
|
||||||
|
:name comp
|
||||||
|
:options (get-options false options)}}]}}))))
|
||||||
|
|
||||||
|
(defn navigate-from-switcher [[comp id from-home?]]
|
||||||
|
(if from-home?
|
||||||
|
(navigate [comp id])
|
||||||
|
(change-stack-root [comp id])))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:init-root-fx-nav2
|
||||||
|
(fn [new-root-id]
|
||||||
|
(reset! nav2-utils/container-stack-view-id new-root-id)
|
||||||
|
(.setRoot Navigation (clj->js (get (roots/roots) new-root-id)))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx :open-modal-fx-nav2 open-modal)
|
||||||
|
|
||||||
|
(re-frame/reg-fx :close-modal-fx-nav2 close-modal)
|
||||||
|
|
||||||
|
(re-frame/reg-fx :navigate-to-fx-nav2 navigate)
|
||||||
|
|
||||||
|
(re-frame/reg-fx :navigate-from-switcher-fx navigate-from-switcher)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
(ns status-im.navigation2.home-stack
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[quo2.screens.main :as quo2.preview]
|
||||||
|
[status-im.switcher.switcher :as switcher]
|
||||||
|
[status-im.ui.screens.home.views :as home]
|
||||||
|
[status-im.switcher.constants :as switcher-constants]
|
||||||
|
[status-im.ui.screens.browser.empty-tab.views :as empty-tab]
|
||||||
|
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||||
|
[status-im.switcher.bottom-tabs :as bottom-tabs]))
|
||||||
|
|
||||||
|
;; TODO(parvesh) - improve stack changing performance (load all stacks at once)
|
||||||
|
(defn stack-view []
|
||||||
|
(let [{:keys [width height]} (switcher-constants/dimensions)]
|
||||||
|
;; bottom-tabs-height (switcher-constants/bottom-tabs-height)]
|
||||||
|
[rn/view {:style {:width width
|
||||||
|
:height (- height 80)}} ;; TODO(parvesh) - add height for ios
|
||||||
|
(case @bottom-tabs/selected-tab-id
|
||||||
|
:chats-stack [home/home]
|
||||||
|
:communities-stack [quo2.preview/main-screen]
|
||||||
|
:wallet-stack [wallet.accounts/accounts-overview]
|
||||||
|
:browser-stack [empty-tab/empty-tab])]))
|
||||||
|
|
||||||
|
(defn home []
|
||||||
|
[:<>
|
||||||
|
[stack-view]
|
||||||
|
[bottom-tabs/bottom-tabs]
|
||||||
|
[switcher/switcher :home-stack]])
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
(ns status-im.navigation2.roots)
|
||||||
|
|
||||||
|
(defn roots []
|
||||||
|
{:home-stack
|
||||||
|
{:root
|
||||||
|
{:stack {:id :home-stack
|
||||||
|
:children [{:component {:name :home-stack
|
||||||
|
:id :home-stack
|
||||||
|
:options {:topBar {:visible false}}}}]}}}})
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
(ns status-im.navigation2.screens
|
||||||
|
(:require [status-im.navigation2.home-stack :as home-stack]))
|
||||||
|
|
||||||
|
(def screens [{:name :home-stack
|
||||||
|
:insets {:top false}
|
||||||
|
:component home-stack/home}])
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
(ns status-im.navigation2.stack-with-switcher
|
||||||
|
(:require [status-im.switcher.switcher :as switcher]))
|
||||||
|
|
||||||
|
(defn overlap-stack [comp view-id]
|
||||||
|
[:<>
|
||||||
|
[comp]
|
||||||
|
[switcher/switcher view-id]])
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
(ns status-im.navigation2.utils)
|
||||||
|
|
||||||
|
(defonce container-stack-view-id (atom nil))
|
||||||
@@ -1,24 +1,13 @@
|
|||||||
(ns status-im.stickers.core
|
(ns status-im.stickers.core
|
||||||
(:require [cljs.reader :as edn]
|
(:require [clojure.string :as string]
|
||||||
[clojure.set :as clojure.set]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]
|
|
||||||
[status-im.ethereum.contracts :as contracts]
|
|
||||||
[status-im.ethereum.core :as ethereum]
|
[status-im.ethereum.core :as ethereum]
|
||||||
[status-im.ethereum.json-rpc :as json-rpc]
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
[status-im.navigation :as navigation]
|
[status-im.navigation :as navigation]
|
||||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
|
||||||
[status-im.signing.core :as signing]
|
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.utils.utils :as utils]))
|
[status-im.utils.utils :as utils]
|
||||||
|
[status-im.utils.config :as config]
|
||||||
(defn pack-data-callback
|
[status-im.constants :as constants]))
|
||||||
[id]
|
|
||||||
(fn [[_ _ _ _ price contenthash]]
|
|
||||||
(when-let [url (contenthash/url contenthash)]
|
|
||||||
(re-frame/dispatch [:stickers/load-pack url id price]))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:stickers/set-pending-timeout-fx
|
:stickers/set-pending-timeout-fx
|
||||||
@@ -26,193 +15,109 @@
|
|||||||
(utils/set-timeout #(re-frame/dispatch [:stickers/pending-timeout])
|
(utils/set-timeout #(re-frame/dispatch [:stickers/pending-timeout])
|
||||||
10000)))
|
10000)))
|
||||||
|
|
||||||
(defn eth-call-pack-data
|
|
||||||
[contract id]
|
|
||||||
(json-rpc/eth-call
|
|
||||||
{:contract contract
|
|
||||||
;; Returns vector of pack data parameters by pack id:
|
|
||||||
;; [category owner mintable timestamp price contenthash]
|
|
||||||
:method "getPackData(uint256)"
|
|
||||||
:params [id]
|
|
||||||
:outputs ["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"]
|
|
||||||
:on-success (pack-data-callback id)}))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:stickers/pack-data-fx
|
|
||||||
(fn [[contract id]]
|
|
||||||
(eth-call-pack-data contract id)))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:stickers/load-packs-fx
|
|
||||||
(fn [[contract]]
|
|
||||||
(json-rpc/eth-call
|
|
||||||
{:contract contract
|
|
||||||
;; Returns number of packs registered in the contract
|
|
||||||
:method "packCount()"
|
|
||||||
:outputs ["uint256"]
|
|
||||||
:on-success
|
|
||||||
(fn [[count]]
|
|
||||||
(dotimes [id count]
|
|
||||||
(eth-call-pack-data contract id)))})))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:stickers/owned-packs-fx
|
|
||||||
(fn [[contract address]]
|
|
||||||
(json-rpc/eth-call
|
|
||||||
{:contract contract
|
|
||||||
;; Returns vector of owned tokens ids in the contract by address
|
|
||||||
:method "balanceOf(address)"
|
|
||||||
:params [address]
|
|
||||||
:outputs ["uint256"]
|
|
||||||
:number-of-retries 3
|
|
||||||
:on-success
|
|
||||||
(fn [[count]]
|
|
||||||
(dotimes [id count]
|
|
||||||
(json-rpc/eth-call
|
|
||||||
{:contract contract
|
|
||||||
;; Returns pack id in the contract by token id
|
|
||||||
:method "tokenOfOwnerByIndex(address,uint256)"
|
|
||||||
:params [address id]
|
|
||||||
:outputs ["uint256"]
|
|
||||||
:number-of-retries 3
|
|
||||||
:on-success
|
|
||||||
(fn [[token-id]]
|
|
||||||
(json-rpc/eth-call
|
|
||||||
{:contract contract
|
|
||||||
;; Returns pack id in the contract by token id
|
|
||||||
:method "tokenPackId(uint256)"
|
|
||||||
:params [token-id]
|
|
||||||
:outputs ["uint256"]
|
|
||||||
:number-of-retries 3
|
|
||||||
:on-success
|
|
||||||
(fn [[pack-id]]
|
|
||||||
(re-frame/dispatch [:stickers/pack-owned pack-id]))}))})))})))
|
|
||||||
|
|
||||||
(fx/defn init-stickers-packs
|
|
||||||
[{:keys [db] :as cofx}]
|
|
||||||
(let [sticker-packs (get-in db [:multiaccount :stickers/packs-installed])
|
|
||||||
pending-packs (get-in db [:multiaccount :stickers/packs-pending] #{})]
|
|
||||||
(cond-> {:db (assoc db
|
|
||||||
:stickers/packs-installed sticker-packs
|
|
||||||
:stickers/packs sticker-packs
|
|
||||||
:stickers/packs-pending pending-packs)}
|
|
||||||
(not-empty pending-packs)
|
|
||||||
(assoc :stickers/set-pending-timeout-fx nil))))
|
|
||||||
|
|
||||||
(fx/defn install-stickers-pack
|
(fx/defn install-stickers-pack
|
||||||
{:events [:stickers/install-pack]}
|
{:events [:stickers/install-pack]}
|
||||||
[{{:keys [multiaccount] :as db} :db :as cofx} id]
|
[{db :db :as cofx} id]
|
||||||
(let [pack (get-in db [:stickers/packs id])]
|
(fx/merge
|
||||||
(fx/merge
|
cofx
|
||||||
cofx
|
{:db (assoc-in db [:stickers/packs id :status] constants/sticker-pack-status-installed)
|
||||||
{:db (-> db
|
::json-rpc/call [{:method "stickers_install"
|
||||||
(assoc-in [:stickers/packs-installed id] pack))}
|
:params [(ethereum/chain-id db) id]
|
||||||
;;(assoc :stickers/selected-pack id))} TODO it doesn't scroll to selected pack on Android
|
:on-success #()}]}))
|
||||||
(multiaccounts.update/multiaccount-update
|
|
||||||
:stickers/packs-installed
|
|
||||||
(assoc (:stickers/packs-installed multiaccount) id pack)
|
|
||||||
{}))))
|
|
||||||
|
|
||||||
(defn valid-sticker? [sticker]
|
|
||||||
(contains? sticker :hash))
|
|
||||||
|
|
||||||
(fx/defn load-sticker-pack-success
|
|
||||||
{:events [:stickers/load-sticker-pack-success]}
|
|
||||||
[{:keys [db] :as cofx} edn-string id price]
|
|
||||||
(let [{:keys [stickers] :as pack} (assoc (get (edn/read-string edn-string) 'meta)
|
|
||||||
:id id :price price)]
|
|
||||||
(fx/merge cofx
|
|
||||||
{:db (cond-> db
|
|
||||||
(and (seq stickers)
|
|
||||||
(every? valid-sticker? stickers))
|
|
||||||
(assoc-in [:stickers/packs id] pack))})))
|
|
||||||
|
|
||||||
(fx/defn open-sticker-pack
|
|
||||||
{:events [:stickers/open-sticker-pack]}
|
|
||||||
[{{:stickers/keys [packs packs-installed] :networks/keys [current-network] :as db} :db :as cofx} id]
|
|
||||||
(when (and id (string/starts-with? current-network "mainnet"))
|
|
||||||
(let [pack (or (get packs-installed id)
|
|
||||||
(get packs id))
|
|
||||||
contract-address (contracts/get-address db :status/stickers)
|
|
||||||
pack-contract (contracts/get-address db :status/sticker-pack)
|
|
||||||
address (ethereum/default-address db)]
|
|
||||||
(fx/merge cofx
|
|
||||||
(navigation/open-modal :stickers-pack {:id id})
|
|
||||||
#(when (and contract-address (not pack))
|
|
||||||
{:stickers/pack-data-fx [contract-address id]
|
|
||||||
:stickers/owned-packs-fx [pack-contract address]})))))
|
|
||||||
|
|
||||||
(fx/defn load-pack
|
|
||||||
{:events [:stickers/load-pack]}
|
|
||||||
[_ url id price]
|
|
||||||
{:http-get {:url url
|
|
||||||
:on-success
|
|
||||||
(fn [o]
|
|
||||||
(re-frame/dispatch [:stickers/load-sticker-pack-success o id price]))}})
|
|
||||||
|
|
||||||
(fx/defn load-packs
|
(fx/defn load-packs
|
||||||
{:events [:stickers/load-packs]}
|
{:events [:stickers/load-packs]}
|
||||||
[{:keys [db]}]
|
[{:keys [db]}]
|
||||||
(let [contract (contracts/get-address db :status/stickers)
|
{::json-rpc/call [{:method "stickers_market"
|
||||||
pack-contract (contracts/get-address db :status/sticker-pack)
|
:params [(ethereum/chain-id db)]
|
||||||
address (ethereum/default-address db)]
|
:on-success #(re-frame/dispatch [:stickers/stickers-market-success %])}
|
||||||
(when contract
|
{:method "stickers_installed"
|
||||||
{:stickers/owned-packs-fx [pack-contract address]
|
:params []
|
||||||
:stickers/load-packs-fx [contract]})))
|
:on-success #(re-frame/dispatch [:stickers/stickers-installed-success %])}
|
||||||
|
{:method "stickers_pending"
|
||||||
|
:params []
|
||||||
|
:on-success #(re-frame/dispatch [:stickers/stickers-pending-success %])}
|
||||||
|
{:method "stickers_recent"
|
||||||
|
:params []
|
||||||
|
:on-success #(re-frame/dispatch [:stickers/stickers-recent-success %])}]})
|
||||||
|
|
||||||
(fx/defn approve-pack
|
(fx/defn buy-pack
|
||||||
{:events [:stickers/buy-pack]}
|
{:events [:stickers/buy-pack]}
|
||||||
[{db :db :as cofx} pack-id price]
|
[{db :db} pack-id]
|
||||||
(let [address (ethereum/default-address db)
|
{::json-rpc/call [{:method "stickers_buyPrepareTx"
|
||||||
sticker-market-contract (contracts/get-address db :status/sticker-market)
|
:params [(ethereum/chain-id db) (ethereum/default-address db) (int pack-id)]
|
||||||
snt-contract (contracts/get-address db :status/snt)]
|
:on-success #(re-frame/dispatch [:signing.ui/sign
|
||||||
(signing/eth-transaction-call
|
{:tx-obj %
|
||||||
cofx
|
:on-result [:stickers/pending-pack pack-id]}])}]})
|
||||||
{:contract snt-contract
|
|
||||||
:method "approveAndCall(address,uint256,bytes)"
|
|
||||||
:params [sticker-market-contract
|
|
||||||
price
|
|
||||||
(abi-spec/encode "buyToken(uint256,address,uint256)" [pack-id address price])]
|
|
||||||
:on-result [:stickers/pending-pack pack-id]})))
|
|
||||||
|
|
||||||
(fx/defn pending-pack
|
(fx/defn pending-pack
|
||||||
{:events [:stickers/pending-pack]}
|
{:events [:stickers/pending-pack]}
|
||||||
[{{:keys [multiaccount] :as db} :db :as cofx} id]
|
[{db :db} id]
|
||||||
(let [contract (contracts/get-address db :status/sticker-pack)
|
{:db (-> db
|
||||||
address (ethereum/default-address db)
|
(assoc-in [:stickers/packs id :status] constants/sticker-pack-status-pending)
|
||||||
pending (get multiaccount :stickers/packs-pending #{})]
|
(update :stickers/packs-pending conj id))
|
||||||
(when contract
|
:stickers/set-pending-timeout-fx nil
|
||||||
(fx/merge cofx
|
::json-rpc/call [{:method "stickers_addPending"
|
||||||
{:db (update db :stickers/packs-pending conj id)
|
:params [(ethereum/chain-id db) (int id)]
|
||||||
:stickers/owned-packs-fx [contract address]}
|
:on-success #()}]})
|
||||||
(multiaccounts.update/multiaccount-update
|
|
||||||
:stickers/packs-pending
|
|
||||||
(conj pending id)
|
|
||||||
{})
|
|
||||||
#(when (zero? (count (:stickers/packs-pending db)))
|
|
||||||
{:stickers/set-pending-timeout-fx nil})))))
|
|
||||||
|
|
||||||
(fx/defn pending-timeout
|
(fx/defn pending-timeout
|
||||||
{:events [:stickers/pending-timeout]}
|
{:events [:stickers/pending-timeout]}
|
||||||
[{{:stickers/keys [packs-pending packs-owned] :as db} :db :as cofx}]
|
[{{:stickers/keys [packs-pending] :as db} :db}]
|
||||||
(let [packs-diff (clojure.set/difference packs-pending packs-owned)
|
(when (seq packs-pending)
|
||||||
contract (contracts/get-address db :status/sticker-pack)
|
{::json-rpc/call [{:method "stickers_processPending"
|
||||||
address (ethereum/default-address db)]
|
:params [(ethereum/chain-id db)]
|
||||||
(when contract
|
:on-success #(re-frame/dispatch [:stickers/stickers-process-pending-success %])}]}))
|
||||||
(fx/merge cofx
|
|
||||||
(merge {:db (assoc db :stickers/packs-pending packs-diff)}
|
|
||||||
(when-not (zero? (count packs-diff))
|
|
||||||
{:stickers/owned-packs-fx [contract address]
|
|
||||||
:stickers/set-pending-timeout-fx nil}))
|
|
||||||
(multiaccounts.update/multiaccount-update
|
|
||||||
:stickers/packs-pending
|
|
||||||
packs-diff
|
|
||||||
{})))))
|
|
||||||
|
|
||||||
(fx/defn pack-owned
|
(fx/defn stickers-process-pending-success
|
||||||
{:events [:stickers/pack-owned]}
|
{:events [:stickers/stickers-process-pending-success]}
|
||||||
[{db :db} id]
|
[{{:stickers/keys [packs-pending packs] :as db} :db} purchased]
|
||||||
{:db (update db :stickers/packs-owned conj id)})
|
(let [purchased-ids (map :id (vals purchased))
|
||||||
|
packs-pending (apply disj packs-pending purchased-ids)
|
||||||
|
packs (reduce (fn [packs id]
|
||||||
|
(assoc-in packs [id :status] constants/sticker-pack-status-owned))
|
||||||
|
packs
|
||||||
|
purchased-ids)]
|
||||||
|
(merge
|
||||||
|
{:db (-> db
|
||||||
|
(assoc :stickers/packs packs)
|
||||||
|
(assoc :stickers/packs-pending packs-pending))}
|
||||||
|
(when (seq packs-pending)
|
||||||
|
{:stickers/set-pending-timeout-fx nil}))))
|
||||||
|
|
||||||
|
(fx/defn stickers-market-success
|
||||||
|
{:events [:stickers/stickers-market-success]}
|
||||||
|
[{:keys [db]} packs]
|
||||||
|
(let [packs (reduce (fn [acc pack] (assoc acc (:id pack) pack)) {} packs)]
|
||||||
|
{:db (update db :stickers/packs merge packs)}))
|
||||||
|
|
||||||
|
(fx/defn stickers-installed-success
|
||||||
|
{:events [:stickers/stickers-installed-success]}
|
||||||
|
[{:keys [db]} packs]
|
||||||
|
(let [packs (reduce (fn [acc [_ pack]] (assoc acc (:id pack) pack)) {} packs)]
|
||||||
|
{:db (update db :stickers/packs merge packs)}))
|
||||||
|
|
||||||
|
(fx/defn stickers-pending-success
|
||||||
|
{:events [:stickers/stickers-pending-success]}
|
||||||
|
[{:keys [db]} packs]
|
||||||
|
(let [packs (reduce (fn [acc [_ pack]] (assoc acc (:id pack) pack)) {} packs)]
|
||||||
|
(merge
|
||||||
|
{:db (-> db
|
||||||
|
(assoc :stickers/packs-pending (into #{} (keys packs)))
|
||||||
|
(update :stickers/packs merge packs))}
|
||||||
|
(when (seq packs)
|
||||||
|
{:stickers/set-pending-timeout-fx nil}))))
|
||||||
|
|
||||||
|
(fx/defn stickers-recent-success
|
||||||
|
{:events [:stickers/stickers-recent-success]}
|
||||||
|
[{:keys [db]} packs]
|
||||||
|
{:db (assoc db :stickers/recent-stickers packs)})
|
||||||
|
|
||||||
|
(fx/defn open-sticker-pack
|
||||||
|
{:events [:stickers/open-sticker-pack]}
|
||||||
|
[{{:networks/keys [current-network]} :db :as cofx} id]
|
||||||
|
(when (and id (or config/stickers-test-enabled? (string/starts-with? current-network "mainnet")))
|
||||||
|
(navigation/open-modal cofx :stickers-pack {:id id})))
|
||||||
|
|
||||||
(fx/defn select-pack
|
(fx/defn select-pack
|
||||||
{:events [:stickers/select-pack]}
|
{:events [:stickers/select-pack]}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
(ns status-im.stickers.core-test
|
|
||||||
(:require [cljs.test :refer-macros [deftest is]]
|
|
||||||
[status-im.stickers.core :as stickers]))
|
|
||||||
|
|
||||||
(deftest valid-sticker?
|
|
||||||
(is (true? (stickers/valid-sticker? {:hash ""})))
|
|
||||||
(is (false? (stickers/valid-sticker? {}))))
|
|
||||||
@@ -87,6 +87,7 @@
|
|||||||
(reg-root-key-sub :home-items-show-number :home-items-show-number)
|
(reg-root-key-sub :home-items-show-number :home-items-show-number)
|
||||||
(reg-root-key-sub :waku/v2-peer-stats :peer-stats)
|
(reg-root-key-sub :waku/v2-peer-stats :peer-stats)
|
||||||
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
||||||
|
(reg-root-key-sub :navigation2/navigation2-stacks :navigation2/navigation2-stacks)
|
||||||
|
|
||||||
;;NOTE this one is not related to ethereum network
|
;;NOTE this one is not related to ethereum network
|
||||||
;; it is about cellular network/ wifi network
|
;; it is about cellular network/ wifi network
|
||||||
@@ -136,9 +137,7 @@
|
|||||||
;;stickers
|
;;stickers
|
||||||
(reg-root-key-sub :stickers/selected-pack :stickers/selected-pack)
|
(reg-root-key-sub :stickers/selected-pack :stickers/selected-pack)
|
||||||
(reg-root-key-sub :stickers/packs :stickers/packs)
|
(reg-root-key-sub :stickers/packs :stickers/packs)
|
||||||
(reg-root-key-sub :stickers/installed-packs :stickers/packs-installed)
|
(reg-root-key-sub :stickers/recent-stickers :stickers/recent-stickers)
|
||||||
(reg-root-key-sub :stickers/packs-owned :stickers/packs-owned)
|
|
||||||
(reg-root-key-sub :stickers/packs-pending :stickers/packs-pending)
|
|
||||||
|
|
||||||
;;mailserver
|
;;mailserver
|
||||||
(reg-root-key-sub :mailserver/current-id :mailserver/current-id)
|
(reg-root-key-sub :mailserver/current-id :mailserver/current-id)
|
||||||
@@ -1336,7 +1335,7 @@
|
|||||||
(fn [[{:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply edit]]
|
(fn [[{:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply edit]]
|
||||||
(let [sending-image (seq sending-image)]
|
(let [sending-image (seq sending-image)]
|
||||||
{:send (not processing)
|
{:send (not processing)
|
||||||
:stickers (and mainnet?
|
:stickers (and (or config/stickers-test-enabled? mainnet?)
|
||||||
(not sending-image)
|
(not sending-image)
|
||||||
(not reply))
|
(not reply))
|
||||||
:image (and (not reply)
|
:image (and (not reply)
|
||||||
@@ -1515,23 +1514,20 @@
|
|||||||
;;STICKERS =============================================================================================================
|
;;STICKERS =============================================================================================================
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:stickers/installed-packs-vals
|
:stickers/installed-packs
|
||||||
:<- [:stickers/installed-packs]
|
:<- [:stickers/packs]
|
||||||
(fn [packs]
|
(fn [packs]
|
||||||
(vals packs)))
|
(filter #(= (:status %) constants/sticker-pack-status-installed) (vals packs))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:stickers/all-packs
|
:stickers/all-packs
|
||||||
:<- [:stickers/packs]
|
:<- [:stickers/packs]
|
||||||
:<- [:stickers/installed-packs]
|
(fn [packs]
|
||||||
:<- [:stickers/packs-owned]
|
(map (fn [{:keys [status] :as pack}]
|
||||||
:<- [:stickers/packs-pending]
|
(-> pack
|
||||||
(fn [[packs installed owned pending]]
|
(assoc :installed (= status constants/sticker-pack-status-installed))
|
||||||
(map (fn [{:keys [id] :as pack}]
|
(assoc :pending (= status constants/sticker-pack-status-pending))
|
||||||
(cond-> pack
|
(assoc :owned (= status constants/sticker-pack-status-owned))))
|
||||||
(get installed id) (assoc :installed true)
|
|
||||||
(get owned id) (assoc :owned true)
|
|
||||||
(get pending id) (assoc :pending true)))
|
|
||||||
(vals packs))))
|
(vals packs))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
@@ -1541,19 +1537,6 @@
|
|||||||
(fn [[{:keys [id]} packs]]
|
(fn [[{:keys [id]} packs]]
|
||||||
(first (filter #(= (:id %) id) packs))))
|
(first (filter #(= (:id %) id) packs))))
|
||||||
|
|
||||||
(defn find-pack-id-for-hash [sticker-uri packs]
|
|
||||||
(some (fn [{:keys [stickers id]}]
|
|
||||||
(when (some #(= sticker-uri (:hash %)) stickers)
|
|
||||||
id))
|
|
||||||
packs))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
:stickers/recent
|
|
||||||
:<- [:multiaccount]
|
|
||||||
:<- [:stickers/installed-packs-vals]
|
|
||||||
(fn [[{:keys [:stickers/recent-stickers]} packs]]
|
|
||||||
(map (fn [hash] {:hash hash :pack (find-pack-id-for-hash hash packs)}) recent-stickers)))
|
|
||||||
|
|
||||||
;;HOME ==============================================================================================================
|
;;HOME ==============================================================================================================
|
||||||
|
|
||||||
(def memo-home-items (atom nil))
|
(def memo-home-items (atom nil))
|
||||||
@@ -2964,3 +2947,19 @@
|
|||||||
:<- [:bookmarks]
|
:<- [:bookmarks]
|
||||||
(fn [bookmarks]
|
(fn [bookmarks]
|
||||||
(into {} (remove #(:removed (second %)) bookmarks))))
|
(into {} (remove #(:removed (second %)) bookmarks))))
|
||||||
|
|
||||||
|
;; NAVIGATION2
|
||||||
|
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:navigation2/switcher-cards
|
||||||
|
:<- [:navigation2/navigation2-stacks]
|
||||||
|
(fn [stacks [_ toggle-switcher-screen]]
|
||||||
|
(sort-by :clock >
|
||||||
|
(reduce (fn [acc stack-vector]
|
||||||
|
(let [{:keys [type clock id]} (get stack-vector 1)]
|
||||||
|
(conj acc {:type type
|
||||||
|
:clock clock
|
||||||
|
:id id
|
||||||
|
:toggle-switcher-screen toggle-switcher-screen})))
|
||||||
|
'() stacks))))
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
(ns status-im.switcher.animation
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im.switcher.constants :as constants]
|
||||||
|
[status-im.ui.components.animation :as anim]))
|
||||||
|
|
||||||
|
(def bottom-tabs-opacity (anim/create-value 1))
|
||||||
|
(def bottom-tabs-position (anim/create-value 0))
|
||||||
|
|
||||||
|
;; TODO(parvesh): Use 300, after using dispatch-later for opening card(otherwise pending animation issue)
|
||||||
|
;; or OnAnimationEnd
|
||||||
|
(def layout-animation #js {:duration 250
|
||||||
|
:create #js {:type (:ease-in-ease-out rn/layout-animation-types)
|
||||||
|
:property (:scale-xy rn/layout-animation-properties)}
|
||||||
|
:update #js {:type (:ease-in-ease-out rn/layout-animation-types)
|
||||||
|
:property (:scale-xy rn/layout-animation-properties)}
|
||||||
|
:delete #js {:type (:ease-in-ease-out rn/layout-animation-types)
|
||||||
|
:property (:scale-xy rn/layout-animation-properties)}})
|
||||||
|
|
||||||
|
(defn animate-layout [show? anim-values]
|
||||||
|
(let [{:keys [width height]} (constants/dimensions)
|
||||||
|
target-radius (- (max width height)
|
||||||
|
constants/switcher-button-radius)]
|
||||||
|
(rn/configure-next layout-animation)
|
||||||
|
(reset! (:switcher-screen-radius anim-values) (if show? target-radius 1))
|
||||||
|
(reagent/flush)))
|
||||||
|
|
||||||
|
(defn timing-animation [property toValue]
|
||||||
|
(anim/timing property {:toValue toValue
|
||||||
|
:duration 300
|
||||||
|
:useNativeDriver true}))
|
||||||
|
|
||||||
|
(defn animate-components [show? view-id anim-values]
|
||||||
|
(anim/start
|
||||||
|
(anim/parallel
|
||||||
|
(into
|
||||||
|
[(timing-animation (:switcher-button-opacity anim-values) (if show? 0 1))
|
||||||
|
(timing-animation (:switcher-close-button-icon-opacity anim-values) (if show? 1 0))
|
||||||
|
(timing-animation (:switcher-close-button-background-opacity anim-values) (if show? 0.2 0))]
|
||||||
|
(when (= view-id :home-stack)
|
||||||
|
[(timing-animation bottom-tabs-opacity (if show? 0 1))
|
||||||
|
(timing-animation bottom-tabs-position (if show? (constants/bottom-tabs-height) 0))])))))
|
||||||
|
|
||||||
|
(defn animate [show? view-id anim-values]
|
||||||
|
(reagent/flush)
|
||||||
|
(animate-layout show? anim-values)
|
||||||
|
(animate-components show? view-id anim-values))
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
(ns status-im.switcher.bottom-tabs
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im.switcher.styles :as styles]
|
||||||
|
[status-im.ui.components.icons.icons :as icons]))
|
||||||
|
|
||||||
|
(def selected-tab-id (reagent/atom :chats-stack))
|
||||||
|
|
||||||
|
(defn bottom-tab-pressed [tab-id]
|
||||||
|
(when-not (= tab-id @selected-tab-id)
|
||||||
|
(reset! selected-tab-id tab-id)))
|
||||||
|
|
||||||
|
;; TODO(parvesh) - reimplement tab with counter, once design is complete
|
||||||
|
;; (implement natively, for performance improvement)
|
||||||
|
(defn bottom-tab [icon tab-id]
|
||||||
|
[rn/touchable-opacity {:style {:padding 15}
|
||||||
|
:active-opacity 1
|
||||||
|
:on-press #(bottom-tab-pressed tab-id)}
|
||||||
|
[icons/icon icon (styles/bottom-tab-icon
|
||||||
|
(if (= tab-id @selected-tab-id)
|
||||||
|
:bottom-tabs-selected-tab
|
||||||
|
:bottom-tabs-non-selected-tab))]])
|
||||||
|
|
||||||
|
(defn bottom-tabs []
|
||||||
|
[rn/animated-view {:style (styles/bottom-tabs)}
|
||||||
|
[bottom-tab :main-icons/redesign-messages :chats-stack]
|
||||||
|
[bottom-tab :main-icons/communities :communities-stack]
|
||||||
|
[rn/view {:width 10}]
|
||||||
|
[bottom-tab :main-icons/redesign-wallet :wallet-stack]
|
||||||
|
[bottom-tab :main-icons/browser :browser-stack]])
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
(ns status-im.switcher.cards.messaging-card
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[quo2.components.text :as text]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[quo2.components.button :as button]
|
||||||
|
[status-im.utils.handlers :refer [>evt <sub]]
|
||||||
|
[status-im.switcher.cards.styles :as styles]))
|
||||||
|
|
||||||
|
(defn on-press [id toggle-switcher-screen]
|
||||||
|
(toggle-switcher-screen)
|
||||||
|
(>evt [:chat.ui/navigate-to-chat-nav2 id true]))
|
||||||
|
|
||||||
|
;; TODO - add last message for other content types
|
||||||
|
(defn last-message [{:keys [content content-type]}]
|
||||||
|
(cond
|
||||||
|
(= constants/content-type-text content-type)
|
||||||
|
[text/text (styles/messaging-card-last-message-text-props) (:text content)]))
|
||||||
|
|
||||||
|
(defn card [{:keys [id toggle-switcher-screen]}]
|
||||||
|
(let [chat (<sub [:chats/chat id])]
|
||||||
|
[rn/touchable-without-feedback {:on-press #(on-press id toggle-switcher-screen)}
|
||||||
|
[rn/view {:style (styles/messaging-card-main-container)}
|
||||||
|
[rn/view {:style (styles/messaging-card-secondary-container)}
|
||||||
|
[text/text (styles/messaging-card-title-props) (:alias chat)]
|
||||||
|
[text/text (styles/messaging-card-subtitle-props) "Message"]
|
||||||
|
[rn/view {:style (styles/messaging-card-details-container)}
|
||||||
|
[last-message (:last-message chat)]]]
|
||||||
|
[rn/view {:style (styles/messaging-card-avatar-container)}]
|
||||||
|
[button/button (styles/messaging-card-close-button-props) :main-icons/close]]]))
|
||||||
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
(ns status-im.switcher.cards.styles
|
||||||
|
(:require [quo.theme :as theme]
|
||||||
|
[quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def themes
|
||||||
|
{:light {:messaging-card-container-background-color "#26A69A"
|
||||||
|
:messaging-card-secondary-container-background-color colors/white
|
||||||
|
:messaging-card-title-color colors/black
|
||||||
|
:messaging-card-subtitle-color colors/neutral-50
|
||||||
|
:messaging-card-last-message-text-color colors/black
|
||||||
|
:messaging-card-close-button-bg-color colors/white-opa-50
|
||||||
|
:messaging-card-close-button-icon-color colors/black}
|
||||||
|
:dark {:messaging-card-container-background-color "#26A69A"
|
||||||
|
:messaging-card-secondary-container-background-color colors/neutral-90
|
||||||
|
:messaging-card-title-color colors/white
|
||||||
|
:messaging-card-subtitle-color colors/neutral-40
|
||||||
|
:messaging-card-last-message-text-color colors/white
|
||||||
|
:messaging-card-close-button-bg-color colors/neutral-80-opa-60
|
||||||
|
:messaging-card-close-button-icon-color colors/white}})
|
||||||
|
|
||||||
|
(defn get-color [key]
|
||||||
|
(get-in themes [(theme/get-theme) key]))
|
||||||
|
|
||||||
|
;; Messaging Card
|
||||||
|
|
||||||
|
(defn messaging-card-main-container []
|
||||||
|
{:width 160
|
||||||
|
:height 172
|
||||||
|
:border-radius 16
|
||||||
|
:margin 8
|
||||||
|
:background-color (get-color :messaging-card-container-background-color)})
|
||||||
|
|
||||||
|
(defn messaging-card-secondary-container []
|
||||||
|
{:width 160
|
||||||
|
:height 132
|
||||||
|
:background-color (get-color :messaging-card-secondary-container-background-color)
|
||||||
|
:border-radius 16
|
||||||
|
:position :absolute
|
||||||
|
:bottom 0})
|
||||||
|
|
||||||
|
(defn messaging-card-title []
|
||||||
|
{:position :absolute
|
||||||
|
:top 32
|
||||||
|
:margin-horizontal 12
|
||||||
|
:color (get-color :messaging-card-title-color)})
|
||||||
|
|
||||||
|
(defn messaging-card-title-props []
|
||||||
|
{:size :paragraph-1
|
||||||
|
:weight :semi-bold
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsize-mode :tail
|
||||||
|
:style (messaging-card-title)})
|
||||||
|
|
||||||
|
(defn messaging-card-subtitle []
|
||||||
|
{:position :absolute
|
||||||
|
:top 54
|
||||||
|
:margin-horizontal 12
|
||||||
|
:color (get-color :messaging-card-subtitle-color)})
|
||||||
|
|
||||||
|
(defn messaging-card-subtitle-props []
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :medium
|
||||||
|
:style (messaging-card-subtitle)})
|
||||||
|
|
||||||
|
(defn messaging-card-details-container []
|
||||||
|
{:position :absolute
|
||||||
|
:bottom 12
|
||||||
|
:margin-horizontal 12
|
||||||
|
:width 136
|
||||||
|
:height 36})
|
||||||
|
|
||||||
|
(defn messaging-card-last-message-text []
|
||||||
|
{:color (get-color :messaging-card-last-message-text-color)})
|
||||||
|
|
||||||
|
(defn messaging-card-last-message-text-props []
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :regular
|
||||||
|
:number-of-lines 2
|
||||||
|
:ellipsize-mode :tail
|
||||||
|
:style (messaging-card-last-message-text)})
|
||||||
|
|
||||||
|
(defn messaging-card-close-button []
|
||||||
|
{:position :absolute
|
||||||
|
:right 8
|
||||||
|
:top 8
|
||||||
|
:background-color (get-color :messaging-card-close-button-bg-color)
|
||||||
|
:icon-color (get-color :messaging-card-icon-color)})
|
||||||
|
|
||||||
|
(defn messaging-card-close-button-props []
|
||||||
|
{:size 24
|
||||||
|
:type :grey
|
||||||
|
:icon true
|
||||||
|
:on-press #(print "close pressed")
|
||||||
|
:style (messaging-card-close-button)})
|
||||||
|
|
||||||
|
(defn messaging-card-avatar-container []
|
||||||
|
{:width 48
|
||||||
|
:height 48
|
||||||
|
:border-radius 24
|
||||||
|
:position :absolute
|
||||||
|
:left 12
|
||||||
|
:top 16
|
||||||
|
:background-color :pink})
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
(ns status-im.switcher.constants
|
||||||
|
(:require [status-im.utils.handlers :refer [<sub]]
|
||||||
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
|
(def switcher-button-radius 24)
|
||||||
|
|
||||||
|
(def switcher-button-size
|
||||||
|
(* switcher-button-radius 2))
|
||||||
|
|
||||||
|
(def switcher-bottom-positions
|
||||||
|
{:android
|
||||||
|
{:home-stack 17
|
||||||
|
:chat 57}
|
||||||
|
:ios
|
||||||
|
{:home-stack 35
|
||||||
|
:chat 67}})
|
||||||
|
|
||||||
|
(defn switcher-bottom-position [view-id]
|
||||||
|
(get-in
|
||||||
|
switcher-bottom-positions
|
||||||
|
[(keyword platform/os) view-id]))
|
||||||
|
|
||||||
|
(defn switcher-center-position [view-id]
|
||||||
|
(+ (switcher-bottom-position view-id) (/ switcher-button-size 2)))
|
||||||
|
|
||||||
|
;; TODO(parvesh) - use different height for android and ios(Confirm from Design)
|
||||||
|
(defn bottom-tabs-height []
|
||||||
|
(if platform/android? 55 80))
|
||||||
|
|
||||||
|
;; TODO - move to switcher/utils.cljs
|
||||||
|
(defn dimensions []
|
||||||
|
(<sub [:dimensions/window]))
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
(ns status-im.switcher.styles
|
||||||
|
(:require [quo.theme :as theme]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[status-im.switcher.constants :as constants]
|
||||||
|
[status-im.switcher.animation :as animation]))
|
||||||
|
|
||||||
|
(def themes
|
||||||
|
{:light {:bottom-tabs-bg-color colors/neutral-80
|
||||||
|
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-80
|
||||||
|
:bottom-tabs-non-selected-tab colors/neutral-50
|
||||||
|
:bottom-tabs-selected-tab colors/white}
|
||||||
|
:dark {:bottom-tabs-bg-color colors/neutral-80
|
||||||
|
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-60
|
||||||
|
:bottom-tabs-non-selected-tab colors/neutral-40
|
||||||
|
:bottom-tabs-selected-tab colors/white}})
|
||||||
|
|
||||||
|
(defn get-color [key]
|
||||||
|
(get-in themes [(theme/get-theme) key]))
|
||||||
|
|
||||||
|
;; Bottom Tabs
|
||||||
|
(defn bottom-tab-icon [tab-state]
|
||||||
|
{:width 20
|
||||||
|
:height 20
|
||||||
|
:color (get-color tab-state)})
|
||||||
|
|
||||||
|
(defn bottom-tabs []
|
||||||
|
{:background-color (get-color :bottom-tabs-bg-color)
|
||||||
|
:flex-direction :row
|
||||||
|
:flex 1
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :space-around
|
||||||
|
:height (constants/bottom-tabs-height)
|
||||||
|
:position :absolute
|
||||||
|
:bottom 0
|
||||||
|
:right 0
|
||||||
|
:left 0
|
||||||
|
:opacity animation/bottom-tabs-opacity
|
||||||
|
:transform [{:translateY animation/bottom-tabs-position}]})
|
||||||
|
|
||||||
|
;; Switcher
|
||||||
|
(defn switcher-button [opacity]
|
||||||
|
{:width constants/switcher-button-size
|
||||||
|
:height constants/switcher-button-size
|
||||||
|
:opacity opacity})
|
||||||
|
|
||||||
|
(defn merge-switcher-button-common-styles [style]
|
||||||
|
(merge
|
||||||
|
{:width constants/switcher-button-size
|
||||||
|
:height constants/switcher-button-size
|
||||||
|
:border-radius constants/switcher-button-radius
|
||||||
|
:position :absolute
|
||||||
|
:bottom 0
|
||||||
|
:z-index 3
|
||||||
|
:align-items :center
|
||||||
|
:align-self :center
|
||||||
|
:justify-content :center}
|
||||||
|
style))
|
||||||
|
|
||||||
|
(defn switcher-button-touchable [view-id]
|
||||||
|
(merge-switcher-button-common-styles
|
||||||
|
{:align-self :center
|
||||||
|
:bottom (constants/switcher-bottom-position view-id)}))
|
||||||
|
|
||||||
|
(defn switcher-close-button-background [opacity]
|
||||||
|
(merge-switcher-button-common-styles
|
||||||
|
{:background-color colors/switcher-background
|
||||||
|
:opacity opacity}))
|
||||||
|
|
||||||
|
(defn switcher-close-button-icon [opacity]
|
||||||
|
(merge-switcher-button-common-styles
|
||||||
|
{:opacity opacity}))
|
||||||
|
|
||||||
|
(defn switcher-screen [view-id radius]
|
||||||
|
(let [bottom (- (constants/switcher-center-position view-id) radius)
|
||||||
|
size (* 2 radius)]
|
||||||
|
(merge-switcher-button-common-styles
|
||||||
|
{:background-color colors/switcher-background-opa-80
|
||||||
|
:bottom bottom
|
||||||
|
:border-radius 1000
|
||||||
|
:width size
|
||||||
|
:overflow :hidden
|
||||||
|
:height size})))
|
||||||
|
|
||||||
|
(defn switcher-screen-container [view-id radius]
|
||||||
|
(let [radius radius
|
||||||
|
bottom (- radius (constants/switcher-center-position view-id))
|
||||||
|
{:keys [width height]} (constants/dimensions)]
|
||||||
|
{:position :absolute
|
||||||
|
:align-self :center
|
||||||
|
:bottom bottom
|
||||||
|
:width width
|
||||||
|
:height (- height 25)
|
||||||
|
:align-items :center}))
|
||||||
|
|
||||||
|
(defn switcher-switch-screen []
|
||||||
|
{:margin-top 40
|
||||||
|
:align-items :center})
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
(ns status-im.switcher.switcher
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im.switcher.styles :as styles]
|
||||||
|
[status-im.ui.components.animation :as anim]
|
||||||
|
[status-im.switcher.animation :as animation]
|
||||||
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
|
[status-im.react-native.resources :as resources]
|
||||||
|
[status-im.switcher.switcher-container :as switcher-container]))
|
||||||
|
|
||||||
|
(defn toggle-switcher-screen [switcher-opened? view-id anim-values]
|
||||||
|
(swap! switcher-opened? not)
|
||||||
|
(animation/animate @switcher-opened? view-id anim-values))
|
||||||
|
|
||||||
|
(defn switcher-button [switcher-opened? view-id anim-values]
|
||||||
|
[rn/touchable-opacity {:active-opacity 1
|
||||||
|
:on-press #(toggle-switcher-screen switcher-opened? view-id anim-values)
|
||||||
|
:style (styles/switcher-button-touchable view-id)}
|
||||||
|
[rn/animated-view {:style (styles/switcher-close-button-background
|
||||||
|
(:switcher-close-button-background-opacity anim-values))}]
|
||||||
|
[rn/animated-view {:style (styles/switcher-close-button-icon
|
||||||
|
(:switcher-close-button-icon-opacity anim-values))}
|
||||||
|
[icons/icon :main-icons/close {:color :white}]]
|
||||||
|
[rn/animated-image-view {:source (resources/get-image :status-logo)
|
||||||
|
:style (styles/switcher-button
|
||||||
|
(:switcher-button-opacity anim-values))}]])
|
||||||
|
|
||||||
|
(defn switcher-screen [switcher-opened? view-id anim-values]
|
||||||
|
[rn/view {:style (styles/switcher-screen
|
||||||
|
view-id @(:switcher-screen-radius anim-values))
|
||||||
|
:pointer-events (if switcher-opened? :auto :none)}
|
||||||
|
[switcher-container/container
|
||||||
|
view-id @(:switcher-screen-radius anim-values)
|
||||||
|
#(toggle-switcher-screen switcher-opened? view-id anim-values)]])
|
||||||
|
|
||||||
|
(defn switcher [view-id]
|
||||||
|
(let [switcher-opened? (reagent/atom false)
|
||||||
|
anim-values {:switcher-button-opacity (anim/create-value 1)
|
||||||
|
:switcher-close-button-icon-opacity (anim/create-value 0)
|
||||||
|
:switcher-close-button-background-opacity (anim/create-value 0)
|
||||||
|
:switcher-screen-radius (reagent/atom 1)}]
|
||||||
|
[:<>
|
||||||
|
[switcher-screen switcher-opened? view-id anim-values]
|
||||||
|
[switcher-button switcher-opened? view-id anim-values]]))
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
(ns status-im.switcher.switcher-container
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
status-im.switcher.cards.messaging-card
|
||||||
|
[status-im.switcher.styles :as styles]
|
||||||
|
[status-im.utils.handlers :refer [<sub]]
|
||||||
|
[status-im.switcher.cards.messaging-card :as messaging-card]))
|
||||||
|
|
||||||
|
;; TODO - use something like this to avoid multiple renders etc.
|
||||||
|
;; (defn switch-screen [toggle-switcher-screen]
|
||||||
|
;; (let [cards (<sub [:navigation2/switcher-cards])
|
||||||
|
;; new-cards (reduce (fn [acc card]
|
||||||
|
;; (conj acc (assoc card :toggle-switcher-screen toggle-switcher-screen)))
|
||||||
|
;; () cards)]
|
||||||
|
;; (fn []
|
||||||
|
;; [rn/view {:style (styles/switcher-switch-screen)}
|
||||||
|
;; [rn/flat-list {:width 352
|
||||||
|
;; :data new-cards
|
||||||
|
;; :render-fn messaging-card/card
|
||||||
|
;; :num-columns 2
|
||||||
|
;; :key-fn str}]])))
|
||||||
|
|
||||||
|
(defn switch-screen [toggle-switcher-screen]
|
||||||
|
(let [cards (<sub [:navigation2/switcher-cards toggle-switcher-screen])]
|
||||||
|
[rn/view {:style (styles/switcher-switch-screen)}
|
||||||
|
[rn/flat-list {:width 352
|
||||||
|
:data cards
|
||||||
|
:render-fn messaging-card/card
|
||||||
|
:num-columns 2
|
||||||
|
:key-fn str}]]))
|
||||||
|
|
||||||
|
(defn container [view-id switcher-screen-radius toggle-switcher-screen]
|
||||||
|
[rn/view {:style (styles/switcher-screen-container
|
||||||
|
view-id switcher-screen-radius)}
|
||||||
|
[switch-screen toggle-switcher-screen]])
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
(ns status-im.switcher.utils
|
||||||
|
(:require [re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(def switcher-container-view-id (atom nil))
|
||||||
|
|
||||||
|
(re-frame/reg-fx :switcher-container-view-id #(reset! switcher-container-view-id %))
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
status-im.transport.shh
|
status-im.transport.shh
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.utils.universal-links.core :as universal-links]))
|
[status-im.utils.universal-links.core :as universal-links]
|
||||||
|
[status-im.stickers.core :as stickers]))
|
||||||
|
|
||||||
(fx/defn set-node-info
|
(fx/defn set-node-info
|
||||||
{:events [:transport.callback/node-info-fetched]}
|
{:events [:transport.callback/node-info-fetched]}
|
||||||
@@ -65,4 +66,5 @@
|
|||||||
(add-mailservers mailservers))}
|
(add-mailservers mailservers))}
|
||||||
(fetch-node-info-fx)
|
(fetch-node-info-fx)
|
||||||
(pairing/init)
|
(pairing/init)
|
||||||
|
(stickers/load-packs)
|
||||||
(universal-links/process-stored-event)))
|
(universal-links/process-stored-event)))
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
[status-im.utils.debounce :as debounce]
|
[status-im.utils.debounce :as debounce]
|
||||||
[status-im.utils.http :as http]
|
[status-im.utils.http :as http]
|
||||||
[status-im.utils.js-resources :as js-res]
|
[status-im.utils.js-resources :as js-res]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.ui.components.permissions :as components.permissions]
|
[status-im.ui.components.permissions :as components.permissions]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[status-im.ui.screens.wallet.components.views :as components]
|
[status-im.ui.screens.wallet.components.views :as components]
|
||||||
@@ -58,8 +57,7 @@
|
|||||||
(reagent/as-element
|
(reagent/as-element
|
||||||
[react/view styles/web-view-error
|
[react/view styles/web-view-error
|
||||||
[react/image {:style {:width 140 :height 140 :margin-bottom 16}
|
[react/image {:style {:width 140 :height 140 :margin-bottom 16}
|
||||||
:source {:uri (contenthash/url
|
:source {:uri "https://bafybeiabxprplp52amc2hpocar753rd64wk2len55zq54yca77bekzre4e.ipfs.cf-ipfs.com"}}]
|
||||||
"e3010170122001bbe2f5bfba0305a3bdc2047fddc47ee595a591bdee61de6040ffc2456624e1")}}]
|
|
||||||
[react/i18n-text {:style styles/web-view-error-text :key :web-view-error}]
|
[react/i18n-text {:style styles/web-view-error-text :key :web-view-error}]
|
||||||
[react/text {:style styles/web-view-error-text}
|
[react/text {:style styles/web-view-error-text}
|
||||||
(str desc)]]))
|
(str desc)]]))
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
[status-im.ui.screens.chat.message.gap :as message.gap]
|
[status-im.ui.screens.chat.message.gap :as message.gap]
|
||||||
[status-im.ui.screens.chat.styles.message.message :as style]
|
[status-im.ui.screens.chat.styles.message.message :as style]
|
||||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.utils.security :as security]
|
[status-im.utils.security :as security]
|
||||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||||
@@ -558,7 +557,7 @@
|
|||||||
:accessibility-label :sticker-message
|
:accessibility-label :sticker-message
|
||||||
:on-press (fn [_]
|
:on-press (fn [_]
|
||||||
(when pack
|
(when pack
|
||||||
(re-frame/dispatch [:stickers/open-sticker-pack pack]))
|
(re-frame/dispatch [:stickers/open-sticker-pack (str pack)]))
|
||||||
(react/dismiss-keyboard!))
|
(react/dismiss-keyboard!))
|
||||||
:delay-long-press 100
|
:delay-long-press 100
|
||||||
:on-long-press (fn []
|
:on-long-press (fn []
|
||||||
@@ -568,8 +567,7 @@
|
|||||||
(re-frame/dispatch [:chat.ui/show-profile from]))
|
(re-frame/dispatch [:chat.ui/show-profile from]))
|
||||||
:label (i18n/label :t/view-details)}])))})
|
:label (i18n/label :t/view-details)}])))})
|
||||||
[react/fast-image {:style {:margin 10 :width 140 :height 140}
|
[react/fast-image {:style {:margin 10 :width 140 :height 140}
|
||||||
;;TODO (perf) move to event
|
:source {:uri (str (-> content :sticker :url) "&download=true")}}]]
|
||||||
:source {:uri (contenthash/url (-> content :sticker :hash))}}]]
|
|
||||||
reaction-picker]))
|
reaction-picker]))
|
||||||
|
|
||||||
(defmethod ->message constants/content-type-image
|
(defmethod ->message constants/content-type-image
|
||||||
|
|||||||
@@ -2,14 +2,12 @@
|
|||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.stickers.core :as stickers]
|
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[status-im.i18n.i18n :as i18n]
|
[status-im.i18n.i18n :as i18n]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[status-im.ui.screens.chat.stickers.styles :as styles]
|
[status-im.ui.screens.chat.stickers.styles :as styles]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.utils.debounce :as debounce]))
|
[status-im.utils.debounce :as debounce]))
|
||||||
|
|
||||||
(def icon-size 28)
|
(def icon-size 28)
|
||||||
@@ -26,25 +24,23 @@
|
|||||||
:height 64}]
|
:height 64}]
|
||||||
[react/text {:style {:margin-vertical 8 :font-size 17}} (i18n/label :t/you-dont-have-stickers)]
|
[react/text {:style {:margin-vertical 8 :font-size 17}} (i18n/label :t/you-dont-have-stickers)]
|
||||||
[quo/button {:type :secondary
|
[quo/button {:type :secondary
|
||||||
:on-press #(do
|
:on-press #(re-frame/dispatch [:navigate-to :stickers])}
|
||||||
(re-frame/dispatch [:stickers/load-packs])
|
|
||||||
(re-frame/dispatch [:navigate-to :stickers]))}
|
|
||||||
(i18n/label :t/get-stickers)]])
|
(i18n/label :t/get-stickers)]])
|
||||||
|
|
||||||
(defn- stickers-panel [stickers window-width]
|
(defn- stickers-panel [stickers window-width]
|
||||||
[react/view {:width window-width :flex 1}
|
[react/view {:width window-width :flex 1}
|
||||||
[react/scroll-view
|
[react/scroll-view
|
||||||
[react/view {:style styles/stickers-panel}
|
[react/view {:style styles/stickers-panel}
|
||||||
(for [{:keys [hash] :as sticker} stickers]
|
(for [{:keys [url] :as sticker} stickers]
|
||||||
^{:key (str hash)}
|
^{:key (str url)}
|
||||||
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
|
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
|
||||||
:on-press #(debounce/dispatch-and-chill [:chat/send-sticker sticker] 1000)}
|
:on-press #(debounce/dispatch-and-chill [:chat/send-sticker sticker] 1000)}
|
||||||
[react/fast-image {:style {:width "100%" :height "100%"}
|
[react/fast-image {:style {:width "100%" :height "100%"}
|
||||||
:accessibility-label :sticker-icon
|
:accessibility-label :sticker-icon
|
||||||
:source {:uri (contenthash/url (str "0x" hash))}}]])]]])
|
:source {:uri (str url "&download=true")}}]])]]])
|
||||||
|
|
||||||
(defview recent-stickers-panel [window-width]
|
(defview recent-stickers-panel [window-width]
|
||||||
(letsubs [stickers [:stickers/recent]]
|
(letsubs [stickers [:stickers/recent-stickers]]
|
||||||
(if (seq stickers)
|
(if (seq stickers)
|
||||||
[stickers-panel stickers window-width]
|
[stickers-panel stickers window-width]
|
||||||
[react/view {:style {:flex 1
|
[react/view {:style {:flex 1
|
||||||
@@ -98,7 +94,7 @@
|
|||||||
[recent-stickers-panel width]
|
[recent-stickers-panel width]
|
||||||
(for [{:keys [stickers id]} installed-packs]
|
(for [{:keys [stickers id]} installed-packs]
|
||||||
^{:key (str "sticker" id)}
|
^{:key (str "sticker" id)}
|
||||||
[stickers-panel (map #(assoc % :pack id) (filter stickers/valid-sticker? stickers)) width])]))
|
[stickers-panel (map #(assoc % :pack id) stickers) width])]))
|
||||||
|
|
||||||
(defn pack-icon [{:keys [id on-press background-color]
|
(defn pack-icon [{:keys [id on-press background-color]
|
||||||
:or {on-press #(re-frame/dispatch [:stickers/select-pack id])}}
|
:or {on-press #(re-frame/dispatch [:stickers/select-pack id])}}
|
||||||
@@ -118,7 +114,7 @@
|
|||||||
|
|
||||||
(defview stickers-view []
|
(defview stickers-view []
|
||||||
(letsubs [selected-pack [:stickers/selected-pack]
|
(letsubs [selected-pack [:stickers/selected-pack]
|
||||||
installed-packs [:stickers/installed-packs-vals]]
|
installed-packs [:stickers/installed-packs]]
|
||||||
[react/view {:style {:background-color colors/white
|
[react/view {:style {:background-color colors/white
|
||||||
:flex 1}}
|
:flex 1}}
|
||||||
(cond
|
(cond
|
||||||
@@ -126,9 +122,7 @@
|
|||||||
(not (seq installed-packs)) [no-stickers-yet-panel]
|
(not (seq installed-packs)) [no-stickers-yet-panel]
|
||||||
:else [stickers-paging-panel installed-packs selected-pack])
|
:else [stickers-paging-panel installed-packs selected-pack])
|
||||||
[react/view {:style {:flex-direction :row :padding-horizontal 4}}
|
[react/view {:style {:flex-direction :row :padding-horizontal 4}}
|
||||||
[pack-icon {:on-press #(do
|
[pack-icon {:on-press #(re-frame/dispatch [:navigate-to :stickers])
|
||||||
(re-frame/dispatch [:stickers/load-packs])
|
|
||||||
(re-frame/dispatch [:navigate-to :stickers]))
|
|
||||||
:selected? false :background-color colors/blue}
|
:selected? false :background-color colors/blue}
|
||||||
[icons/icon :main-icons/add {:width 20 :height 20 :color colors/white-persist}]]
|
[icons/icon :main-icons/add {:width 20 :height 20 :color colors/white-persist}]]
|
||||||
[react/view {:width 2}]
|
[react/view {:width 2}]
|
||||||
@@ -140,9 +134,9 @@
|
|||||||
:width 44
|
:width 44
|
||||||
:height 44}]]
|
:height 44}]]
|
||||||
(for [{:keys [id thumbnail]} installed-packs]
|
(for [{:keys [id thumbnail]} installed-packs]
|
||||||
^{:key id}
|
^{:key (str "pack-icon" id)}
|
||||||
[pack-icon {:id id
|
[pack-icon {:id id
|
||||||
:background-color colors/white}
|
:background-color colors/white}
|
||||||
[react/fast-image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
|
[react/fast-image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
|
||||||
:source {:uri (contenthash/url thumbnail)}}]])]
|
:source {:uri (str thumbnail "&download=true")}}]])]
|
||||||
[scroll-indicator]]]]]))
|
[scroll-indicator]]]]]))
|
||||||
|
|||||||
@@ -123,6 +123,7 @@
|
|||||||
:accessibility-label :appearance-settings-button
|
:accessibility-label :appearance-settings-button
|
||||||
:chevron true
|
:chevron true
|
||||||
:on-press #(re-frame/dispatch [:navigate-to :quo2-preview])}])
|
:on-press #(re-frame/dispatch [:navigate-to :quo2-preview])}])
|
||||||
|
;; :on-press #(re-frame/dispatch [:init-root-nav2 :home-stack])}])
|
||||||
[quo/list-item
|
[quo/list-item
|
||||||
{:icon :main-icons/appearance
|
{:icon :main-icons/appearance
|
||||||
:title (i18n/label :t/appearance)
|
:title (i18n/label :t/appearance)
|
||||||
|
|||||||
@@ -121,7 +121,9 @@
|
|||||||
[status-im.ui.screens.wallet.recipient.views :as recipient]
|
[status-im.ui.screens.wallet.recipient.views :as recipient]
|
||||||
[status-im.ui.screens.wallet.send.views :as wallet.send]
|
[status-im.ui.screens.wallet.send.views :as wallet.send]
|
||||||
[quo2.screens.main :as quo2.preview]
|
[quo2.screens.main :as quo2.preview]
|
||||||
[status-im.utils.config :as config]))
|
[status-im.utils.config :as config]
|
||||||
|
[status-im.navigation2.screens :as navigation2.screens]))
|
||||||
|
;[status-im.navigation2.stack-with-switcher :as stack-with-switcher]))
|
||||||
;[quo2.foundations.colors :as quo2.colors]))
|
;[quo2.foundations.colors :as quo2.colors]))
|
||||||
|
|
||||||
(def components
|
(def components
|
||||||
@@ -229,6 +231,7 @@
|
|||||||
:rightButtons (right-button-options :chat :more)}}
|
:rightButtons (right-button-options :chat :more)}}
|
||||||
:right-handler chat/topbar-button
|
:right-handler chat/topbar-button
|
||||||
:component chat/chat}
|
:component chat/chat}
|
||||||
|
;; :component #(stack-with-switcher/overlap-stack chat/chat :chat)}
|
||||||
|
|
||||||
;Pinned messages
|
;Pinned messages
|
||||||
{:name :chat-pinned-messages
|
{:name :chat-pinned-messages
|
||||||
@@ -914,5 +917,7 @@
|
|||||||
quo.preview/main-screens)
|
quo.preview/main-screens)
|
||||||
(when config/quo-preview-enabled?
|
(when config/quo-preview-enabled?
|
||||||
quo2.preview/screens)
|
quo2.preview/screens)
|
||||||
|
(when config/quo-preview-enabled?
|
||||||
|
navigation2.screens/screens)
|
||||||
(when config/quo-preview-enabled?
|
(when config/quo-preview-enabled?
|
||||||
quo2.preview/main-screens)))
|
quo2.preview/main-screens)))
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
[status-im.ui.components.tabs :as tabs]
|
[status-im.ui.components.tabs :as tabs]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
|
||||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||||
[status-im.chat.models.reactions :as models.reactions]
|
[status-im.chat.models.reactions :as models.reactions]
|
||||||
[status-im.ui.screens.chat.components.reply :as components.reply]
|
[status-im.ui.screens.chat.components.reply :as components.reply]
|
||||||
@@ -175,8 +174,6 @@
|
|||||||
[tabs/tab-title state :timeline (i18n/label :t/timeline) (= tab :timeline)]
|
[tabs/tab-title state :timeline (i18n/label :t/timeline) (= tab :timeline)]
|
||||||
[tabs/tab-title state :status (i18n/label :t/my-status) (= tab :status)]]))
|
[tabs/tab-title state :status (i18n/label :t/my-status) (= tab :status)]]))
|
||||||
|
|
||||||
(def image-hash "e3010170122080c27fe972a95dbb4b0ead029d2c73d18610e849fac197e91068a918755e21b2")
|
|
||||||
|
|
||||||
(defn timeline []
|
(defn timeline []
|
||||||
(let [messages @(re-frame/subscribe [:chats/timeline-messages-stream])
|
(let [messages @(re-frame/subscribe [:chats/timeline-messages-stream])
|
||||||
loading-messages? @(re-frame/subscribe [:chats/loading-messages? constants/timeline-chat-id])
|
loading-messages? @(re-frame/subscribe [:chats/loading-messages? constants/timeline-chat-id])
|
||||||
@@ -191,10 +188,10 @@
|
|||||||
(if no-messages?
|
(if no-messages?
|
||||||
[react/view {:padding-horizontal 32
|
[react/view {:padding-horizontal 32
|
||||||
:margin-top 64}
|
:margin-top 64}
|
||||||
[react/image {:style {:width 140
|
[react/fast-image {:style {:width 140
|
||||||
:height 140
|
:height 140
|
||||||
:align-self :center}
|
:align-self :center}
|
||||||
:source {:uri (contenthash/url image-hash)}}]
|
:source {:uri "https://bafybeieayj76s4vjlw5uwdvnakosy46rqyioqsp2ygl6sedivemhkxrbwi.ipfs.cf-ipfs.com"}}]
|
||||||
[react/view (styles/descr-container)
|
[react/view (styles/descr-container)
|
||||||
[react/text {:style {:color colors/gray
|
[react/text {:style {:color colors/gray
|
||||||
:line-height 22}}
|
:line-height 22}}
|
||||||
|
|||||||
@@ -5,54 +5,56 @@
|
|||||||
[status-im.ui.components.icons.icons :as icons]
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.screens.stickers.styles :as styles]
|
[status-im.ui.screens.stickers.styles :as styles]
|
||||||
[status-im.utils.contenthash :as contenthash]
|
[status-im.utils.money :as money]
|
||||||
[status-im.utils.money :as money])
|
[status-im.utils.handlers :refer [<sub]])
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
|
(defn cache [url]
|
||||||
|
(str url "&download=true"))
|
||||||
|
|
||||||
(defn- thumbnail-icon [uri size]
|
(defn- thumbnail-icon [uri size]
|
||||||
[react/fast-image {:style {:width size :height size :border-radius (/ size 2)}
|
[react/fast-image {:style {:width size :height size :border-radius (/ size 2)}
|
||||||
:source {:uri uri}}])
|
:source {:uri (cache uri)}}])
|
||||||
|
|
||||||
(defn- installed-icon []
|
(defn price-badge [_]
|
||||||
[react/view styles/installed-icon
|
(let [chain (<sub [:ethereum/chain-keyword])
|
||||||
[icons/icon :main-icons/check {:color colors/white-persist :height 20 :width 20}]])
|
balance (<sub [:balance-default])]
|
||||||
|
(fn [{:keys [id price pending owned installed]}]
|
||||||
|
(let [snt (if (= :mainnet chain) (:SNT balance) (:STT balance))
|
||||||
|
price (money/bignumber price)
|
||||||
|
not-enough-snt? (or (nil? snt) (money/equal-to snt 0) (money/greater-than price snt))
|
||||||
|
free (money/equal-to price 0)]
|
||||||
|
(if installed
|
||||||
|
[react/view styles/installed-icon
|
||||||
|
[icons/icon :main-icons/check {:color colors/white-persist :height 20 :width 20}]]
|
||||||
|
[react/touchable-highlight {:on-press #(cond pending nil
|
||||||
|
(or owned free)
|
||||||
|
(re-frame/dispatch [:stickers/install-pack id])
|
||||||
|
not-enough-snt? nil
|
||||||
|
:else (re-frame/dispatch [:stickers/buy-pack id]))}
|
||||||
|
[react/view (styles/price-badge (and (not (or owned free)) not-enough-snt?))
|
||||||
|
(when (and (not free) (not owned))
|
||||||
|
[icons/tiny-icon :tiny-icons/tiny-snt {:color colors/white-persist :container-style {:margin-right 6}}])
|
||||||
|
(if pending
|
||||||
|
[react/activity-indicator {:animating true
|
||||||
|
:color colors/white-persist}]
|
||||||
|
[react/text {:style {:color colors/white-persist}
|
||||||
|
:accessibility-label :sticker-pack-price}
|
||||||
|
(cond owned (i18n/label :t/install)
|
||||||
|
free (i18n/label :t/free)
|
||||||
|
:else (str (money/wei-> :eth price)))])]])))))
|
||||||
|
|
||||||
(defview price-badge [price id owned? pending]
|
(defn pack-badge [{:keys [name author thumbnail preview id] :as pack}]
|
||||||
(letsubs [chain [:ethereum/chain-keyword]
|
|
||||||
balance [:balance-default]]
|
|
||||||
(let [snt (money/to-number (if (= :mainnet chain) (:SNT balance) (:STT balance)))
|
|
||||||
not-enough-snt? (> price snt)
|
|
||||||
no-snt? (or (nil? snt) (zero? snt))]
|
|
||||||
[react/touchable-highlight {:on-press #(cond pending nil
|
|
||||||
(or owned? (zero? price))
|
|
||||||
(re-frame/dispatch [:stickers/install-pack id])
|
|
||||||
(or no-snt? not-enough-snt?) nil
|
|
||||||
:else (re-frame/dispatch [:stickers/buy-pack id price]))}
|
|
||||||
[react/view (styles/price-badge (and (not (or owned? (zero? price))) (or no-snt? not-enough-snt?)))
|
|
||||||
(when (and (not (zero? price)) (not owned?))
|
|
||||||
[icons/tiny-icon :tiny-icons/tiny-snt {:color colors/white-persist :container-style {:margin-right 6}}])
|
|
||||||
(if pending
|
|
||||||
[react/activity-indicator {:animating true
|
|
||||||
:color colors/white-persist}]
|
|
||||||
[react/text {:style {:color colors/white-persist}
|
|
||||||
:accessibility-label :sticker-pack-price}
|
|
||||||
(cond owned? (i18n/label :t/install)
|
|
||||||
(zero? price) (i18n/label :t/free)
|
|
||||||
:else (str (money/wei-> :eth price)))])]])))
|
|
||||||
|
|
||||||
(defn pack-badge [{:keys [name author price thumbnail preview id installed owned pending]}]
|
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack {:id id}])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack {:id id}])}
|
||||||
[react/view {:margin-bottom 27}
|
[react/view {:margin-bottom 27}
|
||||||
[react/fast-image {:style {:height 200 :border-radius 20} :source {:uri (contenthash/url preview)}}]
|
[react/fast-image {:style {:height 200 :border-radius 20} :source {:uri (cache preview)}}]
|
||||||
[react/view {:height 64 :align-items :center :flex-direction :row}
|
[react/view {:height 64 :align-items :center :flex-direction :row}
|
||||||
[thumbnail-icon (contenthash/url thumbnail) 40]
|
[thumbnail-icon thumbnail 40]
|
||||||
[react/view {:padding-horizontal 16 :flex 1}
|
[react/view {:padding-horizontal 16 :flex 1}
|
||||||
[react/text {:accessibility-label :sticker-pack-name} name]
|
[react/text {:accessibility-label :sticker-pack-name} name]
|
||||||
[react/text {:style {:color colors/gray :margin-top 6}
|
[react/text {:style {:color colors/gray :margin-top 6}
|
||||||
:accessibility-label :sticker-pack-author} author]]
|
:accessibility-label :sticker-pack-author} author]]
|
||||||
(if installed
|
[price-badge pack]]]])
|
||||||
[installed-icon]
|
|
||||||
[price-badge price id owned pending])]]])
|
|
||||||
|
|
||||||
(defview packs []
|
(defview packs []
|
||||||
(letsubs [packs [:stickers/all-packs]]
|
(letsubs [packs [:stickers/all-packs]]
|
||||||
@@ -70,28 +72,25 @@
|
|||||||
(def sticker-icon-size 60)
|
(def sticker-icon-size 60)
|
||||||
|
|
||||||
(defview pack-main []
|
(defview pack-main []
|
||||||
(letsubs [{:keys [id name author price thumbnail
|
(letsubs [{:keys [name author thumbnail stickers]
|
||||||
stickers installed owned pending]
|
:as pack}
|
||||||
:as pack}
|
|
||||||
[:stickers/get-current-pack]]
|
[:stickers/get-current-pack]]
|
||||||
[react/keyboard-avoiding-view {:flex 1}
|
[react/keyboard-avoiding-view {:flex 1}
|
||||||
(if pack
|
(if pack
|
||||||
[react/view {:flex 1}
|
[react/view {:flex 1}
|
||||||
[react/view {:height 74 :align-items :center :flex-direction :row :padding-horizontal 16}
|
[react/view {:height 74 :align-items :center :flex-direction :row :padding-horizontal 16}
|
||||||
[thumbnail-icon (contenthash/url thumbnail) 64]
|
[thumbnail-icon thumbnail 64]
|
||||||
[react/view {:padding-horizontal 16 :flex 1}
|
[react/view {:padding-horizontal 16 :flex 1}
|
||||||
[react/text {:style {:typography :header}} name]
|
[react/text {:style {:typography :header}} name]
|
||||||
[react/text {:style {:color colors/gray :margin-top 6}} author]]
|
[react/text {:style {:color colors/gray :margin-top 6}} author]]
|
||||||
(if installed
|
[price-badge pack]]
|
||||||
[installed-icon]
|
|
||||||
[price-badge price id owned pending])]
|
|
||||||
[react/view {:style {:padding-top 8 :flex 1}}
|
[react/view {:style {:padding-top 8 :flex 1}}
|
||||||
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
|
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
|
||||||
[react/view {:flex-direction :row :flex-wrap :wrap}
|
[react/view {:flex-direction :row :flex-wrap :wrap}
|
||||||
(for [{:keys [hash]} stickers]
|
(for [{:keys [url]} stickers]
|
||||||
^{:key hash}
|
^{:key url}
|
||||||
[react/fast-image {:style (styles/sticker-image sticker-icon-size)
|
[react/fast-image {:style (styles/sticker-image sticker-icon-size)
|
||||||
:source {:uri (contenthash/url hash)}}])]]]]
|
:source {:uri (cache url)}}])]]]]
|
||||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||||
[react/activity-indicator {:animating true}]])]))
|
[react/activity-indicator {:animating true}]])]))
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
|
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
|
||||||
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
||||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||||
|
(def stickers-test-enabled? (enabled? (get-config :STICKERS_TEST_ENABLED "0")))
|
||||||
|
|
||||||
;; CONFIG VALUES
|
;; CONFIG VALUES
|
||||||
(def log-level
|
(def log-level
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
(ns status-im.utils.contenthash
|
|
||||||
"TODO: currently we only support encoding/decoding ipfs contenthash
|
|
||||||
implementing swarm and other protocols will come later"
|
|
||||||
(:refer-clojure :exclude [cat])
|
|
||||||
(:require ["hi-base32" :as hi-base32]
|
|
||||||
[alphabase.hex :as hex]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[status-im.ethereum.core :as ethereum]))
|
|
||||||
|
|
||||||
(defn decode
|
|
||||||
"TODO properly decode the CID
|
|
||||||
extract the content-type using varint ns"
|
|
||||||
[hex]
|
|
||||||
(when (and hex (not= hex "0x"))
|
|
||||||
(cond
|
|
||||||
(and (string/starts-with? hex "0xe40101"))
|
|
||||||
;; content type can be 2 or 4 bytes
|
|
||||||
;; we expect 1b20 (hash algorithm keccak256 and hash length 64)
|
|
||||||
;; before the hash so we split the contenthash there
|
|
||||||
(when-let [hash (second (string/split hex "1b20"))]
|
|
||||||
{:namespace :swarm
|
|
||||||
:hash hash})
|
|
||||||
(and (= 78 (count hex))
|
|
||||||
(string/starts-with? hex "0xe3010170"))
|
|
||||||
{:namespace :ipfs
|
|
||||||
:hash (str "b" (-> hex
|
|
||||||
(subs 6)
|
|
||||||
hex/decode
|
|
||||||
((fn [v] (.encode ^js hi-base32 v)))
|
|
||||||
(string/replace #"=" "")
|
|
||||||
string/lower-case))}
|
|
||||||
(and (string/starts-with? hex "0xe50101700"))
|
|
||||||
{:namespace :ipns
|
|
||||||
:hash (-> hex
|
|
||||||
(subs 14)
|
|
||||||
((fn [v] (str "0x" v)))
|
|
||||||
(ethereum/hex-to-utf8))})))
|
|
||||||
|
|
||||||
(defn ipfs-url [hash]
|
|
||||||
(str "https://" hash ".ipfs.cf-ipfs.com"))
|
|
||||||
|
|
||||||
(defn url-fn [hex]
|
|
||||||
(let [{:keys [namespace hash]} (decode (ethereum/normalized-hex hex))]
|
|
||||||
(case namespace
|
|
||||||
:ipfs (ipfs-url hash)
|
|
||||||
"")))
|
|
||||||
|
|
||||||
(def url (memoize url-fn))
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
(ns status-im.utils.contenthash-test
|
|
||||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
|
||||||
[status-im.utils.contenthash :as contenthash]))
|
|
||||||
|
|
||||||
;; we reuse the exemple from EIP-1577 but omit content type: dag-pb (0x70)
|
|
||||||
;; in the contenthash as we do not support it yet
|
|
||||||
|
|
||||||
(deftest contenthash-decode
|
|
||||||
(testing "decoding a valid ipfs hash"
|
|
||||||
(is (= (contenthash/decode "0xe3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f")
|
|
||||||
{:namespace :ipfs
|
|
||||||
:hash "bafybeibj6lixxzqtsb45ysdjnupvqkufgdvzqbnvmhw2kf7cfkesy7r7d4"})))
|
|
||||||
(testing "decoding a valid ipns hash"
|
|
||||||
(is (= (contenthash/decode "0xe5010170000f6170702e756e69737761702e6f7267")
|
|
||||||
{:namespace :ipns
|
|
||||||
:hash "app.uniswap.org"})))
|
|
||||||
(testing "decoding a valid swarm hash"
|
|
||||||
(is (= (contenthash/decode "0xe40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162")
|
|
||||||
{:namespace :swarm
|
|
||||||
:hash "d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162"})))
|
|
||||||
(testing "decoding an invalid ipfs hash"
|
|
||||||
(is (nil? (contenthash/decode "0xe301122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e2"))))
|
|
||||||
(testing "decoding random garbage"
|
|
||||||
(is (nil? (contenthash/decode "0xabcdef1234567890"))))
|
|
||||||
(testing "decoding nil"
|
|
||||||
(is (nil? (contenthash/decode nil)))))
|
|
||||||
@@ -41,6 +41,10 @@
|
|||||||
[bn1 bn2]
|
[bn1 bn2]
|
||||||
(.greaterThan ^js bn1 bn2))
|
(.greaterThan ^js bn1 bn2))
|
||||||
|
|
||||||
|
(defn equal-to
|
||||||
|
[bn1 bn2]
|
||||||
|
(.eq ^js bn1 bn2))
|
||||||
|
|
||||||
(defn sub [bn1 bn2]
|
(defn sub [bn1 bn2]
|
||||||
(.sub ^js bn1 bn2))
|
(.sub ^js bn1 bn2))
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,21 @@
|
|||||||
(ns status-im.utils.prices
|
(ns status-im.utils.prices
|
||||||
(:require [clojure.string :as string]
|
(:require [status-im.ethereum.json-rpc :as json-rpc]))
|
||||||
[status-im.utils.http :as http]
|
|
||||||
[status-im.utils.types :as types]))
|
|
||||||
|
|
||||||
;; Responsible for interacting with Cryptocompare API to get current prices for
|
(defn- format-price-resp [resp to mainnet?]
|
||||||
;; currencies and tokens.
|
|
||||||
;;
|
|
||||||
;; No tests since fetch API (via http-get) relies on `window` being available.
|
|
||||||
;;
|
|
||||||
;; Example usage:
|
|
||||||
;; (get-prices "ETH" "USD" println print)
|
|
||||||
|
|
||||||
(def api-url "https://min-api.cryptocompare.com/data")
|
|
||||||
(def status-identifier "extraParams=Status.im")
|
|
||||||
|
|
||||||
(defn- ->url-param-syms [syms]
|
|
||||||
((comp (partial string/join ",") (partial map name)) syms))
|
|
||||||
|
|
||||||
(defn- gen-price-url [fsyms tsyms]
|
|
||||||
(str api-url "/pricemultifull?fsyms=" (->url-param-syms fsyms) "&tsyms=" (->url-param-syms tsyms) "&" status-identifier))
|
|
||||||
|
|
||||||
(defn- format-price-resp [resp mainnet?]
|
|
||||||
;;NOTE(this check is to allow value conversion for sidechains with native currencies listed on cryptocompare
|
|
||||||
;; under a symbol different than display symbol. Specific use case xDAI.
|
|
||||||
(if mainnet?
|
(if mainnet?
|
||||||
(when-let [RAW (:RAW (types/json->clj resp))]
|
(when (seq resp)
|
||||||
(into {} (for [[from entries] RAW]
|
(into {} (for [[from price] resp]
|
||||||
{from (into {} (for [[to entry] entries]
|
{from {(keyword to) {:from (name from)
|
||||||
{to {:from (name from)
|
:to to
|
||||||
:to (name to)
|
:price price}}})))
|
||||||
:price (:PRICE entry)
|
{:ETH (into {} (for [[_ price] resp]
|
||||||
:last-day (:OPEN24HOUR entry)}}))})))
|
{(keyword to) {:from "ETH"
|
||||||
(into {} (for [[_ entries] (:RAW (types/json->clj resp))]
|
:to to
|
||||||
{:ETH (into {} (for [[to entry] entries]
|
:price price}}))}))
|
||||||
{to {:from "ETH"
|
|
||||||
:to (name to)
|
|
||||||
:price (:PRICE entry)
|
|
||||||
:last-day (:OPEN24HOUR entry)}}))}))))
|
|
||||||
|
|
||||||
(defn get-prices [from to mainnet? on-success on-error]
|
(defn get-prices [from to mainnet? on-success on-error]
|
||||||
(http/get
|
(let [to (first to)]
|
||||||
(gen-price-url from to)
|
(json-rpc/call {:method "wallet_fetchPrices"
|
||||||
(fn [resp] (on-success (format-price-resp resp mainnet?)))
|
:params [from to]
|
||||||
on-error))
|
:on-success (fn [resp] (on-success (format-price-resp resp to mainnet?)))
|
||||||
|
:on-error on-error})))
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
(ns status-im.utils.prices-test
|
|
||||||
(:require [cljs.test :refer-macros [deftest is]]
|
|
||||||
[status-im.utils.prices :as prices]))
|
|
||||||
|
|
||||||
(deftest test-format-price-resp-mainnet
|
|
||||||
(is (= (#'status-im.utils.prices/format-price-resp
|
|
||||||
"{\"RAW\":{\"ETH\":{\"USD\":{\"TYPE\":\"5\",\"MARKET\":\"CCCAGG\",\"FROMSYMBOL\":\"ETH\",\"TOSYMBOL\":\"USD\",\"FLAGS\":\"4\",\"PRICE\":677.91,\"LASTUPDATE\":1525241472,\"LASTVOLUME\":0.69661268,\"LASTVOLUMETO\":472.0874471092,\"LASTTRADEID\":\"1525241472.6714\",\"VOLUMEDAY\":109859.96594606241,\"VOLUMEDAYTO\":73924561.52673237,\"VOLUME24HOUR\":408811.69032152055,\"VOLUME24HOURTO\":270617692.0100031,\"OPENDAY\":670.81,\"HIGHDAY\":681.06,\"LOWDAY\":662.13,\"OPEN24HOUR\":658.68,\"HIGH24HOUR\":681.67,\"LOW24HOUR\":638.25,\"LASTMARKET\":\"Kraken\",\"CHANGE24HOUR\":19.230000000000018,\"CHANGEPCT24HOUR\":2.919475314264896,\"CHANGEDAY\":7.100000000000023,\"CHANGEPCTDAY\":1.0584219078427608,\"SUPPLY\":99176837.749,\"MKTCAP\":67232970078.42458,\"TOTALVOLUME24H\":1308785.4697758215,\"TOTALVOLUME24HTO\":880718916.8398683}},\"SNT\":{\"USD\":{\"TYPE\":\"5\",\"MARKET\":\"CCCAGG\",\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"USD\",\"FLAGS\":\"1\",\"PRICE\":0.1562,\"LASTUPDATE\":1525241236,\"LASTVOLUME\":582.07218,\"LASTVOLUMETO\":90.919674516,\"LASTTRADEID\":\"237582608\",\"VOLUMEDAY\":259125.16382211001,\"VOLUMEDAYTO\":40450.5318867195,\"VOLUME24HOUR\":1451022.9449243098,\"VOLUME24HOURTO\":223465.71221695316,\"OPENDAY\":0.1573,\"HIGHDAY\":0.1592,\"LOWDAY\":0.1532,\"OPEN24HOUR\":0.15,\"HIGH24HOUR\":0.1657,\"LOW24HOUR\":0.1481,\"LASTMARKET\":\"Bitfinex\",\"CHANGE24HOUR\":0.006200000000000011,\"CHANGEPCT24HOUR\":4.133333333333341,\"CHANGEDAY\":-0.0010999999999999899,\"CHANGEPCTDAY\":-0.6993006993006928,\"SUPPLY\":6804870174.87817,\"MKTCAP\":1062920721.3159702,\"TOTALVOLUME24H\":239970152.87898657,\"TOTALVOLUME24HTO\":37480153.807917476}}},\"DISPLAY\":{\"ETH\":{\"USD\":{\"FROMSYMBOL\":\"Ξ\",\"TOSYMBOL\":\"$\",\"MARKET\":\"CryptoCompare Index\",\"PRICE\":\"$ 677.91\",\"LASTUPDATE\":\"Just now\",\"LASTVOLUME\":\"Ξ 0.6966\",\"LASTVOLUMETO\":\"$ 472.09\",\"LASTTRADEID\":\"1525241472.6714\",\"VOLUMEDAY\":\"Ξ 109,860.0\",\"VOLUMEDAYTO\":\"$ 73,924,561.5\",\"VOLUME24HOUR\":\"Ξ 408,811.7\",\"VOLUME24HOURTO\":\"$ 270,617,692.0\",\"OPENDAY\":\"$ 670.81\",\"HIGHDAY\":\"$ 681.06\",\"LOWDAY\":\"$ 662.13\",\"OPEN24HOUR\":\"$ 658.68\",\"HIGH24HOUR\":\"$ 681.67\",\"LOW24HOUR\":\"$ 638.25\",\"LASTMARKET\":\"Kraken\",\"CHANGE24HOUR\":\"$ 19.23\",\"CHANGEPCT24HOUR\":\"2.92\",\"CHANGEDAY\":\"$ 7.10\",\"CHANGEPCTDAY\":\"1.06\",\"SUPPLY\":\"Ξ 99,176,837.7\",\"MKTCAP\":\"$ 67.23 B\",\"TOTALVOLUME24H\":\"Ξ 1,308.79 K\",\"TOTALVOLUME24HTO\":\"$ 880.72 M\"}},\"SNT\":{\"USD\":{\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"$\",\"MARKET\":\"CryptoCompare Index\",\"PRICE\":\"$ 0.1562\",\"LASTUPDATE\":\"3 min ago\",\"LASTVOLUME\":\"SNT 582.07\",\"LASTVOLUMETO\":\"$ 90.92\",\"LASTTRADEID\":\"237582608\",\"VOLUMEDAY\":\"SNT 259,125.2\",\"VOLUMEDAYTO\":\"$ 40,450.5\",\"VOLUME24HOUR\":\"SNT 1,451,022.9\",\"VOLUME24HOURTO\":\"$ 223,465.7\",\"OPENDAY\":\"$ 0.1573\",\"HIGHDAY\":\"$ 0.1592\",\"LOWDAY\":\"$ 0.1532\",\"OPEN24HOUR\":\"$ 0.1500\",\"HIGH24HOUR\":\"$ 0.1657\",\"LOW24HOUR\":\"$ 0.1481\",\"LASTMARKET\":\"Bitfinex\",\"CHANGE24HOUR\":\"$ 0.0062\",\"CHANGEPCT24HOUR\":\"4.13\",\"CHANGEDAY\":\"$ -0.0011\",\"CHANGEPCTDAY\":\"-0.70\",\"SUPPLY\":\"SNT 6,804,870,174.9\",\"MKTCAP\":\"$ 1,062.92 M\",\"TOTALVOLUME24H\":\"SNT 239.97 M\",\"TOTALVOLUME24HTO\":\"$ 37.48 M\"}}}}" true)
|
|
||||||
{:ETH {:USD {:from "ETH", :to "USD", :price 677.91, :last-day 658.68}}
|
|
||||||
:SNT {:USD {:from "SNT", :to "USD", :price 0.1562, :last-day 0.15}}})))
|
|
||||||
|
|
||||||
(deftest test-format-price-resp-non-mainnet
|
|
||||||
(is (= (#'status-im.utils.prices/format-price-resp
|
|
||||||
"{\"RAW\":{\"SNT\":{\"USD\":{\"TYPE\":\"5\",\"MARKET\":\"CCCAGG\",\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"USD\",\"FLAGS\":\"4\",\"PRICE\":0.03511847069999999,\"LASTUPDATE\":1539953131,\"LASTVOLUME\":0,\"LASTVOLUMETO\":0,\"LASTTRADEID\":0,\"VOLUMEDAY\":0,\"VOLUMEDAYTO\":0,\"VOLUME24HOUR\":45900.43172688,\"VOLUME24HOURTO\":1645.4590651064077,\"OPENDAY\":0.0357005448,\"HIGHDAY\":0.0358298946,\"LOWDAY\":0.034924446,\"OPEN24HOUR\":0.0360239193,\"HIGH24HOUR\":0.03621794399999999,\"LOW24HOUR\":0.0348597711,\"LASTMARKET\":\"IDAX\",\"CHANGE24HOUR\":-0.0009054486000000112,\"CHANGEPCT24HOUR\":-2.5134649910233704,\"CHANGEDAY\":-0.0005820741000000101,\"CHANGEPCTDAY\":-1.630434782608724,\"SUPPLY\":6804870174.87817,\"MKTCAP\":238976633.8537628,\"TOTALVOLUME24H\":53502856.59548309,\"TOTALVOLUME24HTO\":1878972.0078131626}}},\"DISPLAY\":{\"SNT\":{\"USD\":{\"FROMSYMBOL\":\"SNT\",\"TOSYMBOL\":\"$\",\"MARKET\":\"CryptoCompare Index\",\"PRICE\":\"$ 0.03512\",\"LASTUPDATE\":\"Just now\",\"LASTVOLUME\":\"SNT 0\",\"LASTVOLUMETO\":\"$ 0\",\"LASTTRADEID\":0,\"VOLUMEDAY\":\"SNT 0\",\"VOLUMEDAYTO\":\"$ 0\",\"VOLUME24HOUR\":\"SNT 45,900.4\",\"VOLUME24HOURTO\":\"$ 1,645.46\",\"OPENDAY\":\"$ 0.03570\",\"HIGHDAY\":\"$ 0.03583\",\"LOWDAY\":\"$ 0.03492\",\"OPEN24HOUR\":\"$ 0.03602\",\"HIGH24HOUR\":\"$ 0.03622\",\"LOW24HOUR\":\"$ 0.03486\",\"LASTMARKET\":\"IDAX\",\"CHANGE24HOUR\":\"$ -0.00091\",\"CHANGEPCT24HOUR\":\"-2.51\",\"CHANGEDAY\":\"$ -0.00058\",\"CHANGEPCTDAY\":\"-1.63\",\"SUPPLY\":\"SNT 6,804,870,174.9\",\"MKTCAP\":\"$ 238.98 M\",\"TOTALVOLUME24H\":\"SNT 53.50 M\",\"TOTALVOLUME24HTO\":\"$ 1,878.97 K\"}}}}" false)
|
|
||||||
{:ETH {:USD {:from "ETH", :to "USD", :price 0.03511847069999999, :last-day 0.0360239193}}})))
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.98.5",
|
"version": "v0.98.6",
|
||||||
"commit-sha1": "640793fe85d9a9eef9eb3712cda1c5a1ceea401a",
|
"commit-sha1": "0048aaebcc7859a6f0dd7cdf0266fe029f3066fc",
|
||||||
"src-sha256": "1k1iw69yw23k29y0b1yvnggjqlmfnwavk4mq1sf2h3wrlb8x47kd"
|
"src-sha256": "1px3ddfbpnlqyzkbp8v4bb8dh5f69cx4lwif8vspw60rr4gpppys"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import json
|
|
||||||
import requests
|
|
||||||
import logging
|
|
||||||
import itertools
|
|
||||||
import emoji
|
|
||||||
import base64
|
import base64
|
||||||
from os import environ
|
import itertools
|
||||||
from support.base_test_report import BaseTestReport
|
import json
|
||||||
from sys import argv
|
import logging
|
||||||
|
import re
|
||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
|
from os import environ
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
import emoji
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from support.base_test_report import BaseTestReport
|
||||||
|
|
||||||
|
|
||||||
class TestrailReport(BaseTestReport):
|
class TestrailReport(BaseTestReport):
|
||||||
@@ -114,11 +117,16 @@ class TestrailReport(BaseTestReport):
|
|||||||
test_cases['pr']['1_1_chat_commands'] = 50825
|
test_cases['pr']['1_1_chat_commands'] = 50825
|
||||||
test_cases['pr']['ens'] = 50827
|
test_cases['pr']['ens'] = 50827
|
||||||
test_cases['pr']['sync'] = 50834
|
test_cases['pr']['sync'] = 50834
|
||||||
|
test_cases['pr']['browser'] = 50812
|
||||||
## Nightly e2e
|
## Nightly e2e
|
||||||
test_cases['nightly']['medium'] = 736
|
test_cases['nightly']['medium'] = 736
|
||||||
test_cases['nightly']['chat'] = 50811
|
test_cases['nightly']['chat'] = 50811
|
||||||
test_cases['nightly']['browser'] = 50826
|
test_cases['nightly']['browser'] = 50826
|
||||||
test_cases['nightly']['profile'] = 50828
|
test_cases['nightly']['profile'] = 50828
|
||||||
|
test_cases['nightly']['deep_link'] = 50836
|
||||||
|
test_cases['nightly']['share_profile'] = 50837
|
||||||
|
test_cases['nightly']['chat_2'] = 50838
|
||||||
|
test_cases['nightly']['group_chat'] = 50839
|
||||||
## Upgrade e2e
|
## Upgrade e2e
|
||||||
test_cases['upgrade']['general'] = 881
|
test_cases['upgrade']['general'] = 881
|
||||||
|
|
||||||
@@ -146,10 +154,11 @@ class TestrailReport(BaseTestReport):
|
|||||||
return case_ids
|
return case_ids
|
||||||
|
|
||||||
def add_results(self):
|
def add_results(self):
|
||||||
for test in self.get_all_tests():
|
data = list()
|
||||||
|
all_tests = self.get_all_tests()
|
||||||
|
for test in all_tests:
|
||||||
test_steps = "# Steps: \n"
|
test_steps = "# Steps: \n"
|
||||||
devices = str()
|
devices = str()
|
||||||
method = 'add_result_for_case/%s/%s' % (self.run_id, test.testrail_case_id)
|
|
||||||
last_testrun = test.testruns[-1]
|
last_testrun = test.testruns[-1]
|
||||||
for step in last_testrun.steps:
|
for step in last_testrun.steps:
|
||||||
test_steps += step + "\n"
|
test_steps += step + "\n"
|
||||||
@@ -166,21 +175,39 @@ class TestrailReport(BaseTestReport):
|
|||||||
comment += '%s' % ('# Error: \n %s \n' % emoji.demojize(last_testrun.error)) + devices + test_steps
|
comment += '%s' % ('# Error: \n %s \n' % emoji.demojize(last_testrun.error)) + devices + test_steps
|
||||||
else:
|
else:
|
||||||
comment += devices + test_steps
|
comment += devices + test_steps
|
||||||
data = {'status_id': self.outcomes['undefined_fail'] if last_testrun.error else self.outcomes['passed'],
|
data.append(
|
||||||
'comment': comment}
|
{'case_id': test.testrail_case_id,
|
||||||
result = self.post(method, data=data)
|
'status_id': self.outcomes['undefined_fail'] if last_testrun.error else self.outcomes['passed'],
|
||||||
try:
|
'comment': comment})
|
||||||
result_id = result['id']
|
|
||||||
except KeyError:
|
results = self.post('add_results_for_cases/%s' % self.run_id, data={"results": data})
|
||||||
result_id = ''
|
try:
|
||||||
print("Got TestRail error when adding results for case %s: \n%s" % (test.testrail_case_id, result))
|
results[0]
|
||||||
|
except IndexError:
|
||||||
|
print("Got TestRail error when adding results: \n%s" % results)
|
||||||
|
|
||||||
|
for test in all_tests:
|
||||||
|
last_testrun = test.testruns[-1]
|
||||||
if last_testrun.error:
|
if last_testrun.error:
|
||||||
try:
|
try:
|
||||||
for geth in test.geth_paths.keys():
|
device = list(last_testrun.jobs.keys())[0]
|
||||||
self.add_attachment(method='add_attachment_to_result/%s' % str(result_id),
|
except IndexError:
|
||||||
path=test.geth_paths[geth])
|
continue
|
||||||
except AttributeError:
|
for res in results:
|
||||||
pass
|
if last_testrun.first_commands:
|
||||||
|
pattern = r"%s\?auth=.*#%s" % (device, str(last_testrun.first_commands[device]))
|
||||||
|
else:
|
||||||
|
pattern = device
|
||||||
|
if re.findall(pattern, res['comment']):
|
||||||
|
res_id = res['id']
|
||||||
|
try:
|
||||||
|
for geth in test.geth_paths.keys():
|
||||||
|
self.add_attachment(method='add_attachment_to_result/%s' % str(res_id),
|
||||||
|
path=test.geth_paths[geth])
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
break
|
||||||
|
|
||||||
self.change_test_run_description()
|
self.change_test_run_description()
|
||||||
|
|
||||||
def change_test_run_description(self):
|
def change_test_run_description(self):
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ def get_capabilities_sauce_lab():
|
|||||||
desired_caps['deviceName'] = 'Android GoogleAPI Emulator'
|
desired_caps['deviceName'] = 'Android GoogleAPI Emulator'
|
||||||
desired_caps['deviceOrientation'] = "portrait"
|
desired_caps['deviceOrientation'] = "portrait"
|
||||||
desired_caps['commandTimeout'] = 600
|
desired_caps['commandTimeout'] = 600
|
||||||
desired_caps['idleTimeout'] = 800
|
desired_caps['idleTimeout'] = 1000
|
||||||
desired_caps['unicodeKeyboard'] = True
|
desired_caps['unicodeKeyboard'] = True
|
||||||
desired_caps['automationName'] = 'UiAutomator2'
|
desired_caps['automationName'] = 'UiAutomator2'
|
||||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||||
|
|||||||
@@ -216,6 +216,16 @@ def should_save_device_stats(config):
|
|||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
outcome = yield
|
outcome = yield
|
||||||
report = outcome.get_result()
|
report = outcome.get_result()
|
||||||
|
if "xdist_group" in item.keywords._markers and report.when == "setup" and report.failed:
|
||||||
|
test_suite_data.set_current_test(item.name, testrail_case_id=get_testrail_case_id(item))
|
||||||
|
test_suite_data.current_test.create_new_testrun()
|
||||||
|
test_suite_data.current_test.group_name = item.instance.__class__.__name__
|
||||||
|
error = report.longreprtext
|
||||||
|
exception = re.findall('E.*Message:|E.*Error:|E.*Failed:', error)
|
||||||
|
if exception:
|
||||||
|
error = error.replace(re.findall('E.*Message:|E.*Error:|E.*Failed:', report.longreprtext)[0], '')
|
||||||
|
test_suite_data.current_test.testruns[-1].error = "Test setup failed: \n" + error
|
||||||
|
github_report.save_test(test_suite_data.current_test)
|
||||||
if report.when == 'call':
|
if report.when == 'call':
|
||||||
is_sauce_env = item.config.getoption('env') == 'sauce'
|
is_sauce_env = item.config.getoption('env') == 'sauce'
|
||||||
current_test = test_suite_data.current_test
|
current_test = test_suite_data.current_test
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import pytest
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="commands_2")
|
@pytest.mark.xdist_group(name="commands_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestCommandsMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
class TestCommandsMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -211,7 +210,6 @@ class TestCommandsMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="1_1_chat_2")
|
@pytest.mark.xdist_group(name="1_1_chat_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -221,14 +219,62 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
|||||||
cls.home_1 = cls.device_1.create_user(enable_notifications=True)
|
cls.home_1 = cls.device_1.create_user(enable_notifications=True)
|
||||||
cls.home_2 = cls.device_2.create_user(enable_notifications=True)
|
cls.home_2 = cls.device_2.create_user(enable_notifications=True)
|
||||||
cls.profile_1 = cls.home_1.profile_button.click()
|
cls.profile_1 = cls.home_1.profile_button.click()
|
||||||
cls.default_username_1 = cls.profile_1.default_username_text.text
|
cls.public_key_1, cls.default_username_1 = cls.profile_1.get_public_key_and_username(return_username=True)
|
||||||
cls.profile_1.home_button.click()
|
cls.profile_1.home_button.click()
|
||||||
|
cls.profile_2 = cls.home_2.profile_button.click()
|
||||||
|
cls.default_username_2 = cls.profile_2.default_username_text.text
|
||||||
|
cls.profile_2.home_button.click()
|
||||||
cls.public_key_2, cls.default_username_2 = cls.home_2.get_public_key_and_username(return_username=True)
|
cls.public_key_2, cls.default_username_2 = cls.home_2.get_public_key_and_username(return_username=True)
|
||||||
cls.chat_1 = cls.home_1.add_contact(cls.public_key_2)
|
cls.chat_1 = cls.home_1.add_contact(cls.public_key_2)
|
||||||
cls.chat_1.send_message('hey')
|
cls.chat_1.send_message('hey')
|
||||||
cls.home_2.home_button.double_click()
|
cls.home_2.home_button.double_click()
|
||||||
cls.chat_2 = cls.home_2.get_chat(cls.default_username_1).click()
|
cls.chat_2 = cls.home_2.get_chat(cls.default_username_1).click()
|
||||||
|
|
||||||
|
@marks.testrail_id(702267)
|
||||||
|
def test_1_1_chat_unread_counter_preview_highlited(self):
|
||||||
|
self.chat_2.get_back_to_home_view()
|
||||||
|
|
||||||
|
message_1, message_2 = 'test message2', 'test'
|
||||||
|
chat_element = self.home_2.get_chat(self.default_username_1)
|
||||||
|
self.home_2.dapp_tab_button.click()
|
||||||
|
self.chat_1.send_message(message_1)
|
||||||
|
|
||||||
|
if self.home_2.home_button.counter.text != '1':
|
||||||
|
self.errors.append('New messages counter is not shown on Home button')
|
||||||
|
self.device_2.home_button.click()
|
||||||
|
if chat_element.new_messages_counter.text != '1':
|
||||||
|
self.errors.append('New messages counter is not shown on chat element')
|
||||||
|
chat_2 = chat_element.click()
|
||||||
|
chat_2.add_to_contacts.click()
|
||||||
|
|
||||||
|
self.home_2.home_button.double_click()
|
||||||
|
|
||||||
|
if self.home_2.home_button.counter.is_element_displayed():
|
||||||
|
self.errors.append('New messages counter is shown on Home button for already seen message')
|
||||||
|
if chat_element.new_messages_counter.text == '1':
|
||||||
|
self.errors.append('New messages counter is shown on chat element for already seen message')
|
||||||
|
self.home_2.delete_chat_long_press(self.default_username_1)
|
||||||
|
|
||||||
|
self.home_2.just_fyi("Checking preview of message and chat highlighting")
|
||||||
|
self.chat_1.send_message(message_2)
|
||||||
|
chat_2_element = self.home_2.get_chat(self.default_username_1)
|
||||||
|
if chat_2_element.chat_preview.is_element_differs_from_template('highligted_preview.png', 0):
|
||||||
|
self.errors.append("Preview message is not hightligted or text is not shown! ")
|
||||||
|
self.home_2.get_chat(self.default_username_1).click()
|
||||||
|
self.home_2.home_button.double_click()
|
||||||
|
if not self.home_2.get_chat(self.default_username_1).chat_preview.is_element_differs_from_template(
|
||||||
|
'highligted_preview.png', 0):
|
||||||
|
self.errors.append("Preview message is still highlighted after opening ")
|
||||||
|
|
||||||
|
self.home_2.just_fyi("Removing user from contacts for the case 5315")
|
||||||
|
chat_element.click()
|
||||||
|
chat_2.chat_options.click()
|
||||||
|
chat_2.view_profile_button.click()
|
||||||
|
chat_2.remove_from_contacts.click()
|
||||||
|
chat_2.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(6315)
|
@marks.testrail_id(6315)
|
||||||
def test_1_1_chat_message_reaction(self):
|
def test_1_1_chat_message_reaction(self):
|
||||||
message_from_sender = "Message sender"
|
message_from_sender = "Message sender"
|
||||||
@@ -240,6 +286,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
|||||||
self.errors.append("Counter of reaction is not updated on your own message!")
|
self.errors.append("Counter of reaction is not updated on your own message!")
|
||||||
|
|
||||||
self.device_2.just_fyi("Receiver set own emoji and verifies counter on received message in 1-1 chat")
|
self.device_2.just_fyi("Receiver set own emoji and verifies counter on received message in 1-1 chat")
|
||||||
|
self.home_2.get_chat(self.default_username_1).click()
|
||||||
message_receiver = self.chat_2.chat_element_by_text(message_from_sender)
|
message_receiver = self.chat_2.chat_element_by_text(message_from_sender)
|
||||||
if message_receiver.emojis_below_message(own=False) != 1:
|
if message_receiver.emojis_below_message(own=False) != 1:
|
||||||
self.errors.append("Counter of reaction is not updated on received message!")
|
self.errors.append("Counter of reaction is not updated on received message!")
|
||||||
@@ -529,7 +576,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
|||||||
self.chat_2.share_via_messenger()
|
self.chat_2.share_via_messenger()
|
||||||
if not self.chat_2.image_in_android_messenger.is_element_present():
|
if not self.chat_2.image_in_android_messenger.is_element_present():
|
||||||
self.errors.append("Can't share image")
|
self.errors.append("Can't share image")
|
||||||
self.chat_2.click_system_back_button()
|
self.chat_2.click_system_back_button_until_element_is_shown()
|
||||||
self.chat_2.save_image_icon_button.click()
|
self.chat_2.save_image_icon_button.click()
|
||||||
self.chat_2.show_images_button.click()
|
self.chat_2.show_images_button.click()
|
||||||
self.chat_2.allow_button.wait_and_click()
|
self.chat_2.allow_button.wait_and_click()
|
||||||
@@ -541,6 +588,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@marks.testrail_id(5310)
|
@marks.testrail_id(5310)
|
||||||
def test_1_1_chat_is_shown_message_sent_delivered_from_offline(self):
|
def test_1_1_chat_is_shown_message_sent_delivered_from_offline(self):
|
||||||
|
|
||||||
self.home_1.home_button.click()
|
self.home_1.home_button.click()
|
||||||
self.home_2.home_button.click()
|
self.home_2.home_button.click()
|
||||||
|
|
||||||
@@ -603,7 +651,6 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="chats_contacts_keycard_2")
|
@pytest.mark.xdist_group(name="chats_contacts_keycard_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestContactBlockMigrateKeycardMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
class TestContactBlockMigrateKeycardMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -944,7 +991,6 @@ class TestContactBlockMigrateKeycardMultipleSharedDevices(MultipleSharedDeviceTe
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="ens_stickers_mention_2")
|
@pytest.mark.xdist_group(name="ens_stickers_mention_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestEnsStickersMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
class TestEnsStickersMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -1011,6 +1057,7 @@ class TestEnsStickersMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
|||||||
send_transaction.ok_got_it_button.click()
|
send_transaction.ok_got_it_button.click()
|
||||||
send_transaction.sign_transaction()
|
send_transaction.sign_transaction()
|
||||||
chat_1_sender_message = self.chat_1.get_outgoing_transaction(transaction_value=amount)
|
chat_1_sender_message = self.chat_1.get_outgoing_transaction(transaction_value=amount)
|
||||||
|
self.home_2.put_app_to_background_and_back()
|
||||||
self.network_api.wait_for_confirmation_of_transaction(self.sender['address'], amount, confirmations=3)
|
self.network_api.wait_for_confirmation_of_transaction(self.sender['address'], amount, confirmations=3)
|
||||||
chat_1_sender_message.transaction_status.wait_for_element_text(chat_1_sender_message.confirmed)
|
chat_1_sender_message.transaction_status.wait_for_element_text(chat_1_sender_message.confirmed)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from views.chat_view import ChatView
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="group_chat_3")
|
@pytest.mark.xdist_group(name="group_chat_3")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -20,8 +19,10 @@ class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
for key in cls.drivers:
|
for key in cls.drivers:
|
||||||
sign_in = SignInView(cls.drivers[key])
|
sign_in = SignInView(cls.drivers[key])
|
||||||
cls.homes[key] = sign_in.create_user(enable_notifications=True)
|
cls.homes[key] = sign_in.create_user(enable_notifications=True)
|
||||||
|
SignInView(cls.drivers[2]).put_app_to_background_and_back()
|
||||||
cls.public_keys[key], cls.usernames[key] = sign_in.get_public_key_and_username(True)
|
cls.public_keys[key], cls.usernames[key] = sign_in.get_public_key_and_username(True)
|
||||||
sign_in.home_button.click()
|
sign_in.home_button.click()
|
||||||
|
SignInView(cls.drivers[0]).put_app_to_background_and_back()
|
||||||
cls.chat_name = cls.homes[0].get_random_chat_name()
|
cls.chat_name = cls.homes[0].get_random_chat_name()
|
||||||
|
|
||||||
cls.homes[0].just_fyi('Admin adds future members to contacts')
|
cls.homes[0].just_fyi('Admin adds future members to contacts')
|
||||||
@@ -43,6 +44,7 @@ class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
@marks.testrail_id(3994)
|
@marks.testrail_id(3994)
|
||||||
def test_group_chat_push_system_messages_when_invited(self):
|
def test_group_chat_push_system_messages_when_invited(self):
|
||||||
self.homes[1].just_fyi("Check system messages in PNs")
|
self.homes[1].just_fyi("Check system messages in PNs")
|
||||||
|
self.homes[2].put_app_to_background_and_back()
|
||||||
self.homes[1].put_app_to_background()
|
self.homes[1].put_app_to_background()
|
||||||
self.homes[1].open_notification_bar()
|
self.homes[1].open_notification_bar()
|
||||||
pns = [self.chats[0].pn_invited_to_group_chat(self.usernames[0], self.chat_name),
|
pns = [self.chats[0].pn_invited_to_group_chat(self.usernames[0], self.chat_name),
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from tests.users import basic_user, transaction_senders
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="onboarding_1")
|
@pytest.mark.xdist_group(name="onboarding_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run2
|
|
||||||
class TestOnboardingOneDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestOnboardingOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -85,8 +84,9 @@ class TestOnboardingOneDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
wallet.click_system_back_button()
|
wallet.click_system_back_button()
|
||||||
|
|
||||||
self.home.just_fyi("Check that can paste wallet address in chat message input")
|
self.home.just_fyi("Check that can paste wallet address in chat message input")
|
||||||
wallet.home_button.double_click()
|
wallet.home_button.click()
|
||||||
self.home.get_chat('#%s' % self.public_chat_name).click()
|
if not self.chat.chat_message_input.is_element_displayed():
|
||||||
|
self.home.get_chat('#%s' % self.public_chat_name).click()
|
||||||
self.chat.chat_message_input.click()
|
self.chat.chat_message_input.click()
|
||||||
self.chat.paste_text()
|
self.chat.paste_text()
|
||||||
if self.chat.chat_message_input.text != address:
|
if self.chat.chat_message_input.text != address:
|
||||||
@@ -225,7 +225,6 @@ class TestOnboardingOneDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="restore_1")
|
@pytest.mark.xdist_group(name="restore_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run2
|
|
||||||
class TestRestoreOneDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestRestoreOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ class TestPairingMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="sync_2")
|
@pytest.mark.xdist_group(name="sync_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestPairingSyncMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
class TestPairingSyncMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -114,6 +113,7 @@ class TestPairingSyncMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
|||||||
cls.profile_1.close_button.click()
|
cls.profile_1.close_button.click()
|
||||||
cls.profile_1.home_button.click()
|
cls.profile_1.home_button.click()
|
||||||
cls.profile_1.get_recovery_phrase()
|
cls.profile_1.get_recovery_phrase()
|
||||||
|
cls.device_2.put_app_to_background_and_back()
|
||||||
|
|
||||||
cls.home_1.just_fyi('Add contact, 1-1 chat (main device): 3-random, contact with ENS, start 1-1')
|
cls.home_1.just_fyi('Add contact, 1-1 chat (main device): 3-random, contact with ENS, start 1-1')
|
||||||
cls.chat_1 = cls.home_1.add_contact(cls.contact_before_sync['public_key'])
|
cls.chat_1 = cls.home_1.add_contact(cls.contact_before_sync['public_key'])
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from selenium.common.exceptions import NoSuchElementException
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="public_chat_2")
|
@pytest.mark.xdist_group(name="public_chat_2")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run2
|
|
||||||
class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -39,9 +38,10 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
self.chat_2.dapp_tab_button.click()
|
self.chat_2.dapp_tab_button.click()
|
||||||
sent_time_variants = self.chat_1.convert_device_time_to_chat_timestamp()
|
sent_time_variants = self.chat_1.convert_device_time_to_chat_timestamp()
|
||||||
timestamp = self.chat_1.chat_element_by_text(message).timestamp_on_tap
|
timestamp = self.chat_1.chat_element_by_text(message).timestamp_on_tap
|
||||||
if timestamp not in sent_time_variants:
|
if sent_time_variants and timestamp:
|
||||||
self.errors.append("Timestamp is not shown, expected: '%s', in fact: '%s'" %
|
if timestamp not in sent_time_variants:
|
||||||
(sent_time_variants.join(','), timestamp))
|
self.errors.append("Timestamp is not shown, expected: '%s', in fact: '%s'" %
|
||||||
|
(sent_time_variants.join(','), timestamp))
|
||||||
self.chat_2.home_button.click(desired_view='chat')
|
self.chat_2.home_button.click(desired_view='chat')
|
||||||
for chat in self.chat_1, self.chat_2:
|
for chat in self.chat_1, self.chat_2:
|
||||||
chat.verify_message_is_under_today_text(message, self.errors)
|
chat.verify_message_is_under_today_text(message, self.errors)
|
||||||
@@ -51,6 +51,8 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@marks.testrail_id(700734)
|
@marks.testrail_id(700734)
|
||||||
def test_public_chat_message_edit(self):
|
def test_public_chat_message_edit(self):
|
||||||
|
if not self.chat_2.chat_message_input.is_element_displayed():
|
||||||
|
self.chat_2.home_button.click(desired_view='chat')
|
||||||
message_before_edit, message_after_edit = self.text_message, "Message AFTER edit 2"
|
message_before_edit, message_after_edit = self.text_message, "Message AFTER edit 2"
|
||||||
self.chat_1.edit_message_in_chat(message_before_edit, message_after_edit)
|
self.chat_1.edit_message_in_chat(message_before_edit, message_after_edit)
|
||||||
for chat in (self.chat_1, self.chat_2):
|
for chat in (self.chat_1, self.chat_2):
|
||||||
@@ -225,7 +227,6 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="public_chat_browser_1")
|
@pytest.mark.xdist_group(name="public_chat_browser_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run2
|
|
||||||
class TestPublicChatBrowserOneDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestPublicChatBrowserOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -420,8 +421,8 @@ class TestPublicChatBrowserOneDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
self.home.just_fyi('Delete one tab')
|
self.home.just_fyi('Delete one tab')
|
||||||
web_page.remove_tab(name=urls['bbc.com'])
|
web_page.remove_tab(name=urls['bbc.com'])
|
||||||
if web_page.element_by_text_part(urls['bbc.com']).is_element_displayed():
|
web_page.open_tabs_button.wait_for_invisibility_of_element()
|
||||||
self.errors.append('Closed tab is present after deletion')
|
web_page.element_by_text_part(urls['bbc.com']).wait_for_invisibility_of_element()
|
||||||
|
|
||||||
self.home.just_fyi('Close all tabs via "Close all", relogin and check that it is not reappearing')
|
self.home.just_fyi('Close all tabs via "Close all", relogin and check that it is not reappearing')
|
||||||
web_page.close_all_button.click()
|
web_page.close_all_button.click()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from views.sign_in_view import SignInView
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="send_tx_1")
|
@pytest.mark.xdist_group(name="send_tx_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestSendTxDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestSendTxDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
@@ -267,7 +266,6 @@ class TestSendTxDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="keycard_tx_1")
|
@pytest.mark.xdist_group(name="keycard_tx_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestKeycardTxOneDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestKeycardTxOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
@@ -427,13 +425,8 @@ class TestKeycardTxOneDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
self.sign_in.maybe_later_button.click_until_presence_of_element(self.sign_in.lets_go_button)
|
self.sign_in.maybe_later_button.click_until_presence_of_element(self.sign_in.lets_go_button)
|
||||||
self.sign_in.lets_go_button.click_until_absense_of_element(self.sign_in.lets_go_button)
|
self.sign_in.lets_go_button.click_until_absense_of_element(self.sign_in.lets_go_button)
|
||||||
self.sign_in.profile_button.wait_for_visibility_of_element(30)
|
self.sign_in.profile_button.wait_for_visibility_of_element(30)
|
||||||
|
|
||||||
self.sign_in.just_fyi('Check that after creating keycard account balance is 0, not ...')
|
|
||||||
wallet_1 = self.sign_in.wallet_button.click()
|
wallet_1 = self.sign_in.wallet_button.click()
|
||||||
wallet_address = wallet_1.get_wallet_address()
|
wallet_address = wallet_1.get_wallet_address()
|
||||||
wallet_1.wallet_button.double_click()
|
|
||||||
if wallet_1.status_account_total_usd_value.text != '0':
|
|
||||||
self.errors.append("Account USD value is not 0, it is %s" % wallet_1.status_account_total_usd_value.text)
|
|
||||||
public_key, default_username = self.sign_in.get_public_key_and_username(return_username=True)
|
public_key, default_username = self.sign_in.get_public_key_and_username(return_username=True)
|
||||||
profile_1 = self.sign_in.get_profile_view()
|
profile_1 = self.sign_in.get_profile_view()
|
||||||
profile_1.logout()
|
profile_1.logout()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from support.utilities import get_merged_txs_list
|
|||||||
|
|
||||||
@pytest.mark.xdist_group(name="wallet_management_1")
|
@pytest.mark.xdist_group(name="wallet_management_1")
|
||||||
@marks.critical
|
@marks.critical
|
||||||
@pytest.mark.run1
|
|
||||||
class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -253,10 +252,9 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(700762)
|
@marks.testrail_id(700762)
|
||||||
@marks.skip
|
def test_wallet_add_account_seed_phrase_collectibles_rinkeby_set_as_profile_image(self):
|
||||||
# TODO: skipped due to #13016
|
|
||||||
def test_wallet_add_account_seed_phrase_collectibles_mainnet_rinkeby(self):
|
|
||||||
user = wallet_users['E']
|
user = wallet_users['E']
|
||||||
|
self.wallet.driver.set_network_connection(6)
|
||||||
account_seed_collectibles = self.account_seed_collectibles
|
account_seed_collectibles = self.account_seed_collectibles
|
||||||
self.wallet.get_back_to_home_view()
|
self.wallet.get_back_to_home_view()
|
||||||
if not self.wallet.add_account_button.is_element_displayed(3):
|
if not self.wallet.add_account_button.is_element_displayed(3):
|
||||||
@@ -281,34 +279,36 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
self.wallet.account_name_input.send_keys(account_seed_collectibles)
|
self.wallet.account_name_input.send_keys(account_seed_collectibles)
|
||||||
self.wallet.add_account_generate_account_button.click()
|
self.wallet.add_account_generate_account_button.click()
|
||||||
account_button = self.wallet.get_account_by_name(account_seed_collectibles)
|
account_button = self.wallet.get_account_by_name(account_seed_collectibles)
|
||||||
if not account_button.is_element_displayed():
|
|
||||||
self.wallet.accounts_status_account.swipe_left_on_element()
|
|
||||||
|
|
||||||
self.home.just_fyi('Check that collectibles are not shown on Ropsten')
|
self.home.just_fyi('Check that collectibles amount is shown on Rinkeby')
|
||||||
account_button.click()
|
|
||||||
self.wallet.collectibles_button.click()
|
|
||||||
self.wallet.element_by_translation_id("display-collectibles").scroll_and_click()
|
|
||||||
if not self.wallet.element_by_translation_id("no-collectibles").is_element_displayed():
|
|
||||||
self.errors.append("Collectibles are shown on Ropsten network!")
|
|
||||||
|
|
||||||
self.wallet.just_fyi('Check collectibles amount in wallet')
|
|
||||||
profile = self.home.profile_button.click()
|
profile = self.home.profile_button.click()
|
||||||
profile.switch_network()
|
profile.switch_network('Rinkeby with upstream RPC')
|
||||||
profile.wallet_button.click()
|
profile.wallet_button.click()
|
||||||
if not account_button.is_element_displayed():
|
if not account_button.is_element_displayed():
|
||||||
self.wallet.accounts_status_account.swipe_left_on_element()
|
self.wallet.accounts_status_account.swipe_left_on_element()
|
||||||
account_button.click()
|
account_button.click()
|
||||||
self.wallet.collectibles_button.click()
|
self.wallet.collectibles_button.click()
|
||||||
self.wallet.element_by_translation_id("display-collectibles").scroll_and_click()
|
self.wallet.element_by_translation_id("display-collectibles").scroll_and_click()
|
||||||
collectible_amount = self.wallet.get_collectibles_amount()
|
# Workaround for situation when after switching network from Ropsten collectibles are not shown
|
||||||
collectible_amount.wait_for_visibility_of_element(30)
|
self.wallet.pull_to_refresh(5)
|
||||||
if collectible_amount.text != '1':
|
if self.wallet.element_by_translation_id("no-collectibles").is_element_displayed():
|
||||||
self.errors.append('Wrong number is shown on CK assets: %s' % collectible_amount.text)
|
self.wallet.reopen_app()
|
||||||
|
profile.wallet_button.click()
|
||||||
|
if not account_button.is_element_displayed():
|
||||||
|
self.wallet.accounts_status_account.swipe_left_on_element()
|
||||||
|
account_button.click()
|
||||||
|
self.wallet.collectibles_button.click()
|
||||||
|
for asset in user['collectibles']:
|
||||||
|
self.wallet.get_collectibles_amount(asset).scroll_to_element()
|
||||||
|
if self.wallet.get_collectibles_amount(asset).text != user['collectibles'][asset]:
|
||||||
|
self.errors.append(
|
||||||
|
'%s %s is not shown in Collectibles for Rinkeby!' % (user['collectibles'][asset], asset))
|
||||||
|
|
||||||
self.wallet.just_fyi('Check that you can open collectible to view')
|
self.wallet.just_fyi('Check that you can open collectible to view')
|
||||||
collectible_amount.click()
|
nft, nft_name = 'Coins & Steel Exclusive Item Skin V2', "Warlock's Arm"
|
||||||
|
self.wallet.get_collectibles_amount(nft).click()
|
||||||
if not self.wallet.nft_asset_button.is_element_displayed(60):
|
if not self.wallet.nft_asset_button.is_element_displayed(60):
|
||||||
self.driver.fail("Kitty is not shown after opening it from collectibles!")
|
self.driver.fail("No card is not shown for %s after opening it from collectibles!" % nft)
|
||||||
self.wallet.nft_asset_button.click()
|
self.wallet.nft_asset_button.click()
|
||||||
self.wallet.set_collectible_as_profile_photo_button.scroll_and_click()
|
self.wallet.set_collectible_as_profile_photo_button.scroll_and_click()
|
||||||
|
|
||||||
@@ -317,47 +317,21 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
|||||||
self.wallet.view_collectible_on_opensea_button.click_until_presence_of_element(
|
self.wallet.view_collectible_on_opensea_button.click_until_presence_of_element(
|
||||||
web_view.browser_previous_page_button)
|
web_view.browser_previous_page_button)
|
||||||
web_view.wait_for_d_aap_to_load()
|
web_view.wait_for_d_aap_to_load()
|
||||||
if not web_view.element_by_text('Princess Gunklater').is_element_displayed(30):
|
if not web_view.element_by_text(nft_name).is_element_displayed(30):
|
||||||
self.errors.append("Collectible can't be opened when tapping 'View on OpenSea' via NFT page")
|
self.errors.append("Collectible can't be opened when tapping 'View on OpenSea' via NFT page")
|
||||||
self.wallet.wallet_button.click()
|
self.wallet.wallet_button.click()
|
||||||
|
|
||||||
self.wallet.just_fyi('Check that collectibles are not shown when sending assets from wallet')
|
self.wallet.just_fyi('Check that collectibles are not shown when sending assets from wallet')
|
||||||
send_transaction = self.wallet.send_transaction_button.click()
|
send_transaction = self.wallet.send_transaction_button.click()
|
||||||
send_transaction.select_asset_button.click()
|
send_transaction.select_asset_button.click()
|
||||||
if send_transaction.asset_by_name("CryptoKitties").is_element_displayed():
|
if send_transaction.asset_by_name(nft).is_element_displayed():
|
||||||
self.errors.append('Collectibles can be sent from wallet')
|
self.errors.append('Collectibles can be sent from wallet')
|
||||||
self.wallet.close_send_transaction_view_button.double_click()
|
self.wallet.close_send_transaction_view_button.double_click()
|
||||||
|
|
||||||
self.wallet.just_fyi('Check "Open in OpenSea" (that user is signed in)')
|
|
||||||
self.wallet.element_by_translation_id("check-on-opensea").click_until_presence_of_element(
|
|
||||||
web_view.browser_previous_page_button)
|
|
||||||
web_view.wait_for_d_aap_to_load(10)
|
|
||||||
self.wallet.element_by_text('e2ecryptokitty').wait_for_element(60)
|
|
||||||
|
|
||||||
self.wallet.just_fyi("Check that custom image from collectible is set as profile photo")
|
self.wallet.just_fyi("Check that custom image from collectible is set as profile photo")
|
||||||
self.wallet.profile_button.double_click()
|
self.wallet.profile_button.double_click()
|
||||||
if not profile.profile_picture.is_element_image_similar_to_template('collectible_pic.png'):
|
if not profile.profile_picture.is_element_image_similar_to_template('collectible_pic.png'):
|
||||||
self.errors.append("Collectible image is not set as profile image")
|
self.errors.append("Collectible image is not set as profile image")
|
||||||
|
|
||||||
self.home.just_fyi('Check that collectibles amount is shown on Rinkeby')
|
|
||||||
profile = self.home.profile_button.click()
|
|
||||||
profile.switch_network('Rinkeby with upstream RPC')
|
|
||||||
profile = self.home.profile_button.click()
|
|
||||||
profile.wallet_button.click()
|
|
||||||
if not account_button.is_element_displayed():
|
|
||||||
self.wallet.accounts_status_account.swipe_left_on_element()
|
|
||||||
self.wallet.scan_tokens()
|
|
||||||
account_button.click()
|
|
||||||
self.wallet.transaction_history_button.click()
|
|
||||||
self.wallet.collectibles_button.click()
|
|
||||||
self.wallet.swipe_up()
|
|
||||||
if self.wallet.element_by_translation_id("display-collectibles").is_element_displayed:
|
|
||||||
self.wallet.element_by_translation_id("display-collectibles").click()
|
|
||||||
for asset in user['collectibles']:
|
|
||||||
self.wallet.get_collectibles_amount(asset).scroll_to_element()
|
|
||||||
if self.wallet.get_collectibles_amount(asset).text != user['collectibles'][asset]:
|
|
||||||
self.errors.append(
|
|
||||||
'%s %s is not shown in Collectibles for Rinkeby!' % (user['collectibles'][asset], asset))
|
|
||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(700766)
|
@marks.testrail_id(700766)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import random
|
import random
|
||||||
|
import time
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import emoji
|
import emoji
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tests import marks
|
from tests import marks
|
||||||
|
from tests.users import ens_user
|
||||||
from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase
|
from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase
|
||||||
from views.sign_in_view import SignInView
|
from views.sign_in_view import SignInView
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ class TestPublicChatMultipleDeviceMergedMedium(MultipleSharedDeviceTestCase):
|
|||||||
chat_2.add_to_contacts.click()
|
chat_2.add_to_contacts.click()
|
||||||
timeline_2 = chat_2.status_button.click()
|
timeline_2 = chat_2.status_button.click()
|
||||||
for status in statuses:
|
for status in statuses:
|
||||||
|
chat_2.element_by_text_part(statuses['*formatted text*']).scroll_to_element()
|
||||||
expected_value = statuses[status]
|
expected_value = statuses[status]
|
||||||
if not timeline_2.element_by_text_part(expected_value).is_element_displayed():
|
if not timeline_2.element_by_text_part(expected_value).is_element_displayed():
|
||||||
self.errors.append(
|
self.errors.append(
|
||||||
@@ -94,8 +97,7 @@ class TestPublicChatMultipleDeviceMergedMedium(MultipleSharedDeviceTestCase):
|
|||||||
tag_status = '#public-chat-to-redirect-long-name'
|
tag_status = '#public-chat-to-redirect-long-name'
|
||||||
timeline_1.set_new_status(tag_status)
|
timeline_1.set_new_status(tag_status)
|
||||||
public_chat_2 = self.home_2.get_chat_view()
|
public_chat_2 = self.home_2.get_chat_view()
|
||||||
|
public_chat_2.element_by_text(tag_status).scroll_and_click('up')
|
||||||
public_chat_2.element_by_text(tag_status).wait_and_click()
|
|
||||||
public_chat_2.user_name_text.wait_for_element(30)
|
public_chat_2.user_name_text.wait_for_element(30)
|
||||||
if not public_chat_2.user_name_text.text == tag_status:
|
if not public_chat_2.user_name_text.text == tag_status:
|
||||||
self.errors.append('Could not redirect a user to a public chat tapping the tag message from timeline_1')
|
self.errors.append('Could not redirect a user to a public chat tapping the tag message from timeline_1')
|
||||||
@@ -173,9 +175,76 @@ class TestChatMultipleDevice(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
cls.message_1, cls.message_2, cls.message_3, cls.message_4 = "Message1", "Message2", "Message3", "Message4"
|
cls.message_1, cls.message_2, cls.message_3, cls.message_4 = "Message1", "Message2", "Message3", "Message4"
|
||||||
|
|
||||||
|
@marks.testrail_id(702268)
|
||||||
|
def test_chat_gap_in_public_and_no_gap_in_1_1_and_group(self):
|
||||||
|
self.home_2.get_back_to_home_view()
|
||||||
|
message_1 = "testing gap"
|
||||||
|
message_2 = "testing no gap"
|
||||||
|
profile_1 = self.home_1.profile_button.click()
|
||||||
|
profile_1.sync_settings_button.click()
|
||||||
|
profile_1.sync_history_for_button.click()
|
||||||
|
profile_1.element_by_translation_id("two-minutes").click()
|
||||||
|
[home.home_button.click() for home in (self.home_1, self.home_2)]
|
||||||
|
|
||||||
|
self.home_1.just_fyi("Creating 1-1 chat and sending message from device 1")
|
||||||
|
self.chat_1.send_message("HI")
|
||||||
|
self.home_1.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.home_1.just_fyi("Creating group chat and sending message from device 1")
|
||||||
|
group_chat_1 = self.home_1.get_chat(self.initial_group_chat_name).click()
|
||||||
|
group_chat_1.send_message("HI")
|
||||||
|
self.home_1.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.home_1.just_fyi("Creating public chat and sending message from device 1")
|
||||||
|
pub_chat_1 = self.home_1.get_chat('#' + self.public_chat_name).click()
|
||||||
|
pub_chat_1.send_message("HI")
|
||||||
|
self.device_1.toggle_airplane_mode()
|
||||||
|
|
||||||
|
self.home_2.just_fyi("Joining public chat by device 2 and sending message")
|
||||||
|
pub_chat_2 = self.home_2.get_chat('#' + self.public_chat_name).click()
|
||||||
|
pub_chat_2.send_message(message_1)
|
||||||
|
self.home_2.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.home_2.just_fyi("Joining 1-1 chat by device 2 and sending message")
|
||||||
|
one_to_one_chat_2 = self.home_2.get_chat(self.default_username_1).click()
|
||||||
|
one_to_one_chat_2.send_message(message_2)
|
||||||
|
self.home_2.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.home_2.just_fyi("Joining Group chat by device 2 and sending message")
|
||||||
|
group_chat_2 = self.home_2.get_chat(self.initial_group_chat_name).click()
|
||||||
|
group_chat_2.send_message(message_2)
|
||||||
|
group_chat_2.get_back_to_home_view()
|
||||||
|
|
||||||
|
# Waiting for 3 minutes and then going back online
|
||||||
|
time.sleep(180)
|
||||||
|
self.device_1.toggle_airplane_mode()
|
||||||
|
|
||||||
|
self.home_1.just_fyi("Checking gap in public chat and fetching messages")
|
||||||
|
if pub_chat_1.chat_element_by_text(message_1).is_element_displayed(10):
|
||||||
|
self.errors.append("Test message has been fetched automatically")
|
||||||
|
pub_chat_1.element_by_translation_id("fetch-messages").wait_and_click(60)
|
||||||
|
if not pub_chat_1.chat_element_by_text(message_1).is_element_displayed(10):
|
||||||
|
self.errors.append("Test message has not been fetched")
|
||||||
|
self.home_1.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.home_1.just_fyi("Checking that there is no gap in 1-1/group chat and messages fetched automatically")
|
||||||
|
for chat in [self.home_1.get_chat(self.default_username_2), self.home_1.get_chat(self.initial_group_chat_name)]:
|
||||||
|
chat_view = chat.click()
|
||||||
|
if chat_view.element_by_translation_id("fetch-messages").is_element_displayed(10):
|
||||||
|
self.errors.append("Fetch messages button is displayed in {}} chat".format(chat.user_name_text.text))
|
||||||
|
if not chat_view.chat_element_by_text(message_2).is_element_displayed(10):
|
||||||
|
self.errors.append(
|
||||||
|
"Message in {} chat has not been fetched automatically".format(chat.user_name_text.text))
|
||||||
|
chat_view.back_button.click()
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(702066)
|
@marks.testrail_id(702066)
|
||||||
def test_chat_1_1_push_and_reaction_for_messages_sticker_audio_image(self):
|
def test_chat_1_1_push_and_reaction_for_messages_sticker_audio_image(self):
|
||||||
|
|
||||||
|
self.home_1.get_chat(self.default_username_2).click()
|
||||||
|
self.home_2.get_chat(self.default_username_1).click()
|
||||||
|
|
||||||
|
|
||||||
# methods with steps to use later in loop
|
# methods with steps to use later in loop
|
||||||
def navigate_to_start_state_of_both_devices():
|
def navigate_to_start_state_of_both_devices():
|
||||||
self.chat_1.put_app_to_background()
|
self.chat_1.put_app_to_background()
|
||||||
@@ -433,4 +502,244 @@ class TestChatMultipleDevice(MultipleSharedDeviceTestCase):
|
|||||||
self.group_chat_2.chat_element_by_text(self.message_1).pinned_by_label.is_element_present()):
|
self.group_chat_2.chat_element_by_text(self.message_1).pinned_by_label.is_element_present()):
|
||||||
self.errors.append("Message failed be unpinned by user who granted admin permissions!")
|
self.errors.append("Message failed be unpinned by user who granted admin permissions!")
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702258)
|
||||||
|
def test_chat_group_chat_set_nickname_and_ens_via_group_info_mention(self):
|
||||||
|
self.drivers[1].reset()
|
||||||
|
|
||||||
|
self.home_2 = SignInView(self.drivers[1]).recover_access(ens_user['passphrase'])
|
||||||
|
self.home_1.home_button.double_click()
|
||||||
|
self.profile_2 = self.home_2.profile_button.click()
|
||||||
|
ens, full_ens, username_2 = ens_user['ens'], '@%s' % ens_user['ens'], ens_user['username']
|
||||||
|
self.profile_2.connect_existing_ens(ens)
|
||||||
|
[home.home_button.click() for home in (self.home_1, self.home_2)]
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Set nickname, using emojis, special chars and cyrrilic chars without adding to contact')
|
||||||
|
emoji_message = random.choice(list(emoji.EMOJI_UNICODE))
|
||||||
|
emoji_unicode = emoji.EMOJI_UNICODE[emoji_message]
|
||||||
|
special_char, cyrrilic = '"£¢€¥~`•|√π¶∆×°™®©%$@', 'стат'
|
||||||
|
nickname_to_set = emoji.emojize(emoji_message) + special_char + cyrrilic
|
||||||
|
nickname_expected = emoji_unicode + special_char + cyrrilic
|
||||||
|
chat_1 = self.home_1.add_contact(ens, add_in_contacts=False, nickname=nickname_to_set)
|
||||||
|
if chat_1.user_name_text.text != nickname_expected:
|
||||||
|
self.errors.append('Expected special char nickname %s does not match actual %s' % (nickname_expected, chat_1.user_name_text.text))
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Can remove nickname without adding to contact')
|
||||||
|
chat_1.chat_options.click()
|
||||||
|
chat_1.view_profile_button.click()
|
||||||
|
chat_1.profile_nickname_button.click()
|
||||||
|
chat_1.nickname_input_field.clear()
|
||||||
|
chat_1.element_by_text('Done').click()
|
||||||
|
chat_1.close_button.click()
|
||||||
|
if chat_1.user_name_text.text != full_ens:
|
||||||
|
self.errors.append(
|
||||||
|
'Nickname was not removed! real chat name is %s instead of %s' % (chat_1.user_name_text.text, full_ens))
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Adding ENS user to contacts and start group chat with him')
|
||||||
|
group_name = 'ens_group'
|
||||||
|
chat_1.add_to_contacts.click()
|
||||||
|
chat_2 = self.home_2.add_contact(self.public_key_1)
|
||||||
|
chat_2.send_message("first")
|
||||||
|
chat_2.home_button.click()
|
||||||
|
chat_1.home_button.click()
|
||||||
|
chat_1 = self.home_1.create_group_chat([full_ens], group_name)
|
||||||
|
chat_2 = self.home_2.get_chat(group_name).click()
|
||||||
|
chat_2.join_chat_button.click()
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Check ENS and in group chat and suggestions list')
|
||||||
|
chat_1.element_by_text_part(full_ens).wait_for_visibility_of_element(60)
|
||||||
|
chat_1.select_mention_from_suggestion_list(ens, typed_search_pattern=ens[:2])
|
||||||
|
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
||||||
|
self.errors.append(
|
||||||
|
'ENS username is not resolved in chat input after selecting it in mention suggestions list!')
|
||||||
|
additional_text = 'and more'
|
||||||
|
chat_1.send_as_keyevent(additional_text)
|
||||||
|
chat_1.send_message_button.click()
|
||||||
|
message_text = '%s %s' % (full_ens, additional_text)
|
||||||
|
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
||||||
|
self.errors.append("ENS name is not resolved on sent message")
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Set nickname via group info and check that can mention by nickname /username in group chat')
|
||||||
|
nickname = 'funny_bunny'
|
||||||
|
device_2_options = chat_1.get_user_options(full_ens)
|
||||||
|
device_2_options.view_profile_button.click()
|
||||||
|
chat_1.set_nickname(nickname, close_profile=False)
|
||||||
|
if not chat_1.element_by_text(nickname).is_element_displayed():
|
||||||
|
self.errors.append('Nickname is not shown in profile view after setting from group info')
|
||||||
|
chat_1.close_button.click()
|
||||||
|
chat_1.element_by_text(nickname).scroll_to_element()
|
||||||
|
chat_1.close_button.click()
|
||||||
|
message_text = '%s %s' % (nickname, additional_text)
|
||||||
|
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
||||||
|
self.errors.append("ENS name was not replaced with nickname on sent message")
|
||||||
|
chat_1.chat_message_input.send_keys('@')
|
||||||
|
if not chat_1.element_by_text('%s %s' % (nickname, full_ens)).is_element_displayed():
|
||||||
|
self.errors.append("ENS name with nickname is not shown in mention input after set")
|
||||||
|
if not chat_1.element_by_text(username_2).is_element_displayed():
|
||||||
|
self.errors.append("3-random name is not shown in mention input after set from group info")
|
||||||
|
chat_1.chat_message_input.clear()
|
||||||
|
chat_1.select_mention_from_suggestion_list('%s %s' % (nickname, full_ens), typed_search_pattern=username_2[:2])
|
||||||
|
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
||||||
|
self.errors.append(
|
||||||
|
'ENS is not resolved in chat input after setting nickname in mention suggestions list (search by 3-random name)!')
|
||||||
|
chat_1.chat_message_input.clear()
|
||||||
|
chat_1.select_mention_from_suggestion_list('%s %s' % (nickname, full_ens), typed_search_pattern=nickname[:2])
|
||||||
|
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
||||||
|
self.errors.append(
|
||||||
|
'ENS is not resolved in chat input after setting nickname in mention suggestions list (search by nickname)!')
|
||||||
|
chat_1.chat_message_input.clear()
|
||||||
|
|
||||||
|
self.home_1.just_fyi('Can delete nickname via group info and recheck received messages')
|
||||||
|
device_2_options = chat_1.get_user_options(full_ens)
|
||||||
|
device_2_options.view_profile_button.click()
|
||||||
|
chat_1.profile_nickname_button.click()
|
||||||
|
chat_1.nickname_input_field.clear()
|
||||||
|
chat_1.element_by_text('Done').click()
|
||||||
|
chat_1.close_button.click()
|
||||||
|
chat_1.close_button.click()
|
||||||
|
message_text = '%s %s' % (full_ens, additional_text)
|
||||||
|
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
||||||
|
self.errors.append("ENS name is not resolved on sent message after removing nickname")
|
||||||
|
chat_1.chat_message_input.send_keys('@')
|
||||||
|
if chat_1.element_by_text_part(nickname).is_element_displayed():
|
||||||
|
self.errors.append("Nickname is shown in group chat after removing!")
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.xdist_group(name="group_chat_medium_3")
|
||||||
|
@marks.medium
|
||||||
|
class TestGroupChatMultipleDevice(MultipleSharedDeviceTestCase):
|
||||||
|
@classmethod
|
||||||
|
def setup_class(cls):
|
||||||
|
cls.drivers, cls.loop = create_shared_drivers(3)
|
||||||
|
cls.sign_ins, cls.homes, cls.public_keys, cls.usernames, cls.chats = {}, {}, {}, {}, {}
|
||||||
|
for key in cls.drivers:
|
||||||
|
cls.sign_ins[key] = SignInView(cls.drivers[key])
|
||||||
|
cls.homes[key] = cls.sign_ins[key].create_user()
|
||||||
|
SignInView(cls.drivers[2]).put_app_to_background_and_back()
|
||||||
|
cls.public_keys[key], cls.usernames[key] = cls.sign_ins[key].get_public_key_and_username(True)
|
||||||
|
cls.sign_ins[key].home_button.click()
|
||||||
|
SignInView(cls.drivers[0]).put_app_to_background_and_back()
|
||||||
|
|
||||||
|
for member in (cls.public_keys[1], cls.public_keys[2]):
|
||||||
|
cls.homes[0].add_contact(member)
|
||||||
|
cls.homes[0].home_button.click()
|
||||||
|
cls.chat_name = cls.homes[0].get_random_chat_name()
|
||||||
|
cls.invite_chat_name = '%s_invite' % cls.homes[0].get_random_chat_name()
|
||||||
|
cls.chats[0] = cls.homes[0].create_group_chat([], cls.invite_chat_name)
|
||||||
|
[SignInView(cls.drivers[i]).put_app_to_background_and_back() for i in range(1, 3)]
|
||||||
|
cls.link = cls.chats[0].get_group_invite_via_group_info()
|
||||||
|
cls.chats[0].home_button.double_click()
|
||||||
|
|
||||||
|
cls.chats[0] = cls.homes[0].create_group_chat([cls.usernames[1], cls.usernames[2]], cls.chat_name)
|
||||||
|
for i in range(1, 3):
|
||||||
|
cls.chats[i] = cls.homes[i].get_chat(cls.chat_name).click()
|
||||||
|
cls.chats[i].join_chat_button.click()
|
||||||
|
|
||||||
|
@marks.testrail_id(702259)
|
||||||
|
def test_group_chat_remove_member(self):
|
||||||
|
self.chats[0].just_fyi("Admin: get options for device 2 in group chat and remove him")
|
||||||
|
removed_user = self.usernames[2]
|
||||||
|
options = self.chats[0].get_user_options(removed_user)
|
||||||
|
options.remove_user_button.click()
|
||||||
|
left_message = self.chats[0].leave_system_message(removed_user)
|
||||||
|
for key in self.chats:
|
||||||
|
if not self.chats[key].chat_element_by_text(left_message).is_element_displayed():
|
||||||
|
self.errors.append("Message with text '%s' was not received" % left_message)
|
||||||
|
|
||||||
|
self.chats[0].just_fyi("Check that input field is not available after removing")
|
||||||
|
if self.chats[2].chat_message_input.is_element_displayed():
|
||||||
|
self.errors.append("Message input is still available for removed user")
|
||||||
|
self.chats[0].just_fyi("Send message and check that it is available only for remaining users")
|
||||||
|
message = 'after removing member'
|
||||||
|
self.chats[0].send_message(message)
|
||||||
|
for chat in (self.chats[0], self.chats[1]):
|
||||||
|
if not chat.chat_element_by_text(message).is_element_displayed(30):
|
||||||
|
self.errors.append("Message '%s' was not received after removing member" % message)
|
||||||
|
if self.chats[2].chat_element_by_text(message).is_element_displayed():
|
||||||
|
self.errors.append("Message '%s' was received by removed member" % message)
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702260)
|
||||||
|
def test_group_chat_make_admin(self):
|
||||||
|
self.homes[0].just_fyi('Check group info view and options of users')
|
||||||
|
self.chats[0].chat_options.click()
|
||||||
|
group_info_1 = self.chats[0].group_info.click()
|
||||||
|
if not group_info_1.user_admin(self.usernames[0]).is_element_displayed():
|
||||||
|
self.errors.append("Admin user is not marked as admin")
|
||||||
|
group_info_1.get_user_from_group_info(self.usernames[0]).click()
|
||||||
|
if self.chats[0].profile_block_contact.is_element_displayed():
|
||||||
|
self.errors.append("Admin is redirected to own profile on tapping own username from group info")
|
||||||
|
|
||||||
|
self.chats[0].just_fyi('Made admin another user and check system message')
|
||||||
|
options = group_info_1.get_username_options(self.usernames[1]).click()
|
||||||
|
options.make_admin_button.click()
|
||||||
|
admin_system_message = self.chats[0].has_been_made_admin_system_message(self.usernames[0], self.usernames[1])
|
||||||
|
for chat in (self.chats[0], self.chats[1]):
|
||||||
|
if not chat.chat_element_by_text(admin_system_message).is_element_displayed():
|
||||||
|
self.errors.append("Message with test '%s' was not received" % admin_system_message)
|
||||||
|
|
||||||
|
self.chats[1].just_fyi('Check Admin in group info and that "add members" is available')
|
||||||
|
self.chats[1].chat_options.click()
|
||||||
|
group_info_1 = self.chats[1].group_info.click()
|
||||||
|
for username in (self.usernames[0], self.usernames[1]):
|
||||||
|
if not group_info_1.user_admin(username).is_element_displayed():
|
||||||
|
self.errors.append("Admin user is not marked as admin")
|
||||||
|
if not group_info_1.add_members.is_element_displayed():
|
||||||
|
self.errors.append("Add member button is not available for new admin")
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702261)
|
||||||
|
def test_group_chat_accept_decline_invite(self):
|
||||||
|
[driver.close_app() for driver in (self.drivers[1], self.drivers[2])]
|
||||||
|
self.homes[0].home_button.double_click()
|
||||||
|
self.chats[0].just_fyi('Member_1, member_2: both users send requests to join group chat')
|
||||||
|
[sign_in.open_weblink_and_login(self.link) for sign_in in (self.sign_ins[1], self.sign_ins[2])]
|
||||||
|
introduction_messages = ['message for retrying']
|
||||||
|
for i in range(1, 3):
|
||||||
|
self.homes[i].element_by_text_part(self.invite_chat_name).click()
|
||||||
|
introduction_messages.append('Please add me, member_%s to your gorgeous group chat' % str(i))
|
||||||
|
self.chats[i].request_membership_for_group_chat(introduction_messages[i])
|
||||||
|
|
||||||
|
self.chats[0].just_fyi('Admin: accept request for Member_1 and decline for Member_2')
|
||||||
|
self.homes[0].get_chat(self.invite_chat_name).click()
|
||||||
|
self.chats[0].group_membership_request_button.wait_and_click()
|
||||||
|
self.chats[0].element_by_text(self.usernames[1]).click()
|
||||||
|
if not self.chats[0].element_by_text_part(introduction_messages[1]).is_element_displayed():
|
||||||
|
self.errors.append('Introduction message is not shown!')
|
||||||
|
self.chats[0].accept_group_invitation_button.wait_and_click()
|
||||||
|
self.chats[0].accept_membership_for_group_chat_via_chat_view(self.usernames[2], accept=False)
|
||||||
|
self.chats[0].click_system_back_button()
|
||||||
|
|
||||||
|
self.chats[2].just_fyi('Member_2: retry request')
|
||||||
|
self.chats[2].retry_group_invite_button.wait_and_click()
|
||||||
|
self.chats[2].request_membership_for_group_chat(introduction_messages[0])
|
||||||
|
|
||||||
|
self.chats[2].just_fyi('Admin: decline request for Member_2')
|
||||||
|
self.chats[0].group_membership_request_button.wait_and_click()
|
||||||
|
self.chats[0].element_by_text(self.usernames[2]).click()
|
||||||
|
if not self.chats[0].element_by_text_part(introduction_messages[0]).is_element_displayed():
|
||||||
|
self.errors.append('Introduction message that was set after retrying attempt is not shown for admin!')
|
||||||
|
self.chats[0].decline_group_invitation_button.wait_and_click()
|
||||||
|
self.chats[0].click_system_back_button()
|
||||||
|
|
||||||
|
self.chats[2].just_fyi('Member_2: remove chat')
|
||||||
|
self.chats[2].remove_group_invite_button.wait_and_click()
|
||||||
|
|
||||||
|
self.chats[2].just_fyi('Double check after relogin')
|
||||||
|
if self.chats[0].group_membership_request_button.is_element_displayed():
|
||||||
|
self.errors.append('Group membership request is still shown when there are no pending requests anymore')
|
||||||
|
[self.homes[i].reopen_app() for i in range(0, 3)]
|
||||||
|
if self.homes[2].element_by_text_part(self.invite_chat_name).is_element_displayed():
|
||||||
|
self.errors.append('Group chat was not removed when removing after declining group invite')
|
||||||
|
[home.get_chat(self.invite_chat_name).click() for home in (self.homes[0], self.homes[1])]
|
||||||
|
if self.chats[0].group_membership_request_button.is_element_displayed():
|
||||||
|
self.errors.append(
|
||||||
|
'Group membership request is shown after relogin when there are no pending requests anymore')
|
||||||
|
join_system_message = self.chats[0].join_system_message(self.usernames[1])
|
||||||
|
for chat in (self.chats[1], self.chats[0]):
|
||||||
|
if not chat.chat_element_by_text(join_system_message).is_element_displayed():
|
||||||
|
self.errors.append('%s is not shown after joining to group chat via invite' % join_system_message)
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ class TestBrowserProfileOneDevice(MultipleSharedDeviceTestCase):
|
|||||||
|
|
||||||
@marks.testrail_id(702159)
|
@marks.testrail_id(702159)
|
||||||
def test_profile_invite_friends(self):
|
def test_profile_invite_friends(self):
|
||||||
self.home.home_button.click()
|
self.home.home_button.double_click()
|
||||||
|
|
||||||
self.home.just_fyi("Check it via 'Invite friends' on home view")
|
self.home.just_fyi("Check it via 'Invite friends' on home view")
|
||||||
self.home.invite_friends_button.click()
|
self.home.invite_friends_button.click()
|
||||||
|
|||||||
@@ -0,0 +1,346 @@
|
|||||||
|
import re
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from tests import marks, mailserver_ams, mailserver_gc, mailserver_hk, used_fleet, common_password, test_dapp_name,\
|
||||||
|
test_dapp_url, pair_code, unique_password
|
||||||
|
from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase
|
||||||
|
from tests.users import user_mainnet, chat_users, dummy_user, recovery_users, transaction_senders, basic_user,\
|
||||||
|
wallet_users, ens_user_ropsten, ens_user
|
||||||
|
from selenium.common.exceptions import NoSuchElementException
|
||||||
|
|
||||||
|
from tests.base_test_case import SingleDeviceTestCase, MultipleDeviceTestCase
|
||||||
|
from views.send_transaction_view import SendTransactionView
|
||||||
|
from views.chat_view import ChatView
|
||||||
|
from views.sign_in_view import SignInView
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.xdist_group(name="deeplink_chat_profile_medium_1")
|
||||||
|
@marks.medium
|
||||||
|
class TestDeeplinkChatProfileOneDevice(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setup_class(cls):
|
||||||
|
cls.drivers, cls.loop = create_shared_drivers(1)
|
||||||
|
cls.sign_in = SignInView(cls.drivers[0])
|
||||||
|
cls.home = cls.sign_in.create_user()
|
||||||
|
cls.public_key, cls.default_username = cls.home.get_public_key_and_username(return_username=True)
|
||||||
|
cls.home.home_button.click()
|
||||||
|
cls.public_chat_name = 'pubchat'
|
||||||
|
cls.nickname = 'dummy_user'
|
||||||
|
cls.search_list_1 = {
|
||||||
|
basic_user['username']: basic_user['username'],
|
||||||
|
ens_user_ropsten['username']: ens_user_ropsten['ens'],
|
||||||
|
cls.public_chat_name: cls.public_chat_name,
|
||||||
|
cls.nickname: cls.nickname,
|
||||||
|
dummy_user['username']: cls.nickname,
|
||||||
|
ens_user_ropsten['ens']: ens_user_ropsten['ens']
|
||||||
|
}
|
||||||
|
cls.public_chat = cls.home.join_public_chat(cls.public_chat_name)
|
||||||
|
cls.public_chat.get_back_to_home_view()
|
||||||
|
|
||||||
|
@marks.testrail_id(702244)
|
||||||
|
def test_deep_link_with_invalid_user_public_key_own_profile_key(self):
|
||||||
|
self.drivers[0].close_app()
|
||||||
|
|
||||||
|
self.sign_in.just_fyi('Check that no error when opening invalid deep link')
|
||||||
|
deep_link = 'status-im://u/%s' % self.public_key[:-10]
|
||||||
|
self.sign_in.open_weblink_and_login(deep_link)
|
||||||
|
self.home = self.sign_in.get_home_view()
|
||||||
|
self.home.plus_button.click_until_presence_of_element(self.home.start_new_chat_button)
|
||||||
|
if not self.home.start_new_chat_button.is_element_present():
|
||||||
|
self.errors.append(
|
||||||
|
"Can't navigate to start new chat after app opened from deep link with invalid public key")
|
||||||
|
self.drivers[0].close_app()
|
||||||
|
|
||||||
|
self.sign_in.just_fyi('Check that no error when opening own valid deep link')
|
||||||
|
deep_link = 'status-im://u/%s' % self.public_key
|
||||||
|
self.sign_in.open_weblink_and_login(deep_link)
|
||||||
|
from views.profile_view import ProfileView
|
||||||
|
profile = ProfileView(self.drivers)
|
||||||
|
if not profile.default_username_text != self.default_username:
|
||||||
|
self.errors.append("Can't navigate to profile from deep link with own public key")
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702245)
|
||||||
|
def test_deep_link_open_user_profile(self):
|
||||||
|
for user_ident in ens_user['ens'], ens_user['ens_another'], ens_user['public_key']:
|
||||||
|
self.drivers[0].close_app()
|
||||||
|
deep_link = 'status-im://u/%s' % user_ident
|
||||||
|
self.sign_in.open_weblink_and_login(deep_link)
|
||||||
|
chat = self.sign_in.get_chat_view()
|
||||||
|
for text in ens_user['username'], self.sign_in.get_translation_by_key("add-to-contacts"):
|
||||||
|
if not chat.element_by_text(text).scroll_to_element(10):
|
||||||
|
self.driver.fail("User profile screen is not opened")
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702246)
|
||||||
|
def test_deep_link_open_dapp(self):
|
||||||
|
self.drivers[0].close_app()
|
||||||
|
dapp_name = test_dapp_url
|
||||||
|
dapp_deep_link = 'status-im://b/%s' % dapp_name
|
||||||
|
self.sign_in.open_weblink_and_login(dapp_deep_link)
|
||||||
|
web_view = self.sign_in.get_chat_view()
|
||||||
|
try:
|
||||||
|
test_dapp_view = web_view.open_in_status_button.click()
|
||||||
|
test_dapp_view.allow_button.is_element_present()
|
||||||
|
except NoSuchElementException:
|
||||||
|
self.drivers[0].fail("DApp '%s' is not opened!" % dapp_name)
|
||||||
|
self.home.reopen_app()
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702247)
|
||||||
|
def test_share_user_profile_url_one_to_one_chat(self):
|
||||||
|
self.home.home_button.click()
|
||||||
|
|
||||||
|
self.home.just_fyi('Join to one-to-one chat and share link to other user profile via messenger')
|
||||||
|
chat = self.home.add_contact(dummy_user["public_key"])
|
||||||
|
chat.chat_options.click()
|
||||||
|
chat.view_profile_button.click_until_presence_of_element(chat.remove_from_contacts)
|
||||||
|
chat.profile_details.click()
|
||||||
|
chat.share_button.click()
|
||||||
|
chat.share_via_messenger()
|
||||||
|
if not chat.element_by_text_part(
|
||||||
|
'https://join.status.im/u/%s' % dummy_user["public_key"]).is_element_present():
|
||||||
|
self.errors.append("Can't share public key of contact")
|
||||||
|
for _ in range(2):
|
||||||
|
chat.click_system_back_button()
|
||||||
|
|
||||||
|
@marks.testrail_id(702252)
|
||||||
|
def test_share_user_profile_url_public_chat(self):
|
||||||
|
|
||||||
|
self.home.just_fyi('Join to public chat and share link to it via messenger')
|
||||||
|
self.home.home_button.click()
|
||||||
|
|
||||||
|
self.home.get_chat('#' + self.public_chat_name).click()
|
||||||
|
self.public_chat.chat_options.click()
|
||||||
|
self.public_chat.share_chat_button.click()
|
||||||
|
self.public_chat.share_via_messenger()
|
||||||
|
if not self.public_chat.element_by_text_part('https://join.status.im/%s' % self.public_chat_name).is_element_present():
|
||||||
|
self.errors.append("Can't share link to public chat")
|
||||||
|
for _ in range(2):
|
||||||
|
self.public_chat.click_system_back_button()
|
||||||
|
self.public_chat.get_back_to_home_view()
|
||||||
|
|
||||||
|
@marks.testrail_id(702251)
|
||||||
|
def test_share_user_profile_url_browser(self):
|
||||||
|
|
||||||
|
self.home.just_fyi('Open URL and share link to it via messenger')
|
||||||
|
daap = self.home.dapp_tab_button.click()
|
||||||
|
browser = daap.open_url('dap.ps')
|
||||||
|
browser.options_button.click()
|
||||||
|
browser.share_url_button.click()
|
||||||
|
browser.share_via_messenger()
|
||||||
|
expeceted_text_1 = 'https://join.status.im/b/https://dap.ps'
|
||||||
|
expeceted_text_2 = 'https://join.status.im/b/http://dap.ps'
|
||||||
|
|
||||||
|
if not (browser.element_by_text_part(expeceted_text_1).is_element_present() or
|
||||||
|
browser.element_by_text_part(expeceted_text_2).is_element_present()):
|
||||||
|
self.errors.append("Can't share link to URL")
|
||||||
|
|
||||||
|
browser.click_system_back_button(1)
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702248)
|
||||||
|
def test_chat_can_start_and_find_from_suggestions_using_search(self):
|
||||||
|
|
||||||
|
self.home.home_button.click()
|
||||||
|
self.home.just_fyi('Start 1-1 with username and with ENS')
|
||||||
|
|
||||||
|
for public_key in (basic_user['public_key'], dummy_user['public_key']):
|
||||||
|
chat = self.home.add_contact(public_key)
|
||||||
|
chat.get_back_to_home_view()
|
||||||
|
profile = self.home.profile_button.click()
|
||||||
|
profile.open_contact_from_profile(dummy_user['username'])
|
||||||
|
self.public_chat.set_nickname(self.nickname)
|
||||||
|
self.public_chat.home_button.click()
|
||||||
|
|
||||||
|
ens_name_status, ens_name_another_domain, public_chat_name = ens_user_ropsten['ens'], \
|
||||||
|
ens_user['ens_another'], 'some-pub-chat'
|
||||||
|
search_list_2 = {
|
||||||
|
ens_name_status: {
|
||||||
|
'home': {
|
||||||
|
'Start a new private chat',
|
||||||
|
'Join a public chat',
|
||||||
|
'%s.stateofus.eth' % ens_name_status,
|
||||||
|
'#%s' % ens_name_status
|
||||||
|
},
|
||||||
|
'navigate_to': '%s.stateofus.eth' % ens_name_status,
|
||||||
|
'chat': {
|
||||||
|
chat.add_to_contacts,
|
||||||
|
chat.element_by_text('@%s' % ens_name_status),
|
||||||
|
chat.chat_message_input
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ens_name_another_domain: {
|
||||||
|
'home': {
|
||||||
|
'Start a new private chat',
|
||||||
|
},
|
||||||
|
'home_not_shown': 'Join a public chat',
|
||||||
|
'navigate_to': 'Start a new private chat',
|
||||||
|
'chat': {
|
||||||
|
chat.add_to_contacts,
|
||||||
|
chat.element_by_text('@%s' % ens_name_another_domain),
|
||||||
|
chat.chat_message_input
|
||||||
|
},
|
||||||
|
},
|
||||||
|
public_chat_name: {
|
||||||
|
'home': {
|
||||||
|
'Join a public chat',
|
||||||
|
},
|
||||||
|
'home_not_shown': 'Start a new private chat',
|
||||||
|
'navigate_to': '#%s' % public_chat_name,
|
||||||
|
'chat': {
|
||||||
|
chat.element_by_text('#%s' % public_chat_name),
|
||||||
|
chat.chat_message_input
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
self.home.swipe_down()
|
||||||
|
|
||||||
|
for keyword in search_list_2:
|
||||||
|
self.home.just_fyi('Can start chat from searching for %s' % keyword)
|
||||||
|
self.home.search_by_keyword(keyword)
|
||||||
|
if not self.home.element_by_text_part('No search results. Do you mean').is_element_displayed():
|
||||||
|
self.errors.append('"No search results" is not shown')
|
||||||
|
if 'home_not_shown' in search_list_2[keyword]:
|
||||||
|
if self.home.element_by_text(search_list_2[keyword]['home_not_shown']).is_element_displayed():
|
||||||
|
self.errors.append('%s is shown on home view while searching for %s' % (
|
||||||
|
search_list_2[keyword]['home_not_shown'], keyword))
|
||||||
|
for text in search_list_2[keyword]['home']:
|
||||||
|
if not self.home.element_by_text(text).is_element_displayed():
|
||||||
|
self.errors.append('%s is not shown on home view while searching for %s' % (text, keyword))
|
||||||
|
self.home.element_by_text(search_list_2[keyword]['navigate_to']).click()
|
||||||
|
for element in search_list_2[keyword]['chat']:
|
||||||
|
if not element.is_element_displayed():
|
||||||
|
self.errors.append(
|
||||||
|
'Requested %s element is not shown on chat view after navigating from suggestion '
|
||||||
|
'for %s' % (element.name, keyword))
|
||||||
|
self.home.back_button.click()
|
||||||
|
|
||||||
|
self.home.just_fyi('Can search for public chat name, ens name, username')
|
||||||
|
self.home.swipe_down()
|
||||||
|
for keyword in self.search_list_1:
|
||||||
|
self.home.search_by_keyword(keyword)
|
||||||
|
search_results = self.home.chat_name_text.find_elements()
|
||||||
|
if not search_results:
|
||||||
|
self.errors.append('No search results after searching by %s keyword' % keyword)
|
||||||
|
for element in search_results:
|
||||||
|
if self.search_list_1[keyword] not in element.text:
|
||||||
|
self.errors.append("'%s' is shown on the home screen after searching by '%s' keyword" %
|
||||||
|
(element.text, keyword))
|
||||||
|
self.home.cancel_button.click()
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702253)
|
||||||
|
def test_chat_no_suggestions_invalid_data_search(self):
|
||||||
|
self.home.just_fyi('No suggestion at attempt to search for invalid data')
|
||||||
|
invalid_data = [' ', 'ab;', '.6', '@ana']
|
||||||
|
for text in invalid_data:
|
||||||
|
self.home.search_by_keyword(text)
|
||||||
|
if self.home.element_by_text_part('No search results. Do you mean').is_element_displayed():
|
||||||
|
self.errors.append('"No search results" is shown when searching for invalid value %s' % text)
|
||||||
|
self.home.cancel_button.click()
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702249)
|
||||||
|
def test_chat_input_delete_cut_and_paste_messages(self):
|
||||||
|
|
||||||
|
chat = self.home.add_contact(transaction_senders['N']['public_key'])
|
||||||
|
|
||||||
|
message_text = 'test'
|
||||||
|
message_input = chat.chat_message_input
|
||||||
|
message_input.send_keys(message_text)
|
||||||
|
|
||||||
|
self.home.just_fyi('Deleting last 2 symbols in initial message')
|
||||||
|
message_input.delete_last_symbols(2)
|
||||||
|
current_text = message_input.text
|
||||||
|
if current_text != message_text[:-2]:
|
||||||
|
self.errors.append("Message input text '%s' doesn't match expected '%s'" % (current_text, message_text[:-2]))
|
||||||
|
|
||||||
|
"""self.home.just_fyi('Cutting message text from input field')
|
||||||
|
message_input.cut_text()
|
||||||
|
message_input.click()
|
||||||
|
if current_text != message_text[:-4]:
|
||||||
|
self.errors.append("Message input text '%s' doesn't match expected '%s'" % (current_text, message_text[:-4]))"""
|
||||||
|
|
||||||
|
message_input.cut_text()
|
||||||
|
|
||||||
|
self.home.just_fyi('Pasting the cut message back to the input field')
|
||||||
|
message_input.paste_text_from_clipboard()
|
||||||
|
if current_text != message_text[:-2]:
|
||||||
|
self.errors.append("Message input text '%s' doesn't match expected '%s'" % (current_text, message_text[:-2]))
|
||||||
|
|
||||||
|
chat.send_message_button.click()
|
||||||
|
|
||||||
|
chat.chat_element_by_text(message_text[:-2]).wait_for_visibility_of_element(2)
|
||||||
|
chat.get_back_to_home_view()
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702250)
|
||||||
|
def test_chat_public_clear_history_via_options_and_long_press(self):
|
||||||
|
|
||||||
|
public_long_press = '#public-clear-options'
|
||||||
|
options_chat_name = '#' + self.public_chat_name
|
||||||
|
message = 'test message'
|
||||||
|
|
||||||
|
long_press_chat = self.home.join_public_chat(public_long_press[1:])
|
||||||
|
[long_press_chat.send_message(message) for _ in range(2)]
|
||||||
|
self.home.home_button.double_click()
|
||||||
|
|
||||||
|
self.home.element_by_text(options_chat_name).scroll_to_element()
|
||||||
|
options_chat = self.home.get_chat(options_chat_name)
|
||||||
|
chat_view = options_chat.click()
|
||||||
|
[chat_view.send_message(message) for _ in range(2)]
|
||||||
|
self.home.home_button.double_click()
|
||||||
|
|
||||||
|
self.home.element_by_text(public_long_press).scroll_to_element(direction='up')
|
||||||
|
self.home.just_fyi('Clearing history via long press')
|
||||||
|
self.home.clear_chat_long_press(public_long_press)
|
||||||
|
|
||||||
|
self.home.just_fyi('Clearing history via options')
|
||||||
|
options_chat.click()
|
||||||
|
chat_view.clear_history()
|
||||||
|
if chat_view.element_by_text(message).is_element_displayed():
|
||||||
|
self.errors.append(
|
||||||
|
'Messages in %s chat are still shown after clearing history via options' % options_chat_name)
|
||||||
|
|
||||||
|
self.home.just_fyi("Recheck that history won't reappear after relogin")
|
||||||
|
self.home.relogin()
|
||||||
|
for chat_name in options_chat_name, public_long_press:
|
||||||
|
chat = self.home.get_chat(chat_name).click()
|
||||||
|
if chat.chat_element_by_text(message).is_element_displayed():
|
||||||
|
self.errors.append('Messages in %s chat are shown after clearing history and relaunch' % chat_name)
|
||||||
|
chat.home_button.click()
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
@marks.testrail_id(702254)
|
||||||
|
# Should be the last in group as it disables network connection
|
||||||
|
def test_chat_can_search_while_offline(self):
|
||||||
|
self.home.just_fyi('Can search for public chat while offline')
|
||||||
|
self.home.toggle_airplane_mode()
|
||||||
|
self.home.search_input.click()
|
||||||
|
self.home.search_input.send_keys(self.public_chat_name)
|
||||||
|
search_results = self.home.chat_name_text.find_elements()
|
||||||
|
if not search_results:
|
||||||
|
self.errors.append('No search results after searching by %s keyword' % self.public_chat_name)
|
||||||
|
for element in search_results:
|
||||||
|
if self.search_list_1[self.public_chat_name] not in element.text:
|
||||||
|
self.errors.append("'%s' is shown on the home screen after searching by '%s' keyword" %
|
||||||
|
(element.text, self.public_chat_name))
|
||||||
|
|
||||||
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -292,121 +292,6 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
|||||||
|
|
||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(5362)
|
|
||||||
# TODO: can be moved to TestOneToOneChatMultipleSharedDevices - should be quick e2e
|
|
||||||
def test_1_1_chat_unread_counter_preview_highlited(self):
|
|
||||||
self.create_drivers(2)
|
|
||||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
|
||||||
home_1, home_2 = device_1.create_user(), device_2.create_user()
|
|
||||||
profile_2 = home_2.profile_button.click()
|
|
||||||
default_username_2 = profile_2.default_username_text.text
|
|
||||||
home_2 = profile_2.home_button.click()
|
|
||||||
public_key_1 = home_1.get_public_key_and_username()
|
|
||||||
home_1.home_button.click()
|
|
||||||
chat_2 = home_2.add_contact(public_key_1)
|
|
||||||
|
|
||||||
message, message_2, message_3 = 'test message', 'test message2', 'test'
|
|
||||||
chat_2.send_message(message)
|
|
||||||
chat_element = home_1.get_chat(default_username_2)
|
|
||||||
home_1.dapp_tab_button.click()
|
|
||||||
chat_2.send_message(message_2)
|
|
||||||
|
|
||||||
if home_1.home_button.counter.text != '1':
|
|
||||||
self.errors.append('New messages counter is not shown on Home button')
|
|
||||||
device_1.home_button.click()
|
|
||||||
if chat_element.new_messages_counter.text != '1':
|
|
||||||
self.errors.append('New messages counter is not shown on chat element')
|
|
||||||
chat_1 = chat_element.click()
|
|
||||||
chat_1.add_to_contacts.click()
|
|
||||||
|
|
||||||
home_1.home_button.double_click()
|
|
||||||
|
|
||||||
if home_1.home_button.counter.is_element_displayed():
|
|
||||||
self.errors.append('New messages counter is shown on Home button for already seen message')
|
|
||||||
if chat_element.new_messages_counter.text == '1':
|
|
||||||
self.errors.append('New messages counter is shown on chat element for already seen message')
|
|
||||||
home_1.delete_chat_long_press(default_username_2)
|
|
||||||
|
|
||||||
home_1.just_fyi("Checking preview of message and chat highlighting")
|
|
||||||
chat_2.send_message(message_3)
|
|
||||||
chat_1_element = home_1.get_chat(default_username_2)
|
|
||||||
if chat_1_element.chat_preview.is_element_differs_from_template('highligted_preview.png', 0):
|
|
||||||
self.errors.append("Preview message is not hightligted or text is not shown! ")
|
|
||||||
home_1.get_chat(default_username_2).click()
|
|
||||||
home_1.home_button.double_click()
|
|
||||||
if not home_1.get_chat(default_username_2).chat_preview.is_element_differs_from_template('highligted_preview.png', 0):
|
|
||||||
self.errors.append("Preview message is still highlighted after opening ")
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(700727)
|
|
||||||
# TODO: merge with any medium group that contains 3 types of chats
|
|
||||||
def test_chat_gap_in_public_and_no_gap_in_1_1_and_group(self):
|
|
||||||
self.create_drivers(2)
|
|
||||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
|
||||||
home_1, home_2 = device_1.create_user(), device_2.create_user()
|
|
||||||
message_1 = "testing gap"
|
|
||||||
message_2 = "testing no gap"
|
|
||||||
pub_chat_name = home_1.get_random_chat_name()
|
|
||||||
group_chat_name = home_1.get_random_chat_name()
|
|
||||||
public_key_1, username_1 = home_1.get_public_key_and_username(True)
|
|
||||||
public_key_2, username_2 = home_2.get_public_key_and_username(True)
|
|
||||||
profile_1 = home_1.profile_button.click()
|
|
||||||
profile_1.sync_settings_button.click()
|
|
||||||
profile_1.sync_history_for_button.click()
|
|
||||||
profile_1.element_by_translation_id("two-minutes").click()
|
|
||||||
[home.home_button.click() for home in (home_1, home_2)]
|
|
||||||
|
|
||||||
home_1.just_fyi("Creating 1-1 chat and sending message from device 1")
|
|
||||||
one_to_one_chat_1 = home_1.add_contact(public_key_2)
|
|
||||||
one_to_one_chat_1.send_message("HI")
|
|
||||||
home_1.get_back_to_home_view()
|
|
||||||
|
|
||||||
home_1.just_fyi("Creating group chat and sending message from device 1")
|
|
||||||
group_chat_1 = home_1.create_group_chat([username_2], group_chat_name)
|
|
||||||
group_chat_1.send_message("HI")
|
|
||||||
home_1.get_back_to_home_view()
|
|
||||||
|
|
||||||
home_1.just_fyi("Creating public chat and sending message from device 1")
|
|
||||||
pub_chat_1, pub_chat_2 = home_1.join_public_chat(pub_chat_name), home_2.join_public_chat(pub_chat_name)
|
|
||||||
pub_chat_1.send_message("HI")
|
|
||||||
device_1.toggle_airplane_mode()
|
|
||||||
|
|
||||||
home_2.just_fyi("Joining public chat by device 2 and sending message")
|
|
||||||
pub_chat_2.send_message(message_1)
|
|
||||||
home_2.get_back_to_home_view()
|
|
||||||
|
|
||||||
home_2.just_fyi("Joining 1-1 chat by device 2 and sending message")
|
|
||||||
one_to_one_chat_2 = home_2.add_contact(public_key_1)
|
|
||||||
one_to_one_chat_2.send_message(message_2)
|
|
||||||
home_2.get_back_to_home_view()
|
|
||||||
|
|
||||||
home_2.just_fyi("Joining Group chat by device 2 and sending message")
|
|
||||||
group_chat_2 = home_2.get_chat(group_chat_name).click()
|
|
||||||
group_chat_2.join_chat_button.click()
|
|
||||||
group_chat_2.send_message(message_2)
|
|
||||||
|
|
||||||
# Waiting for 3 minutes and then going back online
|
|
||||||
time.sleep(180)
|
|
||||||
device_1.toggle_airplane_mode()
|
|
||||||
|
|
||||||
home_1.just_fyi("Checking gap in public chat and fetching messages")
|
|
||||||
if pub_chat_1.chat_element_by_text(message_1).is_element_displayed(10):
|
|
||||||
self.errors.append("Test message has been fetched automatically")
|
|
||||||
pub_chat_1.element_by_translation_id("fetch-messages").wait_and_click(60)
|
|
||||||
if not pub_chat_1.chat_element_by_text(message_1).is_element_displayed(10):
|
|
||||||
self.errors.append("Test message has not been fetched")
|
|
||||||
home_1.get_back_to_home_view()
|
|
||||||
|
|
||||||
home_1.just_fyi("Checking that there is no gap in 1-1/group chat and messages fetched automatically")
|
|
||||||
for chat in [home_1.get_chat(username_2), home_1.get_chat(group_chat_name)]:
|
|
||||||
chat_view = chat.click()
|
|
||||||
if chat_view.element_by_translation_id("fetch-messages").is_element_displayed(10):
|
|
||||||
self.errors.append("Fetch messages button is displayed in {}} chat".format(chat.user_name_text.text))
|
|
||||||
if not chat_view.chat_element_by_text(message_2).is_element_displayed(10):
|
|
||||||
self.errors.append("Message in {} chat has not been fetched automatically".format(chat.user_name_text.text))
|
|
||||||
chat_view.back_button.click()
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(695842)
|
@marks.testrail_id(695842)
|
||||||
@marks.flaky
|
@marks.flaky
|
||||||
def test_community_creating_accept_membership(self):
|
def test_community_creating_accept_membership(self):
|
||||||
@@ -706,268 +591,6 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
|||||||
|
|
||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
|
||||||
@marks.testrail_id(5694)
|
|
||||||
# TODO: merge with other group chats e2e
|
|
||||||
def test_group_chat_make_admin(self):
|
|
||||||
self.create_drivers(2)
|
|
||||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
|
||||||
home_1, home_2 = device_1.create_user(), device_2.create_user()
|
|
||||||
public_key_1, username_1 = device_1.get_public_key_and_username(True)
|
|
||||||
device_1.home_button.click()
|
|
||||||
chat_name = home_1.get_random_chat_name()
|
|
||||||
|
|
||||||
device_2.just_fyi('Create and join to group chat')
|
|
||||||
device_2_key, device_2_username = device_2.get_public_key_and_username(True)
|
|
||||||
device_2.home_button.click()
|
|
||||||
home_1.add_contact(device_2_key)
|
|
||||||
home_1.get_back_to_home_view()
|
|
||||||
chat_1 = home_1.create_group_chat([device_2_username], chat_name)
|
|
||||||
chat_2 = home_2.get_chat(chat_name).click()
|
|
||||||
chat_2.join_chat_button.click()
|
|
||||||
|
|
||||||
device_1.just_fyi('Check group info view and options of users')
|
|
||||||
chat_1.chat_options.click()
|
|
||||||
group_info_1 = chat_1.group_info.click()
|
|
||||||
if not group_info_1.user_admin(username_1).is_element_displayed():
|
|
||||||
self.errors.append("Admin user is not marked as admin")
|
|
||||||
group_info_1.get_user_from_group_info(username_1).click()
|
|
||||||
if chat_1.profile_block_contact.is_element_displayed():
|
|
||||||
self.errors.append("Admin is redirected to own profile on tapping own username from group info")
|
|
||||||
group_info_1.get_user_from_group_info(device_2_username).click()
|
|
||||||
if not chat_1.profile_block_contact.is_element_displayed():
|
|
||||||
self.errors.append("Admin is not redirected to user profile on tapping member username from group info")
|
|
||||||
chat_1.close_button.click()
|
|
||||||
|
|
||||||
device_1.just_fyi('Made admin another user and check system message')
|
|
||||||
options = group_info_1.get_username_options(device_2_username).click()
|
|
||||||
options.make_admin_button.click()
|
|
||||||
admin_system_message = chat_1.has_been_made_admin_system_message(username_1, device_2_username)
|
|
||||||
for chat in (chat_1, chat_2):
|
|
||||||
if not chat.chat_element_by_text(admin_system_message).is_element_displayed():
|
|
||||||
self.errors.append("Message with test '%s' was not received" % admin_system_message)
|
|
||||||
|
|
||||||
device_2.just_fyi('Check Admin in group info and that "add members" is available')
|
|
||||||
chat_2.chat_options.click()
|
|
||||||
group_info_1 = chat_2.group_info.click()
|
|
||||||
for username in (username_1, device_2_username):
|
|
||||||
if not group_info_1.user_admin(username).is_element_displayed():
|
|
||||||
self.errors.append("Admin user is not marked as admin")
|
|
||||||
if not group_info_1.add_members.is_element_displayed():
|
|
||||||
self.errors.append("Add member button is not available for new admin")
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(6327)
|
|
||||||
# TODO: merge with other group chats e2e
|
|
||||||
def test_group_chat_set_nickname_and_ens_via_group_info(self):
|
|
||||||
self.create_drivers(2)
|
|
||||||
home_1 = SignInView(self.drivers[0]).create_user()
|
|
||||||
home_2 = SignInView(self.drivers[1]).recover_access(ens_user['passphrase'])
|
|
||||||
profile_1, profile_2 = [home.profile_button.click() for home in (home_1, home_2)]
|
|
||||||
key_1, username_1 = profile_1.get_public_key_and_username(return_username=True)
|
|
||||||
ens, full_ens, username_2 = ens_user['ens'], '@%s' % ens_user['ens'], ens_user['username']
|
|
||||||
profile_2.connect_existing_ens(ens)
|
|
||||||
[profile.home_button.click() for profile in (profile_1, profile_2)]
|
|
||||||
|
|
||||||
home_1.just_fyi('Set nickname, using emojis, special chars and cyrrilic chars without adding to contact')
|
|
||||||
emoji_message = random.choice(list(emoji.EMOJI_UNICODE))
|
|
||||||
emoji_unicode = emoji.EMOJI_UNICODE[emoji_message]
|
|
||||||
special_char, cyrrilic = '"£¢€¥~`•|√π¶∆×°™®©%$@', 'стат'
|
|
||||||
nickname_to_set = emoji.emojize(emoji_message) + special_char + cyrrilic
|
|
||||||
nickname_expected = emoji_unicode + special_char + cyrrilic
|
|
||||||
chat_1 = home_1.add_contact(ens, add_in_contacts=False, nickname=nickname_to_set)
|
|
||||||
if chat_1.user_name_text.text != nickname_expected:
|
|
||||||
self.errors.append('Expected special char nickname %s does not match actual %s' % (nickname_expected, chat_1.user_name_text.text))
|
|
||||||
|
|
||||||
home_1.just_fyi('Can remove nickname without adding to contact')
|
|
||||||
chat_1.chat_options.click()
|
|
||||||
chat_1.view_profile_button.click()
|
|
||||||
chat_1.profile_nickname_button.click()
|
|
||||||
chat_1.nickname_input_field.clear()
|
|
||||||
chat_1.element_by_text('Done').click()
|
|
||||||
chat_1.close_button.click()
|
|
||||||
if chat_1.user_name_text.text != full_ens:
|
|
||||||
self.errors.append(
|
|
||||||
'Nickname was not removed! real chat name is %s instead of %s' % (chat_1.user_name_text.text, full_ens))
|
|
||||||
|
|
||||||
home_1.just_fyi('Adding ENS user to contacts and start group chat with him')
|
|
||||||
group_name = 'ens_group'
|
|
||||||
chat_1.add_to_contacts.click()
|
|
||||||
chat_2 = home_2.add_contact(key_1)
|
|
||||||
chat_2.send_message("first")
|
|
||||||
chat_2.home_button.click()
|
|
||||||
chat_1.home_button.click()
|
|
||||||
chat_1 = home_1.create_group_chat([full_ens], group_name)
|
|
||||||
chat_2 = home_2.get_chat(group_name).click()
|
|
||||||
chat_2.join_chat_button.click()
|
|
||||||
|
|
||||||
home_1.just_fyi('Check ENS and in group chat and suggestions list')
|
|
||||||
chat_1.element_by_text_part(full_ens).wait_for_visibility_of_element(60)
|
|
||||||
chat_1.select_mention_from_suggestion_list(ens, typed_search_pattern=ens[:2])
|
|
||||||
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
|
||||||
self.errors.append(
|
|
||||||
'ENS username is not resolved in chat input after selecting it in mention suggestions list!')
|
|
||||||
additional_text = 'and more'
|
|
||||||
chat_1.send_as_keyevent(additional_text)
|
|
||||||
chat_1.send_message_button.click()
|
|
||||||
message_text = '%s %s' % (full_ens, additional_text)
|
|
||||||
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
|
||||||
self.errors.append("ENS name is not resolved on sent message")
|
|
||||||
chat_1 = home_1.get_chat_view()
|
|
||||||
|
|
||||||
home_1.just_fyi('Set nickname via group info and check that can mention by nickname /username in group chat')
|
|
||||||
nickname = 'funny_bunny'
|
|
||||||
device_2_options = chat_1.get_user_options(full_ens)
|
|
||||||
device_2_options.view_profile_button.click()
|
|
||||||
chat_1.set_nickname(nickname, close_profile=False)
|
|
||||||
if not chat_1.element_by_text(nickname).is_element_displayed():
|
|
||||||
self.errors.append('Nickname is not shown in profile view after setting from group info')
|
|
||||||
chat_1.close_button.click()
|
|
||||||
chat_1.element_by_text(nickname).scroll_to_element()
|
|
||||||
chat_1.close_button.click()
|
|
||||||
message_text = '%s %s' % (nickname, additional_text)
|
|
||||||
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
|
||||||
self.errors.append("ENS name was not replaced with nickname on sent message")
|
|
||||||
chat_1.chat_message_input.send_keys('@')
|
|
||||||
if not chat_1.element_by_text('%s %s' % (nickname, full_ens)).is_element_displayed():
|
|
||||||
self.errors.append("ENS name with nickname is not shown in mention input after set")
|
|
||||||
if not chat_1.element_by_text(username_2).is_element_displayed():
|
|
||||||
self.errors.append("3-random name is not shown in mention input after set from group info")
|
|
||||||
chat_1.chat_message_input.clear()
|
|
||||||
chat_1.select_mention_from_suggestion_list('%s %s' % (nickname, full_ens), typed_search_pattern=username_2[:2])
|
|
||||||
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
|
||||||
self.errors.append(
|
|
||||||
'ENS is not resolved in chat input after setting nickname in mention suggestions list (search by 3-random name)!')
|
|
||||||
chat_1.chat_message_input.clear()
|
|
||||||
chat_1.select_mention_from_suggestion_list('%s %s' % (nickname, full_ens), typed_search_pattern=nickname[:2])
|
|
||||||
if chat_1.chat_message_input.text != '@' + ens + ' ':
|
|
||||||
self.errors.append(
|
|
||||||
'ENS is not resolved in chat input after setting nickname in mention suggestions list (search by nickname)!')
|
|
||||||
chat_1.chat_message_input.clear()
|
|
||||||
|
|
||||||
home_1.just_fyi('Can delete nickname via group info and recheck received messages')
|
|
||||||
device_2_options = chat_1.get_user_options(full_ens)
|
|
||||||
device_2_options.view_profile_button.click()
|
|
||||||
chat_1.profile_nickname_button.click()
|
|
||||||
chat_1.nickname_input_field.clear()
|
|
||||||
chat_1.element_by_text('Done').click()
|
|
||||||
chat_1.close_button.click()
|
|
||||||
chat_1.close_button.click()
|
|
||||||
message_text = '%s %s' % (full_ens, additional_text)
|
|
||||||
if not chat_1.chat_element_by_text(message_text).is_element_displayed():
|
|
||||||
self.errors.append("ENS name is not resolved on sent message after removing nickname")
|
|
||||||
chat_1.chat_message_input.send_keys('@')
|
|
||||||
if chat_1.element_by_text_part(nickname).is_element_displayed():
|
|
||||||
self.errors.append("Nickname is shown in group chat after removing!")
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(6324)
|
|
||||||
def test_group_chat_invite_handling(self):
|
|
||||||
self.create_drivers(3)
|
|
||||||
sign_ins, homes, public_keys, usernames, chats = {}, {}, {}, {}, {}
|
|
||||||
for key in self.drivers:
|
|
||||||
sign_ins[key] = SignInView(self.drivers[key])
|
|
||||||
homes[key] = sign_ins[key].create_user()
|
|
||||||
public_keys[key], usernames[key] = sign_ins[key].get_public_key_and_username(True)
|
|
||||||
sign_ins[key].home_button.click()
|
|
||||||
[driver.close_app() for driver in (self.drivers[1], self.drivers[2])]
|
|
||||||
chat_name = homes[0].get_random_chat_name()
|
|
||||||
|
|
||||||
homes[0].just_fyi('Create group chats without members')
|
|
||||||
chats[0] = homes[0].create_group_chat([], chat_name)
|
|
||||||
link = chats[0].get_group_invite_via_group_info()
|
|
||||||
chats[0].get_back_to_home_view()
|
|
||||||
chats[0].just_fyi('Member_1, member_2: both users send requests to join group chat')
|
|
||||||
[sign_in.open_weblink_and_login(link) for sign_in in (sign_ins[1], sign_ins[2])]
|
|
||||||
introduction_messages = ['message for retrying']
|
|
||||||
for i in range(1, 3):
|
|
||||||
homes[i].element_by_text_part(chat_name).click()
|
|
||||||
chats[i] = ChatView(self.drivers[i])
|
|
||||||
introduction_messages.append('Please add me, member_%s to your gorgeous group chat' % str(i))
|
|
||||||
chats[i].request_membership_for_group_chat(introduction_messages[i])
|
|
||||||
|
|
||||||
chats[0].just_fyi('Admin: accept request for Member_1 and decline for Member_2')
|
|
||||||
homes[0].get_chat(chat_name).click()
|
|
||||||
chats[0].group_membership_request_button.wait_and_click()
|
|
||||||
chats[0].element_by_text(usernames[1]).click()
|
|
||||||
if not chats[0].element_by_text_part(introduction_messages[1]).is_element_displayed():
|
|
||||||
self.errors.append('Introduction message is not shown!')
|
|
||||||
chats[0].accept_group_invitation_button.wait_and_click()
|
|
||||||
chats[0].accept_membership_for_group_chat_via_chat_view(usernames[2], accept=False)
|
|
||||||
chats[0].click_system_back_button()
|
|
||||||
|
|
||||||
chats[2].just_fyi('Member_2: retry request')
|
|
||||||
chats[2].retry_group_invite_button.wait_and_click()
|
|
||||||
chats[2].request_membership_for_group_chat(introduction_messages[0])
|
|
||||||
|
|
||||||
chats[2].just_fyi('Admin: decline request for Member_2')
|
|
||||||
chats[0].group_membership_request_button.wait_and_click()
|
|
||||||
chats[0].element_by_text(usernames[2]).click()
|
|
||||||
if not chats[0].element_by_text_part(introduction_messages[0]).is_element_displayed():
|
|
||||||
self.errors.append('Introduction message that was set after retrying attempt is not shown for admin!')
|
|
||||||
chats[0].decline_group_invitation_button.wait_and_click()
|
|
||||||
chats[0].click_system_back_button()
|
|
||||||
|
|
||||||
chats[2].just_fyi('Member_2: remove chat')
|
|
||||||
chats[2].remove_group_invite_button.wait_and_click()
|
|
||||||
|
|
||||||
chats[2].just_fyi('Double check after relogin')
|
|
||||||
if chats[0].group_membership_request_button.is_element_displayed():
|
|
||||||
self.errors.append('Group membership request is still shown when there are no pending requests anymore')
|
|
||||||
[homes[i].relogin() for i in range(0, 3)]
|
|
||||||
if homes[2].element_by_text_part(chat_name).is_element_displayed():
|
|
||||||
self.errors.append('Group chat was not removed when removing after declining group invite')
|
|
||||||
[home.get_chat(chat_name).click() for home in (homes[0], homes[1])]
|
|
||||||
if chats[0].group_membership_request_button.is_element_displayed():
|
|
||||||
self.errors.append(
|
|
||||||
'Group membership request is shown after relogin when there are no pending requests anymore')
|
|
||||||
join_system_message = chats[0].join_system_message(usernames[1])
|
|
||||||
for chat in (chats[1], chats[0]):
|
|
||||||
if not chat.chat_element_by_text(join_system_message).is_element_displayed():
|
|
||||||
self.errors.append('%s is not shown after joining to group chat via invite' % join_system_message)
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(4001)
|
|
||||||
def test_group_chat_remove_member(self):
|
|
||||||
self.create_drivers(3)
|
|
||||||
homes, public_keys, usernames, chats = {}, {}, {}, {}
|
|
||||||
for key in self.drivers:
|
|
||||||
sign_in_view = SignInView(self.drivers[key])
|
|
||||||
homes[key] = sign_in_view.create_user()
|
|
||||||
public_keys[key], usernames[key] = sign_in_view.get_public_key_and_username(True)
|
|
||||||
sign_in_view.home_button.click()
|
|
||||||
chat_name = homes[0].get_random_chat_name()
|
|
||||||
for i in range(1, 3):
|
|
||||||
homes[0].add_contact(public_keys[i])
|
|
||||||
homes[0].get_back_to_home_view()
|
|
||||||
chats[0] = homes[0].create_group_chat([usernames[1],
|
|
||||||
usernames[2]], chat_name)
|
|
||||||
chats[0].just_fyi('Member_1, member_2: both users join to group chat')
|
|
||||||
for i in range(1, 3):
|
|
||||||
chats[i] = homes[i].get_chat(chat_name).click()
|
|
||||||
chats[i].join_chat_button.click()
|
|
||||||
chats[0].just_fyi("Admin: get options for device 2 in group chat and remove him")
|
|
||||||
options = chats[0].get_user_options(usernames[1])
|
|
||||||
options.remove_user_button.click()
|
|
||||||
left_message = chats[0].leave_system_message(usernames[1])
|
|
||||||
for key in chats:
|
|
||||||
if not chats[key].chat_element_by_text(left_message).is_element_displayed():
|
|
||||||
self.errors.append("Message with text '%s' was not received" % left_message)
|
|
||||||
|
|
||||||
chats[0].just_fyi("Check that input field is not available after removing")
|
|
||||||
if chats[1].chat_message_input.is_element_displayed():
|
|
||||||
self.errors.append("Message input is still available for removed user")
|
|
||||||
chats[0].just_fyi("Send message and check that it is available only for remaining users")
|
|
||||||
message = 'after removing member'
|
|
||||||
chats[0].send_message(message)
|
|
||||||
for chat in (chats[0], chats[2]):
|
|
||||||
if not chat.chat_element_by_text(message).is_element_displayed(30):
|
|
||||||
self.errors.append("Message '%s' was not received after removing member" % message)
|
|
||||||
if chats[1].chat_element_by_text(message).is_element_displayed():
|
|
||||||
self.errors.append("Message '%s' was received by removed member" % message)
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(6294)
|
@marks.testrail_id(6294)
|
||||||
# TODO: may be merged with 6295 to group and add more tx tests
|
# TODO: may be merged with 6295 to group and add more tx tests
|
||||||
def test_keycard_1_1_chat_command_request_and_send_tx_stt_in_1_1_chat_offline_opened_from_push(self):
|
def test_keycard_1_1_chat_command_request_and_send_tx_stt_in_1_1_chat_offline_opened_from_push(self):
|
||||||
@@ -1468,7 +1091,7 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
|||||||
|
|
||||||
@marks.testrail_id(695856)
|
@marks.testrail_id(695856)
|
||||||
# TODO: can be included to TestPairingMultipleDevicesMerged after #13257
|
# TODO: can be included to TestPairingMultipleDevicesMerged after #13257
|
||||||
def test_pairing_devices_sync_photo_community_group_chats(self):
|
def test_pair_devices_sync_photo_community_group_chats(self):
|
||||||
self.create_drivers(2)
|
self.create_drivers(2)
|
||||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
||||||
home_1 = device_1.create_user()
|
home_1 = device_1.create_user()
|
||||||
@@ -1585,9 +1208,11 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
|||||||
recovery_phrase = profile_1.get_recovery_phrase()
|
recovery_phrase = profile_1.get_recovery_phrase()
|
||||||
profile_1.close_button.click()
|
profile_1.close_button.click()
|
||||||
profile_1.home_button.click()
|
profile_1.home_button.click()
|
||||||
|
device_2.put_app_to_background_and_back()
|
||||||
home_3 = device_3.create_user()
|
home_3 = device_3.create_user()
|
||||||
public_key_3, username_3 = home_3.get_public_key_and_username(return_username=True)
|
public_key_3, username_3 = home_3.get_public_key_and_username(return_username=True)
|
||||||
device_3.home_button.click()
|
device_3.home_button.click()
|
||||||
|
device_1.put_app_to_background_and_back()
|
||||||
device_1_name, device_2_name, group_chat_name = 'creator', 'paired', 'some group chat'
|
device_1_name, device_2_name, group_chat_name = 'creator', 'paired', 'some group chat'
|
||||||
home_2 = device_2.recover_access(passphrase=' '.join(recovery_phrase.values()))
|
home_2 = device_2.recover_access(passphrase=' '.join(recovery_phrase.values()))
|
||||||
|
|
||||||
|
|||||||
@@ -16,200 +16,6 @@ from views.sign_in_view import SignInView
|
|||||||
|
|
||||||
@marks.medium
|
@marks.medium
|
||||||
class TestChatManagement(SingleDeviceTestCase):
|
class TestChatManagement(SingleDeviceTestCase):
|
||||||
@marks.testrail_id(5426)
|
|
||||||
# TODO: add to any group with history in public chat
|
|
||||||
def test_chat_public_clear_history_via_options_and_long_press(self):
|
|
||||||
home = SignInView(self.driver).create_user()
|
|
||||||
|
|
||||||
public_options, public_long_press = '#public-clear-options', '#public-long-options'
|
|
||||||
message = 'test message'
|
|
||||||
for pub_chat in [public_options[1:], public_long_press[1:]]:
|
|
||||||
chat = home.join_public_chat(pub_chat)
|
|
||||||
[chat.send_message(message) for _ in range(2)]
|
|
||||||
home.home_button.double_click()
|
|
||||||
|
|
||||||
home.just_fyi('Clearing history via long press')
|
|
||||||
home.clear_chat_long_press(public_long_press)
|
|
||||||
|
|
||||||
home.just_fyi('Clearing history via options')
|
|
||||||
chat = home.get_chat(public_options).click()
|
|
||||||
chat.clear_history()
|
|
||||||
if chat.element_by_text(message).is_element_displayed():
|
|
||||||
self.errors.append(
|
|
||||||
'Messages in %s chat are still shown after clearing history via options' % public_options)
|
|
||||||
|
|
||||||
home.just_fyi("Recheck that history won't reappear after relogin")
|
|
||||||
home.relogin()
|
|
||||||
for chat_name in public_options, public_long_press:
|
|
||||||
chat = home.get_chat(chat_name).click()
|
|
||||||
if chat.chat_element_by_text(message).is_element_displayed():
|
|
||||||
self.errors.append('Messages in %s chat are shown after clearing history and relaunch' % chat_name)
|
|
||||||
chat.home_button.click()
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(6320)
|
|
||||||
# TODO: to unite it with 5757
|
|
||||||
def test_chat_can_start_from_suggestions_using_search(self):
|
|
||||||
sign_in = SignInView(self.driver)
|
|
||||||
home = sign_in.create_user()
|
|
||||||
chat = ChatView(self.driver)
|
|
||||||
ens_name_status, ens_name_another_domain, public_chat_name = ens_user_ropsten['ens'], \
|
|
||||||
ens_user['ens_another'], 'some-pub-chat'
|
|
||||||
search_list = {
|
|
||||||
ens_name_status: {
|
|
||||||
'home': {
|
|
||||||
'Start a new private chat',
|
|
||||||
'Join a public chat',
|
|
||||||
'%s.stateofus.eth' % ens_name_status,
|
|
||||||
'#%s' % ens_name_status
|
|
||||||
},
|
|
||||||
'navigate_to': '%s.stateofus.eth' % ens_name_status,
|
|
||||||
'chat': {
|
|
||||||
chat.add_to_contacts,
|
|
||||||
chat.element_by_text('@%s' % ens_name_status),
|
|
||||||
chat.chat_message_input
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ens_name_another_domain: {
|
|
||||||
'home': {
|
|
||||||
'Start a new private chat',
|
|
||||||
},
|
|
||||||
'home_not_shown': 'Join a public chat',
|
|
||||||
'navigate_to': 'Start a new private chat',
|
|
||||||
'chat': {
|
|
||||||
chat.add_to_contacts,
|
|
||||||
chat.element_by_text('@%s' % ens_name_another_domain),
|
|
||||||
chat.chat_message_input
|
|
||||||
},
|
|
||||||
},
|
|
||||||
public_chat_name: {
|
|
||||||
'home': {
|
|
||||||
'Join a public chat',
|
|
||||||
},
|
|
||||||
'home_not_shown': 'Start a new private chat',
|
|
||||||
'navigate_to': '#%s' % public_chat_name,
|
|
||||||
'chat': {
|
|
||||||
chat.element_by_text('#%s' % public_chat_name),
|
|
||||||
chat.chat_message_input
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
home.just_fyi('Join public chat to have search input on home view')
|
|
||||||
chat_name = home.get_random_chat_name()
|
|
||||||
public_chat = home.join_public_chat(chat_name)
|
|
||||||
public_chat.get_back_to_home_view()
|
|
||||||
home.swipe_down()
|
|
||||||
|
|
||||||
for keyword in search_list:
|
|
||||||
home.just_fyi('Can start chat from searching for %s' % keyword)
|
|
||||||
home.search_by_keyword(keyword)
|
|
||||||
if not home.element_by_text_part('No search results. Do you mean').is_element_displayed():
|
|
||||||
self.errors.append('"No search results" is not shown')
|
|
||||||
if 'home_not_shown' in search_list[keyword]:
|
|
||||||
if home.element_by_text(search_list[keyword]['home_not_shown']).is_element_displayed():
|
|
||||||
self.errors.append('%s is shown on home view while searching for %s' % (
|
|
||||||
search_list[keyword]['home_not_shown'], keyword))
|
|
||||||
for text in search_list[keyword]['home']:
|
|
||||||
if not home.element_by_text(text).is_element_displayed():
|
|
||||||
self.errors.append('%s is not shown on home view while searching for %s' % (text, keyword))
|
|
||||||
home.element_by_text(search_list[keyword]['navigate_to']).click()
|
|
||||||
for element in search_list[keyword]['chat']:
|
|
||||||
if not element.is_element_displayed():
|
|
||||||
self.errors.append(
|
|
||||||
'Requested %s element is not shown on chat view after navigating from suggestion '
|
|
||||||
'for %s' % (element.name, keyword))
|
|
||||||
home.back_button.click()
|
|
||||||
|
|
||||||
home.just_fyi('No suggestion at attempt to search for invalid data')
|
|
||||||
invalid_data = [' ', 'ab;', '.6', '@ana']
|
|
||||||
for text in invalid_data:
|
|
||||||
home.search_by_keyword(text)
|
|
||||||
if home.element_by_text_part('No search results. Do you mean').is_element_displayed():
|
|
||||||
self.errors.append('"No search results" is shown when searching for invalid value %s' % text)
|
|
||||||
home.cancel_button.click()
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(5757)
|
|
||||||
# TODO: to unite it with 6320 and cut the part about offline - to add it to the end of group for instance
|
|
||||||
def test_chat_search_on_home(self):
|
|
||||||
sign_in = SignInView(self.driver)
|
|
||||||
home = sign_in.create_user()
|
|
||||||
|
|
||||||
home.just_fyi('Join public chat, start 1-1 with username and with ENS')
|
|
||||||
chat_name = home.get_random_chat_name()
|
|
||||||
public_chat = home.join_public_chat(chat_name)
|
|
||||||
public_chat.get_back_to_home_view()
|
|
||||||
for public_key in (basic_user['public_key'], ens_user_ropsten['ens'], dummy_user['public_key']):
|
|
||||||
chat = home.add_contact(public_key)
|
|
||||||
chat.get_back_to_home_view()
|
|
||||||
profile = home.profile_button.click()
|
|
||||||
profile.open_contact_from_profile(dummy_user['username'])
|
|
||||||
nickname = 'dummy_user'
|
|
||||||
public_chat.set_nickname(nickname)
|
|
||||||
public_chat.home_button.click()
|
|
||||||
|
|
||||||
search_list = {
|
|
||||||
basic_user['username']: basic_user['username'],
|
|
||||||
ens_user_ropsten['username']: ens_user_ropsten['ens'],
|
|
||||||
chat_name: chat_name,
|
|
||||||
nickname: nickname,
|
|
||||||
dummy_user['username']: nickname,
|
|
||||||
ens_user_ropsten['ens']: ens_user_ropsten['ens']
|
|
||||||
}
|
|
||||||
|
|
||||||
home.just_fyi('Can search for public chat name, ens name, username')
|
|
||||||
home.swipe_down()
|
|
||||||
for keyword in search_list:
|
|
||||||
home.search_by_keyword(keyword)
|
|
||||||
search_results = home.chat_name_text.find_elements()
|
|
||||||
if not search_results:
|
|
||||||
self.errors.append('No search results after searching by %s keyword' % keyword)
|
|
||||||
for element in search_results:
|
|
||||||
if search_list[keyword] not in element.text:
|
|
||||||
self.errors.append("'%s' is shown on the home screen after searching by '%s' keyword" %
|
|
||||||
(element.text, keyword))
|
|
||||||
home.cancel_button.click()
|
|
||||||
|
|
||||||
home.just_fyi('Can search for public chat while offline')
|
|
||||||
home.toggle_airplane_mode()
|
|
||||||
home.search_input.click()
|
|
||||||
home.search_input.send_keys(chat_name)
|
|
||||||
search_results = home.chat_name_text.find_elements()
|
|
||||||
if not search_results:
|
|
||||||
self.errors.append('No search results after searching by %s keyword' % chat_name)
|
|
||||||
for element in search_results:
|
|
||||||
if search_list[chat_name] not in element.text:
|
|
||||||
self.errors.append("'%s' is shown on the home screen after searching by '%s' keyword" %
|
|
||||||
(element.text, chat_name))
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(5322)
|
|
||||||
# TODO: merge with other 1-driver medium e2e
|
|
||||||
def test_chat_input_delete_cut_and_paste_messages(self):
|
|
||||||
sign_in = SignInView(self.driver)
|
|
||||||
home = sign_in.create_user()
|
|
||||||
chat = home.add_contact(transaction_senders['N']['public_key'])
|
|
||||||
|
|
||||||
message_text = 'test'
|
|
||||||
message_input = chat.chat_message_input
|
|
||||||
message_input.send_keys(message_text)
|
|
||||||
|
|
||||||
message_input.delete_last_symbols(2)
|
|
||||||
current_text = message_input.text
|
|
||||||
if current_text != message_text[:-2]:
|
|
||||||
self.driver.fail("Message input text '%s' doesn't match expected '%s'" % (current_text, message_text[:-2]))
|
|
||||||
|
|
||||||
message_input.cut_text()
|
|
||||||
|
|
||||||
message_input.paste_text_from_clipboard()
|
|
||||||
chat.send_message_button.click()
|
|
||||||
|
|
||||||
chat.chat_element_by_text(message_text[:-2]).wait_for_visibility_of_element(2)
|
|
||||||
|
|
||||||
@marks.testrail_id(6221)
|
@marks.testrail_id(6221)
|
||||||
# TODO: delete? a lot of tests are already using this
|
# TODO: delete? a lot of tests are already using this
|
||||||
@@ -249,108 +55,6 @@ class TestChatManagement(SingleDeviceTestCase):
|
|||||||
if profile.element_by_text(basic_user["username"]).is_element_displayed():
|
if profile.element_by_text(basic_user["username"]).is_element_displayed():
|
||||||
self.driver.fail("Unblocked user not added previously in contact list added in contacts!")
|
self.driver.fail("Unblocked user not added previously in contact list added in contacts!")
|
||||||
|
|
||||||
@marks.testrail_id(5498)
|
|
||||||
# TODO: split into separate parts and include to group
|
|
||||||
def test_share_user_profile_url_public_chat(self):
|
|
||||||
home = SignInView(self.driver).create_user()
|
|
||||||
|
|
||||||
home.just_fyi('Join to one-to-one chat and share link to other user profile via messenger')
|
|
||||||
chat = home.add_contact(dummy_user["public_key"])
|
|
||||||
chat.chat_options.click()
|
|
||||||
chat.view_profile_button.click_until_presence_of_element(chat.remove_from_contacts)
|
|
||||||
chat.profile_details.click()
|
|
||||||
chat.share_button.click()
|
|
||||||
chat.share_via_messenger()
|
|
||||||
if not chat.element_by_text_part(
|
|
||||||
'https://join.status.im/u/%s' % dummy_user["public_key"]).is_element_present():
|
|
||||||
self.errors.append("Can't share public key of contact")
|
|
||||||
for _ in range(2):
|
|
||||||
chat.click_system_back_button()
|
|
||||||
|
|
||||||
home.just_fyi('Join to public chat and share link to it via messenger')
|
|
||||||
chat.get_back_to_home_view()
|
|
||||||
public_chat_name = 'pubchat'
|
|
||||||
public_chat = home.join_public_chat(public_chat_name)
|
|
||||||
public_chat.chat_options.click()
|
|
||||||
public_chat.share_chat_button.click()
|
|
||||||
public_chat.share_via_messenger()
|
|
||||||
if not chat.element_by_text_part('https://join.status.im/%s' % public_chat_name).is_element_present():
|
|
||||||
self.errors.append("Can't share link to public chat")
|
|
||||||
for _ in range(2):
|
|
||||||
chat.click_system_back_button()
|
|
||||||
chat.get_back_to_home_view()
|
|
||||||
|
|
||||||
home.just_fyi('Open URL and share link to it via messenger')
|
|
||||||
daap = home.dapp_tab_button.click()
|
|
||||||
browser = daap.open_url('dap.ps')
|
|
||||||
browser.options_button.click()
|
|
||||||
browser.share_url_button.click()
|
|
||||||
browser.share_via_messenger()
|
|
||||||
expeceted_text_1 = 'https://join.status.im/b/https://dap.ps'
|
|
||||||
expeceted_text_2 = 'https://join.status.im/b/http://dap.ps'
|
|
||||||
|
|
||||||
if not (chat.element_by_text_part(expeceted_text_1).is_element_present() or
|
|
||||||
chat.element_by_text_part(expeceted_text_2).is_element_present()):
|
|
||||||
self.errors.append("Can't share link to URL")
|
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(5441)
|
|
||||||
# TODO: merge with other 1-driver medium e2e
|
|
||||||
def test_deep_link_open_user_profile(self):
|
|
||||||
sign_in = SignInView(self.driver)
|
|
||||||
sign_in.create_user()
|
|
||||||
for user_ident in ens_user['ens'], ens_user['ens_another'], ens_user['public_key']:
|
|
||||||
self.driver.close_app()
|
|
||||||
deep_link = 'status-im://u/%s' % user_ident
|
|
||||||
sign_in.open_weblink_and_login(deep_link)
|
|
||||||
chat = sign_in.get_chat_view()
|
|
||||||
for text in ens_user['username'], sign_in.get_translation_by_key("add-to-contacts"):
|
|
||||||
if not chat.element_by_text(text).scroll_to_element(10):
|
|
||||||
self.driver.fail("User profile screen is not opened")
|
|
||||||
|
|
||||||
@marks.testrail_id(5442)
|
|
||||||
# TODO: merge with other 1-driver medium e2e
|
|
||||||
def test_deep_link_open_dapp(self):
|
|
||||||
sign_in_view = SignInView(self.driver)
|
|
||||||
sign_in_view.create_user()
|
|
||||||
self.driver.close_app()
|
|
||||||
dapp_name = test_dapp_url
|
|
||||||
dapp_deep_link = 'status-im://b/%s' % dapp_name
|
|
||||||
sign_in_view.open_weblink_and_login(dapp_deep_link)
|
|
||||||
web_view = sign_in_view.get_chat_view()
|
|
||||||
try:
|
|
||||||
test_dapp_view = web_view.open_in_status_button.click()
|
|
||||||
test_dapp_view.allow_button.is_element_present()
|
|
||||||
except NoSuchElementException:
|
|
||||||
self.driver.fail("DApp '%s' is not opened!" % dapp_name)
|
|
||||||
|
|
||||||
@marks.testrail_id(5781)
|
|
||||||
# TODO: merge with other 1-driver medium e2e
|
|
||||||
def test_deep_link_with_invalid_user_public_key_own_profile_key(self):
|
|
||||||
sign_in = SignInView(self.driver)
|
|
||||||
sign_in.recover_access(passphrase=basic_user['passphrase'])
|
|
||||||
self.driver.close_app()
|
|
||||||
|
|
||||||
sign_in.just_fyi('Check that no error when opening invalid deep link')
|
|
||||||
deep_link = 'status-im://u/%s' % basic_user['public_key'][:-10]
|
|
||||||
sign_in.open_weblink_and_login(deep_link)
|
|
||||||
home = sign_in.get_home_view()
|
|
||||||
home.plus_button.click_until_presence_of_element(home.start_new_chat_button)
|
|
||||||
if not home.start_new_chat_button.is_element_present():
|
|
||||||
self.errors.append(
|
|
||||||
"Can't navigate to start new chat after app opened from deep link with invalid public key")
|
|
||||||
self.driver.close_app()
|
|
||||||
|
|
||||||
sign_in.just_fyi('Check that no error when opening invalid deep link')
|
|
||||||
deep_link = 'status-im://u/%s' % basic_user['public_key']
|
|
||||||
sign_in.open_weblink_and_login(deep_link)
|
|
||||||
from views.profile_view import ProfileView
|
|
||||||
profile = ProfileView(self.driver)
|
|
||||||
if not profile.default_username_text != basic_user['username']:
|
|
||||||
self.errors.append("Can't navigate to profile from deep link with own public key")
|
|
||||||
self.errors.verify_no_errors()
|
|
||||||
|
|
||||||
@marks.testrail_id(6319)
|
@marks.testrail_id(6319)
|
||||||
# TODO: merge with other 1-driver medium e2e
|
# TODO: merge with other 1-driver medium e2e
|
||||||
def test_permissions_deny_access_camera_and_gallery(self):
|
def test_permissions_deny_access_camera_and_gallery(self):
|
||||||
@@ -892,7 +596,7 @@ class TestChatManagement(SingleDeviceTestCase):
|
|||||||
wallet.click_system_back_button()
|
wallet.click_system_back_button()
|
||||||
|
|
||||||
wallet.just_fyi("Send transaction to new account")
|
wallet.just_fyi("Send transaction to new account")
|
||||||
transaction_amount = '0.004'
|
transaction_amount = '0.006'
|
||||||
initial_balance = self.network_api.get_balance(status_account_address)
|
initial_balance = self.network_api.get_balance(status_account_address)
|
||||||
wallet.send_transaction(account_name=account_name, amount=transaction_amount, keycard=True)
|
wallet.send_transaction(account_name=account_name, amount=transaction_amount, keycard=True)
|
||||||
self.network_api.wait_for_confirmation_of_transaction(status_account_address, transaction_amount)
|
self.network_api.wait_for_confirmation_of_transaction(status_account_address, transaction_amount)
|
||||||
@@ -1151,6 +855,7 @@ class TestChatManagement(SingleDeviceTestCase):
|
|||||||
home.just_fyi("Checking setting pairing with new PIN")
|
home.just_fyi("Checking setting pairing with new PIN")
|
||||||
profile.change_pairing_code_button.click()
|
profile.change_pairing_code_button.click()
|
||||||
keycard.enter_another_pin()
|
keycard.enter_another_pin()
|
||||||
|
sign_in.create_password_input.wait_for_element()
|
||||||
sign_in.create_password_input.set_value(common_password)
|
sign_in.create_password_input.set_value(common_password)
|
||||||
sign_in.confirm_your_password_input.set_value(common_password + "1")
|
sign_in.confirm_your_password_input.set_value(common_password + "1")
|
||||||
if not keycard.element_by_translation_id("pairing-code_error1").is_element_displayed():
|
if not keycard.element_by_translation_id("pairing-code_error1").is_element_displayed():
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from support.api.third_parties_api import get_token_info
|
|||||||
|
|
||||||
|
|
||||||
def get_parameters():
|
def get_parameters():
|
||||||
directory = os.sep.join(__file__.split(os.sep)[:-4])
|
directory = os.sep.join(__file__.split(os.sep)[:-5])
|
||||||
file_path = path.join(directory, 'src/status_im/ethereum/tokens.cljs')
|
file_path = path.join(directory, 'src/status_im/ethereum/tokens.cljs')
|
||||||
with open(file_path, 'r') as f:
|
with open(file_path, 'r') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
|
|||||||
@@ -346,6 +346,21 @@ class BaseView(object):
|
|||||||
for _ in range(times):
|
for _ in range(times):
|
||||||
self.driver.press_keycode(4)
|
self.driver.press_keycode(4)
|
||||||
|
|
||||||
|
def click_system_back_button_until_element_is_shown(self, attempts=3, element='home'):
|
||||||
|
counter = 0
|
||||||
|
if element is 'home':
|
||||||
|
element = self.home_button
|
||||||
|
while not element.is_element_present(1) and counter <= attempts:
|
||||||
|
try:
|
||||||
|
self.driver.press_keycode(4)
|
||||||
|
element.is_element_present(5)
|
||||||
|
return self
|
||||||
|
except (NoSuchElementException, TimeoutException):
|
||||||
|
counter += 1
|
||||||
|
else:
|
||||||
|
self.driver.info("Could not reach %s element by pressing back" % element.name)
|
||||||
|
|
||||||
|
|
||||||
def get_app_from_background(self):
|
def get_app_from_background(self):
|
||||||
self.driver.info('Get Status back from Recent apps')
|
self.driver.info('Get Status back from Recent apps')
|
||||||
self.driver.press_keycode(187)
|
self.driver.press_keycode(187)
|
||||||
@@ -564,7 +579,8 @@ class BaseView(object):
|
|||||||
|
|
||||||
def share_via_messenger(self):
|
def share_via_messenger(self):
|
||||||
self.driver.info("Sharing via messenger", device=False)
|
self.driver.info("Sharing via messenger", device=False)
|
||||||
self.element_by_text('Messages').wait_and_click(40)
|
self.element_by_text('Messages').wait_for_visibility_of_element(40)
|
||||||
|
self.element_by_text('Messages').click_until_presence_of_element(self.element_by_text('New message'))
|
||||||
self.element_by_text('New message').wait_and_click()
|
self.element_by_text('New message').wait_and_click()
|
||||||
self.send_as_keyevent('+0100100101')
|
self.send_as_keyevent('+0100100101')
|
||||||
self.confirm()
|
self.confirm()
|
||||||
|
|||||||
@@ -881,7 +881,7 @@ class ChatView(BaseView):
|
|||||||
self.get_stickers.click()
|
self.get_stickers.click()
|
||||||
element = Button(self.driver,
|
element = Button(self.driver,
|
||||||
xpath="//*[@content-desc='sticker-pack-name'][@text='%s']/..//*[@content-desc='sticker-pack-price']" % pack_name)
|
xpath="//*[@content-desc='sticker-pack-name'][@text='%s']/..//*[@content-desc='sticker-pack-price']" % pack_name)
|
||||||
element.scroll_to_element()
|
element.scroll_to_element(depth=21)
|
||||||
element.click()
|
element.click()
|
||||||
element.wait_for_invisibility_of_element()
|
element.wait_for_invisibility_of_element()
|
||||||
self.back_button.click()
|
self.back_button.click()
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 295 B |
@@ -38,7 +38,7 @@ class AccountElementButton(SilentButton):
|
|||||||
|
|
||||||
def color_matches(self, expected_color_image_name: str):
|
def color_matches(self, expected_color_image_name: str):
|
||||||
amount_text = Text(self.driver, xpath="%s//*[@content-desc='account-total-value']" % self.locator)
|
amount_text = Text(self.driver, xpath="%s//*[@content-desc='account-total-value']" % self.locator)
|
||||||
amount_text.wait_for_element_text('0', 60)
|
amount_text.wait_for_element_text('...', 60)
|
||||||
return not amount_text.is_element_differs_from_template(expected_color_image_name)
|
return not amount_text.is_element_differs_from_template(expected_color_image_name)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7491,10 +7491,10 @@ react-native-share@^7.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-7.0.1.tgz#1deef27afcd8275222ba0efeac337e7cea99bc4b"
|
resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-7.0.1.tgz#1deef27afcd8275222ba0efeac337e7cea99bc4b"
|
||||||
integrity sha512-hq7nOirgih/zIF9UU9FuYKZ3NGvasu2c/eJesvyPKYiykTtgQZM+mvDwFk/ogEsGwRtTPJBtj8/6IyIFcGa7lw==
|
integrity sha512-hq7nOirgih/zIF9UU9FuYKZ3NGvasu2c/eJesvyPKYiykTtgQZM+mvDwFk/ogEsGwRtTPJBtj8/6IyIFcGa7lw==
|
||||||
|
|
||||||
react-native-splash-screen@^3.2.0:
|
react-native-splash-screen@3.3.0:
|
||||||
version "3.2.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45"
|
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02"
|
||||||
integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg==
|
integrity sha512-rGjt6HkoSXxMqH4SQUJ1gnPQlPJV8+J47+4yhgTIan4bVvAwJhEeJH7wWt9hXSdH4+VfwTS0GTaflj1Tw83IhA==
|
||||||
|
|
||||||
"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.37":
|
"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.37":
|
||||||
version "2.5.37"
|
version "2.5.37"
|
||||||
|
|||||||