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
|
||||
TWO_MINUTES_SYNCING=1
|
||||
SWAP_ENABLED=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
|
||||
@@ -34,3 +34,4 @@ COMMUNITIES_MANAGEMENT_ENABLED=1
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
@@ -37,3 +37,4 @@ METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
ENABLE_QUO_PREVIEW=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
@@ -17,12 +17,12 @@ buildscript {
|
||||
repositories {
|
||||
flatDir { dirs "libs", "${rootDir}/app/libs" }
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
|
||||
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!
|
||||
// They belong in the individual module build.gradle files.
|
||||
}
|
||||
@@ -45,27 +45,22 @@ subprojects {
|
||||
|
||||
allprojects {
|
||||
beforeEvaluate {
|
||||
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!')
|
||||
}
|
||||
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!')
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url("$rootDir/../node_modules/react-native/android")
|
||||
}
|
||||
maven {
|
||||
// Android JSC is installed from npm
|
||||
url("$rootDir/../node_modules/jsc-android/dist")
|
||||
}
|
||||
|
||||
google()
|
||||
jcenter()
|
||||
|
||||
// for geth, function, and status-go
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
maven { url("$rootDir/../node_modules/react-native/android") }
|
||||
// Android JSC is installed from npm
|
||||
maven { url("$rootDir/../node_modules/jsc-android/dist") }
|
||||
// For geth, function, and status-go
|
||||
flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR }
|
||||
// Everything Else
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url "https://www.jitpack.io" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
library 'status-jenkins-lib@v1.4.1'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux && x86_64 && nix-2.6' }
|
||||
agent { label 'linux && x86_64 && nix-2.8' }
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
library 'status-jenkins-lib@v1.4.1'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos && x86_64 && nix-2.6 && xcode-12.5' }
|
||||
agent { label 'macos && x86_64 && nix-2.8 && xcode-13.3' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
|
||||
@@ -98,8 +98,8 @@ pipeline {
|
||||
nix.shell("""
|
||||
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
|
||||
-not -name '*.links' -and -not -name '*-status-react-*' \
|
||||
| xargs nix-copy-closure -v \
|
||||
--to ${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
|
||||
| xargs nix copy \
|
||||
--to ssh-ng://${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
|
||||
""",
|
||||
pure: false
|
||||
)
|
||||
|
||||
@@ -58,7 +58,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 15 \
|
||||
--numprocesses 9 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m testrail_id \
|
||||
|
||||
@@ -97,7 +97,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 15 \
|
||||
--numprocesses 9 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m \"${params.TEST_MARKERS}\" \
|
||||
|
||||
@@ -8,7 +8,7 @@ Modules provided by `yarn2nix` are normally fine, but we use `react-native-*` pa
|
||||
```js
|
||||
repositories {
|
||||
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.
|
||||
|
||||
@@ -11,3 +11,5 @@ keep-derivations = true
|
||||
keep-outputs = true
|
||||
# Extra isolation for network and filesystem, doesn't work on MacOS
|
||||
build-use-sandbox = false
|
||||
# Enable Nix v2 interface.
|
||||
experimental-features = nix-command
|
||||
|
||||
@@ -33,12 +33,12 @@ in {
|
||||
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
|
||||
|
||||
# Package version adjustments
|
||||
go = super.pkgs.go_1_16;
|
||||
go = super.pkgs.go_1_17;
|
||||
gradle = super.pkgs.gradle_5;
|
||||
nodejs = super.pkgs.nodejs-12_x;
|
||||
nodejs = super.pkgs.nodejs-16_x;
|
||||
openjdk = super.pkgs.openjdk8_headless;
|
||||
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
|
||||
version = "11.5";
|
||||
version = "13.3";
|
||||
allowHigher = true;
|
||||
};
|
||||
gomobile = super.gomobile.override {
|
||||
|
||||
@@ -13,8 +13,8 @@ let
|
||||
name = "nixpkgs-source";
|
||||
owner = "status-im";
|
||||
repo = "nixpkgs";
|
||||
rev = "15111f8a9ad423d300886b537647691c2faa28cd";
|
||||
sha256 = "05ny644x3dpxigljnb4rmams5vrs5gkbcyqjfamvlqm8rdmsi0kn";
|
||||
rev = "4ba5f26780e7a27aa2e97676603cd9ef04f11e74";
|
||||
sha256 = "sha256-ZpHXUuF9bvHooKwGuR1Mr/n2mE/LJ6/MCdCk2AfdD9M=";
|
||||
# To get the compressed Nix sha256, use:
|
||||
# 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}/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_SHA256="a63732b4f3628ce97e096dbda88e3cb9851ff6b4f94b5cd43feb257126437b9d"
|
||||
NIX_INSTALL_SHA256="f43bfedfca9151479462d8bc11f238615a2d52f19b14894d8e2b59980e75ef72"
|
||||
NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}"
|
||||
|
||||
install_nix() {
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
"react-native-safe-area-context": "^2.0.0",
|
||||
"react-native-shake": "^3.3.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-svg": "^9.8.4",
|
||||
"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 [])
|
||||
:View {}
|
||||
:FlatList {}
|
||||
:Image {}
|
||||
:ScrollView {}
|
||||
:Text {}}
|
||||
:Easing {:bezier (fn [])
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
["@react-native-community/hooks" :as hooks]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
["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))
|
||||
|
||||
@@ -74,6 +75,9 @@
|
||||
(def animated-view
|
||||
(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 layout-animation (.-LayoutAnimation ^js rn))
|
||||
@@ -103,6 +107,10 @@
|
||||
:delete #js {:type (:ease-in-ease-out layout-animation-types)
|
||||
: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)))
|
||||
|
||||
;; Flat-list
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
[_ _]
|
||||
(let [pressed (reagent/atom false)]
|
||||
(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
|
||||
size 40}}
|
||||
children]
|
||||
@@ -126,17 +126,19 @@
|
||||
{:on-press-out (fn []
|
||||
(reset! pressed nil))})
|
||||
|
||||
[rn/view {:style (style-container
|
||||
type
|
||||
size
|
||||
disabled
|
||||
(get background-color state)
|
||||
(get border-color state)
|
||||
icon
|
||||
above
|
||||
width
|
||||
before
|
||||
after)}
|
||||
[rn/view {:style (merge
|
||||
(style-container
|
||||
type
|
||||
size
|
||||
disabled
|
||||
(get background-color state)
|
||||
(get border-color state)
|
||||
icon
|
||||
above
|
||||
width
|
||||
before
|
||||
after)
|
||||
style)}
|
||||
(when above
|
||||
[rn/view
|
||||
[quo2.icons/icon above {:container-style {:margin-bottom 2}
|
||||
@@ -168,4 +170,4 @@
|
||||
[quo2.icons/icon after {:container-style {:margin-left 4
|
||||
:margin-right (if (= size 40) 12 8)}
|
||||
:color icon-color
|
||||
:size icon-size}]])]]))))
|
||||
:size icon-size}]])]]))))
|
||||
|
||||
@@ -29,5 +29,6 @@
|
||||
(let [this (reagent/current-component)
|
||||
props (reagent/props this)
|
||||
style (text-style props)]
|
||||
(into [rn/text {:style style}]
|
||||
(reagent/children this))))
|
||||
(into [rn/text (merge {:style style}
|
||||
(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-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
|
||||
(def neutral-80-opa-60 (alpha neutral-80 0.6))
|
||||
(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-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]
|
||||
(if (theme/dark?) dark light))
|
||||
(if (theme/dark?) dark light))
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
[status-im.navigation :as navigation]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.platform :as platform]
|
||||
@@ -182,20 +181,6 @@
|
||||
:history new-history
|
||||
: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
|
||||
{:events [:browser.callback/resolve-ens-multihash-success]}
|
||||
[{:keys [db] :as cofx} url]
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.navigation :as navigation]
|
||||
[status-im.navigation2 :as navigation2]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.utils :as utils]
|
||||
@@ -263,6 +264,15 @@
|
||||
(navigation/pop-to-root-tab % :chat-stack))
|
||||
(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
|
||||
{:events [::history-cleared]}
|
||||
[{:keys [db]} chat-id response]
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
[status-im.utils.fx :as fx]
|
||||
["emojilib" :as emojis]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]))
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(defn text->emoji
|
||||
"Replaces emojis in a specified `text`"
|
||||
@@ -230,12 +229,12 @@
|
||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})})))
|
||||
|
||||
(fx/defn send-sticker-message
|
||||
[cofx {:keys [hash pack]} current-chat-id]
|
||||
(when-not (string/blank? hash)
|
||||
[cofx {:keys [hash packID]} current-chat-id]
|
||||
(when-not (or (string/blank? hash) (string/blank? packID))
|
||||
(chat.message/send-message cofx {:chat-id current-chat-id
|
||||
:content-type constants/content-type-sticker
|
||||
:sticker {:hash hash
|
||||
:pack pack}
|
||||
:pack (int packID)}
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||
|
||||
(fx/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id]}]
|
||||
@@ -265,13 +264,16 @@
|
||||
|
||||
(fx/defn 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
|
||||
cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:stickers/recent-stickers
|
||||
(conj (remove #(= hash %) (:stickers/recent-stickers multiaccount)) hash)
|
||||
{})
|
||||
{:db (update db
|
||||
:stickers/recent-stickers
|
||||
(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)))
|
||||
|
||||
(fx/defn chat-send-audio
|
||||
|
||||
@@ -171,4 +171,8 @@
|
||||
(def ^:const visibility-status-inactive 4)
|
||||
|
||||
(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))
|
||||
(update :wallet/visible-tokens rpc->visible-tokens)
|
||||
(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 :custom-bootnodes rpc->custom-bootnodes)
|
||||
(update :custom-bootnodes-enabled? rpc->custom-bootnodes)
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
:dimensions/window (dimensions/window)
|
||||
:registry {}
|
||||
:visibility-status-updates {}
|
||||
:stickers/packs-owned #{}
|
||||
:stickers/packs-pending #{}
|
||||
:keycard {:nfc-enabled? false
|
||||
:pin {:original []
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
#(re-frame/dispatch [::name-resolved username
|
||||
(cond
|
||||
(not public-key) :owned
|
||||
(string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
(and (string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000") (not custom-domain?))
|
||||
:invalid-ens
|
||||
(= % public-key) :connected
|
||||
:else :connected-with-different-key)
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
"wallet_loadTransferByHash" {}
|
||||
"wallet_getTokens" {};, %* [chainId]}
|
||||
"wallet_getTokensBalancesForChainIDs" {};, %* [@[chainId], accounts, tokens]
|
||||
"wallet_fetchPrices" {}
|
||||
"browsers_getBrowsers" {}
|
||||
"browsers_addBrowser" {}
|
||||
"browsers_deleteBrowser" {}
|
||||
@@ -241,7 +242,16 @@
|
||||
"mailservers_getChatRequestRanges" {}
|
||||
"mailservers_deleteChatRequestRange" {}
|
||||
"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
|
||||
[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.signing.core :as signing]
|
||||
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
|
||||
:dismiss-keyboard
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.communities.core :as communities]
|
||||
[status-im.transport.core :as transport]
|
||||
[status-im.stickers.core :as stickers]
|
||||
[status-im.mobile-sync-settings.core :as mobile-network]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
@@ -445,7 +444,6 @@
|
||||
(initialize-transactions-management-enabled)
|
||||
(check-network-version network-id)
|
||||
(contact/initialize-contacts)
|
||||
(stickers/init-stickers-packs)
|
||||
(initialize-browser)
|
||||
(mobile-network/on-network-status-change)
|
||||
(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
|
||||
(:require [cljs.reader :as edn]
|
||||
[clojure.set :as clojure.set]
|
||||
[clojure.string :as string]
|
||||
(:require [clojure.string :as string]
|
||||
[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.json-rpc :as json-rpc]
|
||||
[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.utils :as utils]))
|
||||
|
||||
(defn pack-data-callback
|
||||
[id]
|
||||
(fn [[_ _ _ _ price contenthash]]
|
||||
(when-let [url (contenthash/url contenthash)]
|
||||
(re-frame/dispatch [:stickers/load-pack url id price]))))
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:stickers/set-pending-timeout-fx
|
||||
@@ -26,193 +15,109 @@
|
||||
(utils/set-timeout #(re-frame/dispatch [:stickers/pending-timeout])
|
||||
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
|
||||
{:events [:stickers/install-pack]}
|
||||
[{{:keys [multiaccount] :as db} :db :as cofx} id]
|
||||
(let [pack (get-in db [:stickers/packs id])]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:stickers/packs-installed id] pack))}
|
||||
;;(assoc :stickers/selected-pack id))} TODO it doesn't scroll to selected pack on Android
|
||||
(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]))}})
|
||||
[{db :db :as cofx} id]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:stickers/packs id :status] constants/sticker-pack-status-installed)
|
||||
::json-rpc/call [{:method "stickers_install"
|
||||
:params [(ethereum/chain-id db) id]
|
||||
:on-success #()}]}))
|
||||
|
||||
(fx/defn load-packs
|
||||
{:events [:stickers/load-packs]}
|
||||
[{:keys [db]}]
|
||||
(let [contract (contracts/get-address db :status/stickers)
|
||||
pack-contract (contracts/get-address db :status/sticker-pack)
|
||||
address (ethereum/default-address db)]
|
||||
(when contract
|
||||
{:stickers/owned-packs-fx [pack-contract address]
|
||||
:stickers/load-packs-fx [contract]})))
|
||||
{::json-rpc/call [{:method "stickers_market"
|
||||
:params [(ethereum/chain-id db)]
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-market-success %])}
|
||||
{:method "stickers_installed"
|
||||
:params []
|
||||
: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]}
|
||||
[{db :db :as cofx} pack-id price]
|
||||
(let [address (ethereum/default-address db)
|
||||
sticker-market-contract (contracts/get-address db :status/sticker-market)
|
||||
snt-contract (contracts/get-address db :status/snt)]
|
||||
(signing/eth-transaction-call
|
||||
cofx
|
||||
{: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]})))
|
||||
[{db :db} pack-id]
|
||||
{::json-rpc/call [{:method "stickers_buyPrepareTx"
|
||||
:params [(ethereum/chain-id db) (ethereum/default-address db) (int pack-id)]
|
||||
:on-success #(re-frame/dispatch [:signing.ui/sign
|
||||
{:tx-obj %
|
||||
:on-result [:stickers/pending-pack pack-id]}])}]})
|
||||
|
||||
(fx/defn pending-pack
|
||||
{:events [:stickers/pending-pack]}
|
||||
[{{:keys [multiaccount] :as db} :db :as cofx} id]
|
||||
(let [contract (contracts/get-address db :status/sticker-pack)
|
||||
address (ethereum/default-address db)
|
||||
pending (get multiaccount :stickers/packs-pending #{})]
|
||||
(when contract
|
||||
(fx/merge cofx
|
||||
{:db (update db :stickers/packs-pending conj id)
|
||||
:stickers/owned-packs-fx [contract address]}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:stickers/packs-pending
|
||||
(conj pending id)
|
||||
{})
|
||||
#(when (zero? (count (:stickers/packs-pending db)))
|
||||
{:stickers/set-pending-timeout-fx nil})))))
|
||||
[{db :db} id]
|
||||
{:db (-> db
|
||||
(assoc-in [:stickers/packs id :status] constants/sticker-pack-status-pending)
|
||||
(update :stickers/packs-pending conj id))
|
||||
:stickers/set-pending-timeout-fx nil
|
||||
::json-rpc/call [{:method "stickers_addPending"
|
||||
:params [(ethereum/chain-id db) (int id)]
|
||||
:on-success #()}]})
|
||||
|
||||
(fx/defn pending-timeout
|
||||
{:events [:stickers/pending-timeout]}
|
||||
[{{:stickers/keys [packs-pending packs-owned] :as db} :db :as cofx}]
|
||||
(let [packs-diff (clojure.set/difference packs-pending packs-owned)
|
||||
contract (contracts/get-address db :status/sticker-pack)
|
||||
address (ethereum/default-address db)]
|
||||
(when contract
|
||||
(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
|
||||
{})))))
|
||||
[{{:stickers/keys [packs-pending] :as db} :db}]
|
||||
(when (seq packs-pending)
|
||||
{::json-rpc/call [{:method "stickers_processPending"
|
||||
:params [(ethereum/chain-id db)]
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-process-pending-success %])}]}))
|
||||
|
||||
(fx/defn pack-owned
|
||||
{:events [:stickers/pack-owned]}
|
||||
[{db :db} id]
|
||||
{:db (update db :stickers/packs-owned conj id)})
|
||||
(fx/defn stickers-process-pending-success
|
||||
{:events [:stickers/stickers-process-pending-success]}
|
||||
[{{:stickers/keys [packs-pending packs] :as db} :db} purchased]
|
||||
(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
|
||||
{: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 :waku/v2-peer-stats :peer-stats)
|
||||
(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
|
||||
;; it is about cellular network/ wifi network
|
||||
@@ -136,9 +137,7 @@
|
||||
;;stickers
|
||||
(reg-root-key-sub :stickers/selected-pack :stickers/selected-pack)
|
||||
(reg-root-key-sub :stickers/packs :stickers/packs)
|
||||
(reg-root-key-sub :stickers/installed-packs :stickers/packs-installed)
|
||||
(reg-root-key-sub :stickers/packs-owned :stickers/packs-owned)
|
||||
(reg-root-key-sub :stickers/packs-pending :stickers/packs-pending)
|
||||
(reg-root-key-sub :stickers/recent-stickers :stickers/recent-stickers)
|
||||
|
||||
;;mailserver
|
||||
(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]]
|
||||
(let [sending-image (seq sending-image)]
|
||||
{:send (not processing)
|
||||
:stickers (and mainnet?
|
||||
:stickers (and (or config/stickers-test-enabled? mainnet?)
|
||||
(not sending-image)
|
||||
(not reply))
|
||||
:image (and (not reply)
|
||||
@@ -1515,23 +1514,20 @@
|
||||
;;STICKERS =============================================================================================================
|
||||
|
||||
(re-frame/reg-sub
|
||||
:stickers/installed-packs-vals
|
||||
:<- [:stickers/installed-packs]
|
||||
:stickers/installed-packs
|
||||
:<- [:stickers/packs]
|
||||
(fn [packs]
|
||||
(vals packs)))
|
||||
(filter #(= (:status %) constants/sticker-pack-status-installed) (vals packs))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:stickers/all-packs
|
||||
:<- [:stickers/packs]
|
||||
:<- [:stickers/installed-packs]
|
||||
:<- [:stickers/packs-owned]
|
||||
:<- [:stickers/packs-pending]
|
||||
(fn [[packs installed owned pending]]
|
||||
(map (fn [{:keys [id] :as pack}]
|
||||
(cond-> pack
|
||||
(get installed id) (assoc :installed true)
|
||||
(get owned id) (assoc :owned true)
|
||||
(get pending id) (assoc :pending true)))
|
||||
(fn [packs]
|
||||
(map (fn [{:keys [status] :as pack}]
|
||||
(-> pack
|
||||
(assoc :installed (= status constants/sticker-pack-status-installed))
|
||||
(assoc :pending (= status constants/sticker-pack-status-pending))
|
||||
(assoc :owned (= status constants/sticker-pack-status-owned))))
|
||||
(vals packs))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
@@ -1541,19 +1537,6 @@
|
||||
(fn [[{:keys [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 ==============================================================================================================
|
||||
|
||||
(def memo-home-items (atom nil))
|
||||
@@ -2964,3 +2947,19 @@
|
||||
:<- [:bookmarks]
|
||||
(fn [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.transport.shh
|
||||
[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
|
||||
{:events [:transport.callback/node-info-fetched]}
|
||||
@@ -65,4 +66,5 @@
|
||||
(add-mailservers mailservers))}
|
||||
(fetch-node-info-fx)
|
||||
(pairing/init)
|
||||
(stickers/load-packs)
|
||||
(universal-links/process-stored-event)))
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
[status-im.utils.debounce :as debounce]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.js-resources :as js-res]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.ui.components.permissions :as components.permissions]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
@@ -58,8 +57,7 @@
|
||||
(reagent/as-element
|
||||
[react/view styles/web-view-error
|
||||
[react/image {:style {:width 140 :height 140 :margin-bottom 16}
|
||||
:source {:uri (contenthash/url
|
||||
"e3010170122001bbe2f5bfba0305a3bdc2047fddc47ee595a591bdee61de6040ffc2456624e1")}}]
|
||||
:source {:uri "https://bafybeiabxprplp52amc2hpocar753rd64wk2len55zq54yca77bekzre4e.ipfs.cf-ipfs.com"}}]
|
||||
[react/i18n-text {:style styles/web-view-error-text :key :web-view-error}]
|
||||
[react/text {:style styles/web-view-error-text}
|
||||
(str desc)]]))
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
[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.utils :as chat.utils]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||
@@ -558,7 +557,7 @@
|
||||
:accessibility-label :sticker-message
|
||||
:on-press (fn [_]
|
||||
(when pack
|
||||
(re-frame/dispatch [:stickers/open-sticker-pack pack]))
|
||||
(re-frame/dispatch [:stickers/open-sticker-pack (str pack)]))
|
||||
(react/dismiss-keyboard!))
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
@@ -568,8 +567,7 @@
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))
|
||||
:label (i18n/label :t/view-details)}])))})
|
||||
[react/fast-image {:style {:margin 10 :width 140 :height 140}
|
||||
;;TODO (perf) move to event
|
||||
:source {:uri (contenthash/url (-> content :sticker :hash))}}]]
|
||||
:source {:uri (str (-> content :sticker :url) "&download=true")}}]]
|
||||
reaction-picker]))
|
||||
|
||||
(defmethod ->message constants/content-type-image
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.stickers.core :as stickers]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.screens.chat.stickers.styles :as styles]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.utils.debounce :as debounce]))
|
||||
|
||||
(def icon-size 28)
|
||||
@@ -26,25 +24,23 @@
|
||||
:height 64}]
|
||||
[react/text {:style {:margin-vertical 8 :font-size 17}} (i18n/label :t/you-dont-have-stickers)]
|
||||
[quo/button {:type :secondary
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:stickers/load-packs])
|
||||
(re-frame/dispatch [:navigate-to :stickers]))}
|
||||
:on-press #(re-frame/dispatch [:navigate-to :stickers])}
|
||||
(i18n/label :t/get-stickers)]])
|
||||
|
||||
(defn- stickers-panel [stickers window-width]
|
||||
[react/view {:width window-width :flex 1}
|
||||
[react/scroll-view
|
||||
[react/view {:style styles/stickers-panel}
|
||||
(for [{:keys [hash] :as sticker} stickers]
|
||||
^{:key (str hash)}
|
||||
(for [{:keys [url] :as sticker} stickers]
|
||||
^{:key (str url)}
|
||||
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
|
||||
:on-press #(debounce/dispatch-and-chill [:chat/send-sticker sticker] 1000)}
|
||||
[react/fast-image {:style {:width "100%" :height "100%"}
|
||||
:accessibility-label :sticker-icon
|
||||
:source {:uri (contenthash/url (str "0x" hash))}}]])]]])
|
||||
:source {:uri (str url "&download=true")}}]])]]])
|
||||
|
||||
(defview recent-stickers-panel [window-width]
|
||||
(letsubs [stickers [:stickers/recent]]
|
||||
(letsubs [stickers [:stickers/recent-stickers]]
|
||||
(if (seq stickers)
|
||||
[stickers-panel stickers window-width]
|
||||
[react/view {:style {:flex 1
|
||||
@@ -98,7 +94,7 @@
|
||||
[recent-stickers-panel width]
|
||||
(for [{:keys [stickers id]} installed-packs]
|
||||
^{: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]
|
||||
:or {on-press #(re-frame/dispatch [:stickers/select-pack id])}}
|
||||
@@ -118,7 +114,7 @@
|
||||
|
||||
(defview stickers-view []
|
||||
(letsubs [selected-pack [:stickers/selected-pack]
|
||||
installed-packs [:stickers/installed-packs-vals]]
|
||||
installed-packs [:stickers/installed-packs]]
|
||||
[react/view {:style {:background-color colors/white
|
||||
:flex 1}}
|
||||
(cond
|
||||
@@ -126,9 +122,7 @@
|
||||
(not (seq installed-packs)) [no-stickers-yet-panel]
|
||||
:else [stickers-paging-panel installed-packs selected-pack])
|
||||
[react/view {:style {:flex-direction :row :padding-horizontal 4}}
|
||||
[pack-icon {:on-press #(do
|
||||
(re-frame/dispatch [:stickers/load-packs])
|
||||
(re-frame/dispatch [:navigate-to :stickers]))
|
||||
[pack-icon {:on-press #(re-frame/dispatch [:navigate-to :stickers])
|
||||
:selected? false :background-color colors/blue}
|
||||
[icons/icon :main-icons/add {:width 20 :height 20 :color colors/white-persist}]]
|
||||
[react/view {:width 2}]
|
||||
@@ -140,9 +134,9 @@
|
||||
:width 44
|
||||
:height 44}]]
|
||||
(for [{:keys [id thumbnail]} installed-packs]
|
||||
^{:key id}
|
||||
^{:key (str "pack-icon" id)}
|
||||
[pack-icon {:id id
|
||||
:background-color colors/white}
|
||||
[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]]]]]))
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
:accessibility-label :appearance-settings-button
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :quo2-preview])}])
|
||||
;; :on-press #(re-frame/dispatch [:init-root-nav2 :home-stack])}])
|
||||
[quo/list-item
|
||||
{:icon :main-icons/appearance
|
||||
:title (i18n/label :t/appearance)
|
||||
|
||||
@@ -121,7 +121,9 @@
|
||||
[status-im.ui.screens.wallet.recipient.views :as recipient]
|
||||
[status-im.ui.screens.wallet.send.views :as wallet.send]
|
||||
[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]))
|
||||
|
||||
(def components
|
||||
@@ -229,6 +231,7 @@
|
||||
:rightButtons (right-button-options :chat :more)}}
|
||||
:right-handler chat/topbar-button
|
||||
:component chat/chat}
|
||||
;; :component #(stack-with-switcher/overlap-stack chat/chat :chat)}
|
||||
|
||||
;Pinned messages
|
||||
{:name :chat-pinned-messages
|
||||
@@ -914,5 +917,7 @@
|
||||
quo.preview/main-screens)
|
||||
(when config/quo-preview-enabled?
|
||||
quo2.preview/screens)
|
||||
(when config/quo-preview-enabled?
|
||||
navigation2.screens/screens)
|
||||
(when config/quo-preview-enabled?
|
||||
quo2.preview/main-screens)))
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.components.tabs :as tabs]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||
[status-im.chat.models.reactions :as models.reactions]
|
||||
[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 :status (i18n/label :t/my-status) (= tab :status)]]))
|
||||
|
||||
(def image-hash "e3010170122080c27fe972a95dbb4b0ead029d2c73d18610e849fac197e91068a918755e21b2")
|
||||
|
||||
(defn timeline []
|
||||
(let [messages @(re-frame/subscribe [:chats/timeline-messages-stream])
|
||||
loading-messages? @(re-frame/subscribe [:chats/loading-messages? constants/timeline-chat-id])
|
||||
@@ -191,10 +188,10 @@
|
||||
(if no-messages?
|
||||
[react/view {:padding-horizontal 32
|
||||
:margin-top 64}
|
||||
[react/image {:style {:width 140
|
||||
:height 140
|
||||
:align-self :center}
|
||||
:source {:uri (contenthash/url image-hash)}}]
|
||||
[react/fast-image {:style {:width 140
|
||||
:height 140
|
||||
:align-self :center}
|
||||
:source {:uri "https://bafybeieayj76s4vjlw5uwdvnakosy46rqyioqsp2ygl6sedivemhkxrbwi.ipfs.cf-ipfs.com"}}]
|
||||
[react/view (styles/descr-container)
|
||||
[react/text {:style {:color colors/gray
|
||||
:line-height 22}}
|
||||
|
||||
@@ -5,54 +5,56 @@
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
[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]]))
|
||||
|
||||
(defn cache [url]
|
||||
(str url "&download=true"))
|
||||
|
||||
(defn- thumbnail-icon [uri size]
|
||||
[react/fast-image {:style {:width size :height size :border-radius (/ size 2)}
|
||||
:source {:uri uri}}])
|
||||
:source {:uri (cache uri)}}])
|
||||
|
||||
(defn- installed-icon []
|
||||
[react/view styles/installed-icon
|
||||
[icons/icon :main-icons/check {:color colors/white-persist :height 20 :width 20}]])
|
||||
(defn price-badge [_]
|
||||
(let [chain (<sub [:ethereum/chain-keyword])
|
||||
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]
|
||||
(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]}]
|
||||
(defn pack-badge [{:keys [name author thumbnail preview id] :as pack}]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack {:id id}])}
|
||||
[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}
|
||||
[thumbnail-icon (contenthash/url thumbnail) 40]
|
||||
[thumbnail-icon thumbnail 40]
|
||||
[react/view {:padding-horizontal 16 :flex 1}
|
||||
[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]]
|
||||
(if installed
|
||||
[installed-icon]
|
||||
[price-badge price id owned pending])]]])
|
||||
[price-badge pack]]]])
|
||||
|
||||
(defview packs []
|
||||
(letsubs [packs [:stickers/all-packs]]
|
||||
@@ -70,28 +72,25 @@
|
||||
(def sticker-icon-size 60)
|
||||
|
||||
(defview pack-main []
|
||||
(letsubs [{:keys [id name author price thumbnail
|
||||
stickers installed owned pending]
|
||||
:as pack}
|
||||
(letsubs [{:keys [name author thumbnail stickers]
|
||||
:as pack}
|
||||
[:stickers/get-current-pack]]
|
||||
[react/keyboard-avoiding-view {:flex 1}
|
||||
(if pack
|
||||
[react/view {:flex 1}
|
||||
[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/text {:style {:typography :header}} name]
|
||||
[react/text {:style {:color colors/gray :margin-top 6}} author]]
|
||||
(if installed
|
||||
[installed-icon]
|
||||
[price-badge price id owned pending])]
|
||||
[price-badge pack]]
|
||||
[react/view {:style {:padding-top 8 :flex 1}}
|
||||
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
|
||||
[react/view {:flex-direction :row :flex-wrap :wrap}
|
||||
(for [{:keys [hash]} stickers]
|
||||
^{:key hash}
|
||||
[react/fast-image {:style (styles/sticker-image sticker-icon-size)
|
||||
:source {:uri (contenthash/url hash)}}])]]]]
|
||||
(for [{:keys [url]} stickers]
|
||||
^{:key url}
|
||||
[react/fast-image {:style (styles/sticker-image sticker-icon-size)
|
||||
:source {:uri (cache url)}}])]]]]
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/activity-indicator {:animating true}]])]))
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
|
||||
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||
(def stickers-test-enabled? (enabled? (get-config :STICKERS_TEST_ENABLED "0")))
|
||||
|
||||
;; CONFIG VALUES
|
||||
(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]
|
||||
(.greaterThan ^js bn1 bn2))
|
||||
|
||||
(defn equal-to
|
||||
[bn1 bn2]
|
||||
(.eq ^js bn1 bn2))
|
||||
|
||||
(defn sub [bn1 bn2]
|
||||
(.sub ^js bn1 bn2))
|
||||
|
||||
|
||||
@@ -1,45 +1,21 @@
|
||||
(ns status-im.utils.prices
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.types :as types]))
|
||||
(:require [status-im.ethereum.json-rpc :as json-rpc]))
|
||||
|
||||
;; Responsible for interacting with Cryptocompare API to get current prices for
|
||||
;; 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.
|
||||
(defn- format-price-resp [resp to mainnet?]
|
||||
(if mainnet?
|
||||
(when-let [RAW (:RAW (types/json->clj resp))]
|
||||
(into {} (for [[from entries] RAW]
|
||||
{from (into {} (for [[to entry] entries]
|
||||
{to {:from (name from)
|
||||
:to (name to)
|
||||
:price (:PRICE entry)
|
||||
:last-day (:OPEN24HOUR entry)}}))})))
|
||||
(into {} (for [[_ entries] (:RAW (types/json->clj resp))]
|
||||
{:ETH (into {} (for [[to entry] entries]
|
||||
{to {:from "ETH"
|
||||
:to (name to)
|
||||
:price (:PRICE entry)
|
||||
:last-day (:OPEN24HOUR entry)}}))}))))
|
||||
(when (seq resp)
|
||||
(into {} (for [[from price] resp]
|
||||
{from {(keyword to) {:from (name from)
|
||||
:to to
|
||||
:price price}}})))
|
||||
{:ETH (into {} (for [[_ price] resp]
|
||||
{(keyword to) {:from "ETH"
|
||||
:to to
|
||||
:price price}}))}))
|
||||
|
||||
(defn get-prices [from to mainnet? on-success on-error]
|
||||
(http/get
|
||||
(gen-price-url from to)
|
||||
(fn [resp] (on-success (format-price-resp resp mainnet?)))
|
||||
on-error))
|
||||
(let [to (first to)]
|
||||
(json-rpc/call {:method "wallet_fetchPrices"
|
||||
:params [from to]
|
||||
: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>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.98.5",
|
||||
"commit-sha1": "640793fe85d9a9eef9eb3712cda1c5a1ceea401a",
|
||||
"src-sha256": "1k1iw69yw23k29y0b1yvnggjqlmfnwavk4mq1sf2h3wrlb8x47kd"
|
||||
"version": "v0.98.6",
|
||||
"commit-sha1": "0048aaebcc7859a6f0dd7cdf0266fe029f3066fc",
|
||||
"src-sha256": "1px3ddfbpnlqyzkbp8v4bb8dh5f69cx4lwif8vspw60rr4gpppys"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import json
|
||||
import requests
|
||||
import logging
|
||||
import itertools
|
||||
import emoji
|
||||
import base64
|
||||
from os import environ
|
||||
from support.base_test_report import BaseTestReport
|
||||
from sys import argv
|
||||
import itertools
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
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):
|
||||
@@ -114,11 +117,16 @@ class TestrailReport(BaseTestReport):
|
||||
test_cases['pr']['1_1_chat_commands'] = 50825
|
||||
test_cases['pr']['ens'] = 50827
|
||||
test_cases['pr']['sync'] = 50834
|
||||
test_cases['pr']['browser'] = 50812
|
||||
## Nightly e2e
|
||||
test_cases['nightly']['medium'] = 736
|
||||
test_cases['nightly']['chat'] = 50811
|
||||
test_cases['nightly']['browser'] = 50826
|
||||
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
|
||||
test_cases['upgrade']['general'] = 881
|
||||
|
||||
@@ -146,10 +154,11 @@ class TestrailReport(BaseTestReport):
|
||||
return case_ids
|
||||
|
||||
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"
|
||||
devices = str()
|
||||
method = 'add_result_for_case/%s/%s' % (self.run_id, test.testrail_case_id)
|
||||
last_testrun = test.testruns[-1]
|
||||
for step in last_testrun.steps:
|
||||
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
|
||||
else:
|
||||
comment += devices + test_steps
|
||||
data = {'status_id': self.outcomes['undefined_fail'] if last_testrun.error else self.outcomes['passed'],
|
||||
'comment': comment}
|
||||
result = self.post(method, data=data)
|
||||
try:
|
||||
result_id = result['id']
|
||||
except KeyError:
|
||||
result_id = ''
|
||||
print("Got TestRail error when adding results for case %s: \n%s" % (test.testrail_case_id, result))
|
||||
data.append(
|
||||
{'case_id': test.testrail_case_id,
|
||||
'status_id': self.outcomes['undefined_fail'] if last_testrun.error else self.outcomes['passed'],
|
||||
'comment': comment})
|
||||
|
||||
results = self.post('add_results_for_cases/%s' % self.run_id, data={"results": data})
|
||||
try:
|
||||
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:
|
||||
try:
|
||||
for geth in test.geth_paths.keys():
|
||||
self.add_attachment(method='add_attachment_to_result/%s' % str(result_id),
|
||||
path=test.geth_paths[geth])
|
||||
except AttributeError:
|
||||
pass
|
||||
device = list(last_testrun.jobs.keys())[0]
|
||||
except IndexError:
|
||||
continue
|
||||
for res in results:
|
||||
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()
|
||||
|
||||
def change_test_run_description(self):
|
||||
|
||||
@@ -81,7 +81,7 @@ def get_capabilities_sauce_lab():
|
||||
desired_caps['deviceName'] = 'Android GoogleAPI Emulator'
|
||||
desired_caps['deviceOrientation'] = "portrait"
|
||||
desired_caps['commandTimeout'] = 600
|
||||
desired_caps['idleTimeout'] = 800
|
||||
desired_caps['idleTimeout'] = 1000
|
||||
desired_caps['unicodeKeyboard'] = True
|
||||
desired_caps['automationName'] = 'UiAutomator2'
|
||||
desired_caps['setWebContentDebuggingEnabled'] = True
|
||||
|
||||
@@ -216,6 +216,16 @@ def should_save_device_stats(config):
|
||||
def pytest_runtest_makereport(item, call):
|
||||
outcome = yield
|
||||
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':
|
||||
is_sauce_env = item.config.getoption('env') == 'sauce'
|
||||
current_test = test_suite_data.current_test
|
||||
|
||||
@@ -219,14 +219,62 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||
cls.home_1 = cls.device_1.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.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_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.chat_1 = cls.home_1.add_contact(cls.public_key_2)
|
||||
cls.chat_1.send_message('hey')
|
||||
cls.home_2.home_button.double_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)
|
||||
def test_1_1_chat_message_reaction(self):
|
||||
message_from_sender = "Message sender"
|
||||
@@ -238,6 +286,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||
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.home_2.get_chat(self.default_username_1).click()
|
||||
message_receiver = self.chat_2.chat_element_by_text(message_from_sender)
|
||||
if message_receiver.emojis_below_message(own=False) != 1:
|
||||
self.errors.append("Counter of reaction is not updated on received message!")
|
||||
@@ -527,7 +576,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||
self.chat_2.share_via_messenger()
|
||||
if not self.chat_2.image_in_android_messenger.is_element_present():
|
||||
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.show_images_button.click()
|
||||
self.chat_2.allow_button.wait_and_click()
|
||||
@@ -539,6 +588,7 @@ class TestOneToOneChatMultipleSharedDevices(MultipleSharedDeviceTestCase):
|
||||
|
||||
@marks.testrail_id(5310)
|
||||
def test_1_1_chat_is_shown_message_sent_delivered_from_offline(self):
|
||||
|
||||
self.home_1.home_button.click()
|
||||
self.home_2.home_button.click()
|
||||
|
||||
@@ -1007,6 +1057,7 @@ class TestEnsStickersMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
||||
send_transaction.ok_got_it_button.click()
|
||||
send_transaction.sign_transaction()
|
||||
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)
|
||||
chat_1_sender_message.transaction_status.wait_for_element_text(chat_1_sender_message.confirmed)
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
for key in cls.drivers:
|
||||
sign_in = SignInView(cls.drivers[key])
|
||||
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)
|
||||
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.homes[0].just_fyi('Admin adds future members to contacts')
|
||||
@@ -42,6 +44,7 @@ class TestGroupChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
@marks.testrail_id(3994)
|
||||
def test_group_chat_push_system_messages_when_invited(self):
|
||||
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].open_notification_bar()
|
||||
pns = [self.chats[0].pn_invited_to_group_chat(self.usernames[0], self.chat_name),
|
||||
|
||||
@@ -84,8 +84,9 @@ class TestOnboardingOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
wallet.click_system_back_button()
|
||||
|
||||
self.home.just_fyi("Check that can paste wallet address in chat message input")
|
||||
wallet.home_button.double_click()
|
||||
self.home.get_chat('#%s' % self.public_chat_name).click()
|
||||
wallet.home_button.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.paste_text()
|
||||
if self.chat.chat_message_input.text != address:
|
||||
|
||||
@@ -113,6 +113,7 @@ class TestPairingSyncMultipleDevicesMerged(MultipleSharedDeviceTestCase):
|
||||
cls.profile_1.close_button.click()
|
||||
cls.profile_1.home_button.click()
|
||||
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.chat_1 = cls.home_1.add_contact(cls.contact_before_sync['public_key'])
|
||||
|
||||
@@ -38,9 +38,10 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.chat_2.dapp_tab_button.click()
|
||||
sent_time_variants = self.chat_1.convert_device_time_to_chat_timestamp()
|
||||
timestamp = self.chat_1.chat_element_by_text(message).timestamp_on_tap
|
||||
if timestamp not in sent_time_variants:
|
||||
self.errors.append("Timestamp is not shown, expected: '%s', in fact: '%s'" %
|
||||
(sent_time_variants.join(','), timestamp))
|
||||
if sent_time_variants and timestamp:
|
||||
if timestamp not in sent_time_variants:
|
||||
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')
|
||||
for chat in self.chat_1, self.chat_2:
|
||||
chat.verify_message_is_under_today_text(message, self.errors)
|
||||
@@ -50,6 +51,8 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
|
||||
@marks.testrail_id(700734)
|
||||
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"
|
||||
self.chat_1.edit_message_in_chat(message_before_edit, message_after_edit)
|
||||
for chat in (self.chat_1, self.chat_2):
|
||||
@@ -418,8 +421,8 @@ class TestPublicChatBrowserOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
|
||||
self.home.just_fyi('Delete one tab')
|
||||
web_page.remove_tab(name=urls['bbc.com'])
|
||||
if web_page.element_by_text_part(urls['bbc.com']).is_element_displayed():
|
||||
self.errors.append('Closed tab is present after deletion')
|
||||
web_page.open_tabs_button.wait_for_invisibility_of_element()
|
||||
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')
|
||||
web_page.close_all_button.click()
|
||||
|
||||
@@ -425,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.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.just_fyi('Check that after creating keycard account balance is 0, not ...')
|
||||
wallet_1 = self.sign_in.wallet_button.click()
|
||||
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)
|
||||
profile_1 = self.sign_in.get_profile_view()
|
||||
profile_1.logout()
|
||||
|
||||
@@ -252,10 +252,9 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@marks.testrail_id(700762)
|
||||
@marks.skip
|
||||
# TODO: skipped due to #13016
|
||||
def test_wallet_add_account_seed_phrase_collectibles_mainnet_rinkeby(self):
|
||||
def test_wallet_add_account_seed_phrase_collectibles_rinkeby_set_as_profile_image(self):
|
||||
user = wallet_users['E']
|
||||
self.wallet.driver.set_network_connection(6)
|
||||
account_seed_collectibles = self.account_seed_collectibles
|
||||
self.wallet.get_back_to_home_view()
|
||||
if not self.wallet.add_account_button.is_element_displayed(3):
|
||||
@@ -280,34 +279,36 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.wallet.account_name_input.send_keys(account_seed_collectibles)
|
||||
self.wallet.add_account_generate_account_button.click()
|
||||
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')
|
||||
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')
|
||||
self.home.just_fyi('Check that collectibles amount is shown on Rinkeby')
|
||||
profile = self.home.profile_button.click()
|
||||
profile.switch_network()
|
||||
profile.switch_network('Rinkeby with upstream RPC')
|
||||
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()
|
||||
self.wallet.element_by_translation_id("display-collectibles").scroll_and_click()
|
||||
collectible_amount = self.wallet.get_collectibles_amount()
|
||||
collectible_amount.wait_for_visibility_of_element(30)
|
||||
if collectible_amount.text != '1':
|
||||
self.errors.append('Wrong number is shown on CK assets: %s' % collectible_amount.text)
|
||||
# Workaround for situation when after switching network from Ropsten collectibles are not shown
|
||||
self.wallet.pull_to_refresh(5)
|
||||
if self.wallet.element_by_translation_id("no-collectibles").is_element_displayed():
|
||||
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')
|
||||
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):
|
||||
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.set_collectible_as_profile_photo_button.scroll_and_click()
|
||||
|
||||
@@ -316,47 +317,21 @@ class TestWalletManagementDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.wallet.view_collectible_on_opensea_button.click_until_presence_of_element(
|
||||
web_view.browser_previous_page_button)
|
||||
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.wallet.wallet_button.click()
|
||||
|
||||
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.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.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.profile_button.double_click()
|
||||
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.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()
|
||||
|
||||
@marks.testrail_id(700766)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import random
|
||||
import time
|
||||
from time import sleep
|
||||
import emoji
|
||||
import pytest
|
||||
|
||||
from tests import marks
|
||||
from tests.users import ens_user
|
||||
from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase
|
||||
from views.sign_in_view import SignInView
|
||||
|
||||
@@ -82,6 +84,7 @@ class TestPublicChatMultipleDeviceMergedMedium(MultipleSharedDeviceTestCase):
|
||||
chat_2.add_to_contacts.click()
|
||||
timeline_2 = chat_2.status_button.click()
|
||||
for status in statuses:
|
||||
chat_2.element_by_text_part(statuses['*formatted text*']).scroll_to_element()
|
||||
expected_value = statuses[status]
|
||||
if not timeline_2.element_by_text_part(expected_value).is_element_displayed():
|
||||
self.errors.append(
|
||||
@@ -94,8 +97,7 @@ class TestPublicChatMultipleDeviceMergedMedium(MultipleSharedDeviceTestCase):
|
||||
tag_status = '#public-chat-to-redirect-long-name'
|
||||
timeline_1.set_new_status(tag_status)
|
||||
public_chat_2 = self.home_2.get_chat_view()
|
||||
|
||||
public_chat_2.element_by_text(tag_status).wait_and_click()
|
||||
public_chat_2.element_by_text(tag_status).scroll_and_click('up')
|
||||
public_chat_2.user_name_text.wait_for_element(30)
|
||||
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')
|
||||
@@ -173,9 +175,76 @@ class TestChatMultipleDevice(MultipleSharedDeviceTestCase):
|
||||
|
||||
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)
|
||||
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
|
||||
def navigate_to_start_state_of_both_devices():
|
||||
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.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)
|
||||
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.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()
|
||||
|
||||
@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.flaky
|
||||
def test_community_creating_accept_membership(self):
|
||||
@@ -706,268 +591,6 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
||||
|
||||
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)
|
||||
# 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):
|
||||
@@ -1468,7 +1091,7 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
||||
|
||||
@marks.testrail_id(695856)
|
||||
# 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)
|
||||
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
|
||||
home_1 = device_1.create_user()
|
||||
@@ -1585,9 +1208,11 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
||||
recovery_phrase = profile_1.get_recovery_phrase()
|
||||
profile_1.close_button.click()
|
||||
profile_1.home_button.click()
|
||||
device_2.put_app_to_background_and_back()
|
||||
home_3 = device_3.create_user()
|
||||
public_key_3, username_3 = home_3.get_public_key_and_username(return_username=True)
|
||||
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'
|
||||
home_2 = device_2.recover_access(passphrase=' '.join(recovery_phrase.values()))
|
||||
|
||||
|
||||
@@ -16,200 +16,6 @@ from views.sign_in_view import SignInView
|
||||
|
||||
@marks.medium
|
||||
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)
|
||||
# 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():
|
||||
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)
|
||||
# TODO: merge with other 1-driver medium e2e
|
||||
def test_permissions_deny_access_camera_and_gallery(self):
|
||||
@@ -892,7 +596,7 @@ class TestChatManagement(SingleDeviceTestCase):
|
||||
wallet.click_system_back_button()
|
||||
|
||||
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)
|
||||
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)
|
||||
@@ -1151,6 +855,7 @@ class TestChatManagement(SingleDeviceTestCase):
|
||||
home.just_fyi("Checking setting pairing with new PIN")
|
||||
profile.change_pairing_code_button.click()
|
||||
keycard.enter_another_pin()
|
||||
sign_in.create_password_input.wait_for_element()
|
||||
sign_in.create_password_input.set_value(common_password)
|
||||
sign_in.confirm_your_password_input.set_value(common_password + "1")
|
||||
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():
|
||||
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')
|
||||
with open(file_path, 'r') as f:
|
||||
data = f.read()
|
||||
|
||||
@@ -346,6 +346,21 @@ class BaseView(object):
|
||||
for _ in range(times):
|
||||
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):
|
||||
self.driver.info('Get Status back from Recent apps')
|
||||
self.driver.press_keycode(187)
|
||||
@@ -564,7 +579,8 @@ class BaseView(object):
|
||||
|
||||
def share_via_messenger(self):
|
||||
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.send_as_keyevent('+0100100101')
|
||||
self.confirm()
|
||||
|
||||
@@ -881,7 +881,7 @@ class ChatView(BaseView):
|
||||
self.get_stickers.click()
|
||||
element = Button(self.driver,
|
||||
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.wait_for_invisibility_of_element()
|
||||
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):
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
integrity sha512-hq7nOirgih/zIF9UU9FuYKZ3NGvasu2c/eJesvyPKYiykTtgQZM+mvDwFk/ogEsGwRtTPJBtj8/6IyIFcGa7lw==
|
||||
|
||||
react-native-splash-screen@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45"
|
||||
integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg==
|
||||
react-native-splash-screen@3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.3.0.tgz#3af71ed17afe50fee69590a45aec399d071ead02"
|
||||
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":
|
||||
version "2.5.37"
|
||||
|
||||