Compare commits

..
Author SHA1 Message Date
Richard Ramos 98b0c218b4 status-go: extract node configuration to individual tables 2022-01-07 11:05:31 -04:00
Shivek Khurana eeb8db00f7 🔁 SWAP UI
CLJ Refactor x Hydra are cool. Add modal

Swap UI

Swap token input and gas slider in place

Asset selector sheets

WIP

Selector events

Tabs are back

Hide Swaps behind ff, add cards and modals for advanced settings

Fix lint issues

Signed-off-by: Shivek Khurana <shivek@status.im>
2022-01-05 23:57:51 +05:30
Churikova Tetiana 3499cdc123 e2e: update ci and made first group 2021-12-29 18:02:58 +01:00
Parvesh Monu 44b8a4c0f4 fix community invite link is not resolved (#12956) 2021-12-28 16:38:42 +05:30
Michele Balistreri e45f959c27 support PUK and seed recovery during onboarding
Signed-off-by: Michele Balistreri <michele@bitgamma.com>
2021-12-27 20:35:33 +03:00
Roman Volosovskyi cd86a1065b [#12936] Add accessibility-id to message timestamp 2021-12-27 13:44:21 +02:00
Parvesh Monu ffba396e4d fix distortion of app theme due to change in system theme (#12934) 2021-12-27 15:24:45 +05:30
Du Cheng 961692251c [#12930] Remove public chat references 2021-12-24 21:10:10 +02:00
Parvesh Monu 94fde74b88 Reorder community chats and categories using drag and drop (#12854) 2021-12-24 21:04:44 +05:30
Roman Volosovskyi 5402c217df [#12913] Properly handle syncing of pubchat delition/installation after offline 2021-12-24 17:03:34 +02:00
Parvesh Monu 4588dafe02 Open user profile from membership requests (#12950) 2021-12-24 20:27:30 +05:30
Parvesh Monu edbb06a7c3 Add community members to mentionable list (#12926) 2021-12-24 20:25:00 +05:30
Roman Volosovskyi 29a7e4dc1c [#12918] Show history gaps only in public chats and communities 2021-12-24 13:40:01 +02:00
Roman Volosovskyi de3c08ba18 Add sync history for 2 mins option for testing purposes 2021-12-21 21:42:42 +02:00
Churikova Tetiana e5ff46fdd5 e2e: fixes
Signed-off-by: Churikova Tetiana <churikova.tm@gmail.com>
2021-12-21 14:58:41 +01:00
78 changed files with 1331 additions and 543 deletions
+2
View File
@@ -32,3 +32,5 @@ METRICS_ENABLED=0
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
COMMANDS_ENABLED=1
TWO_MINUTES_SYNCING=1
SWAP_ENABLED=1
+1
View File
@@ -33,3 +33,4 @@ COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
DELETE_MESSAGE_ENABLED=1
TWO_MINUTES_SYNCING=1
+1
View File
@@ -35,3 +35,4 @@ COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
DELETE_MESSAGE_ENABLED=1
TWO_MINUTES_SYNCING=1
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="alert_text">#ffffff</color>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="alert_text">#000000</color>
</resources>
@@ -8,6 +8,7 @@
<item name="android:forceDarkAllowed">true</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:statusBarColor">?attr/backgroundColor</item>
<item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>
<style name="LightTheme" parent="AppTheme">
@@ -21,4 +22,9 @@
<item name="backgroundColor">#000000</item>
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="AlertDialogTheme" parent="Base.Theme.AppCompat.Light.Dialog.Alert">
<item name="android:textColor">@color/alert_text</item>
<item name="android:textColorPrimary">@color/alert_text</item>
</style>
</resources>
+7 -7
View File
@@ -3,15 +3,15 @@ pipeline {
agent { label 'linux' }
parameters {
string(
name: 'NETWORK',
description: 'Name of test network to use.',
defaultValue: 'ropsten',
)
string(
name: 'APK_NAME',
description: 'Filename of APK uploaded to SauceLabs.',
)
string(
name: 'KEYWORD_EXPRESSION',
description: 'This will run tests which contain names that match the given string expression (Optional)',
defaultValue: '',
)
}
options {
@@ -56,8 +56,8 @@ pipeline {
--rerun_count=2 \
--testrail_report=True \
-m testrail_id \
-m "not upgrade" \
--network=${params.NETWORK} \
-m \"not upgrade\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_NAME}
"""
}
+9 -9
View File
@@ -8,15 +8,10 @@ pipeline {
description: 'Name of the branch to checkout and build.',
defaultValue: 'develop',
)
string(
name: 'NETWORK',
description: 'Name of test network to use.',
defaultValue: 'ropsten',
)
string(
name: 'TEST_MARKERS',
description: 'Marker expression for matching tests to run.',
defaultValue: 'critical or high',
defaultValue: '',
)
string(
name: 'APK_NAME',
@@ -26,9 +21,14 @@ pipeline {
name: 'PR_ID',
description: 'ID of the Pull Request triggering this build.',
)
string(
name: 'KEYWORD_EXPRESSION',
description: 'This will run tests which contain names that match the given string expression (Optional)',
defaultValue: '',
)
string(
name: 'TR_CASE_IDS',
description: 'IDs of the TestRail case, separated by a comma. (Optional)',
description: 'IDs of the TestRail case, separated by a comma (Optional)',
defaultValue: '',
)
}
@@ -91,8 +91,8 @@ pipeline {
--numprocesses 15 \
--rerun_count=2 \
--testrail_report=True \
-m "${params.TEST_MARKERS}" \
--network=${params.NETWORK} \
-m \"${params.TEST_MARKERS}\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_NAME} \
--build=PR-${params.PR_ID} \
--pr_number=${params.PR_ID} \
+21 -10
View File
@@ -3,11 +3,6 @@ pipeline {
agent { label 'linux' }
parameters {
string(
name: 'NETWORK',
description: 'Name of test network to use',
defaultValue: 'ropsten',
)
string(
name: 'APK_NAME',
description: 'Filename of APK uploaded to SauceLabs (base for upgrade, usually release build)',
@@ -16,6 +11,16 @@ pipeline {
name: 'APK_NAME_UPGRADE',
description: 'Filename of APK of upgraded application (installed on top of base)',
)
string(
name: 'KEYWORD_EXPRESSION',
description: 'This will run tests which contain names that match the given string expression (Optional)',
defaultValue: '',
)
string(
name: 'TR_CASE_IDS',
description: 'IDs of the TestRail case, separated by a comma (Optional)',
defaultValue: '',
)
}
options {
@@ -32,7 +37,12 @@ pipeline {
} }
}
stage('Test') {
steps {
steps { script {
/* for managing optional arguments */
def extraPytestOpts = ''
if (params.TR_CASE_IDS != '') {
extraPytestOpts = "--run_testrail_ids='${params.TR_CASE_IDS}'"
}
withCredentials([
usernamePassword(
credentialsId: 'test-rail-api',
@@ -56,18 +66,19 @@ pipeline {
dir('test/appium/tests') {
sh """
python3 -m pytest \
-m upgrade \
-m "upgrade" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--numprocesses 15 \
--rerun_count=2 \
--testrail_report=True \
--network=${params.NETWORK} \
--apk=${params.APK_NAME} \
--apk_upgrade=${params.APK_NAME_UPGRADE}
--apk_upgrade=${params.APK_NAME_UPGRADE} \
${extraPytestOpts}
"""
}
}
}
}
} }
}
post {
+5 -1
View File
@@ -163,4 +163,8 @@ used for some abi encoding primitives
## "rn-emoji-keyboard": "https://github.com/status-im/rn-emoji-keyboard"
Used for taking emoji input, for custom emoji thumbnails for community channels
Used for taking emoji input, for custom emoji thumbnails for community channels
## "react-native-draggable-flatlist": "https://github.com/computerjazz/react-native-draggable-flatlist"
A drag-and-drop-enabled FlatList component for React Native
+3 -3
View File
@@ -230,7 +230,7 @@ PODS:
- React
- react-native-status (1.0.0):
- React
- react-native-status-keycard (2.5.36):
- react-native-status-keycard (2.5.37):
- Keycard
- React
- react-native-webview (11.3.0):
@@ -626,7 +626,7 @@ SPEC CHECKSUMS:
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 5bc68409594b19a3e5c5cbced7b1ecf61053b709
glog: 61334f8bdb4deea07543d4fbac3fb5948e78a7a5
Keycard: dd96182888da0aacf4de821b641103143bbb26cc
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
@@ -653,7 +653,7 @@ SPEC CHECKSUMS:
react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-status: 45dbf1302ce3c258b459dfab137cd1c2c68c295d
react-native-status-keycard: eb84554a23315510948613a9467e7e3481be340c
react-native-status-keycard: 961d01ca190889ddf220206822fd752f8f4f3f7a
react-native-webview: af9990b21a9aeafa8e8347746eb4116c0de086af
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
+1
View File
@@ -39,6 +39,7 @@
"react-native-dark-mode": "^0.2.2",
"react-native-device-info": "^7.4.0",
"react-native-dialogs": "^1.0.4",
"react-native-draggable-flatlist": "^3.0.3",
"react-native-fast-image": "8.5.11",
"react-native-fetch-polyfill": "^1.1.2",
"react-native-fs": "^2.14.1",
Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

+4
View File
@@ -206,6 +206,9 @@
(def rn-emoji-keyboard
#js {:EmojiKeyboard #js {}})
(def react-native-draggable-flatlist
#js {:default #js {}})
;; Update i18n_resources.cljs
(defn mock [module]
(case module
@@ -239,6 +242,7 @@
"@react-native-community/push-notification-ios" push-notification-ios
"react-native-camera-kit" react-native-camera-kit
"rn-emoji-keyboard" rn-emoji-keyboard
"react-native-draggable-flatlist" react-native-draggable-flatlist
"./fleets.js" default-fleets
"./chats.js" default-chats
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
+14 -12
View File
@@ -55,13 +55,13 @@
:small :base
:large))
(defn container [{:keys [size]} & children]
(defn container [{:keys [size container-style]} & children]
(into [rn/view {:style (merge (:tiny spacing/padding-horizontal)
{:min-height (size->container-size size)
:padding-vertical 8
:flex-direction :row
:align-items :center
:justify-content :space-between})}]
:justify-content :space-between} container-style)}]
children))
(defn icon-column
@@ -197,17 +197,19 @@
left-side-alignment icon-color icon-bg-color
title subtitle subtitle-secondary active on-press on-long-press chevron size text-size
accessory-text accessibility-label title-accessibility-label accessory-style
haptic-feedback haptic-type error animated animated-accessory? title-text-weight]
:or {subtitle-max-lines 1
theme :main
haptic-feedback true
animated platform/ios?
haptic-type :selection}}]
haptic-feedback haptic-type error animated animated-accessory? title-text-weight container-style
active-background-enabled]
:or {subtitle-max-lines 1
theme :main
haptic-feedback true
animated platform/ios?
active-background-enabled true
haptic-type :selection}}]
(let [theme (if disabled :disabled theme)
{:keys [text-color active-background passive-background]}
(themes theme)
icon-color (or icon-color (:icon-color (themes theme)))
icon-bg-color (or icon-bg-color (:icon-bg-color (themes theme)))
icon-color (or icon-color (:icon-color (themes theme)))
icon-bg-color (or icon-bg-color (:icon-bg-color (themes theme)))
optional-haptic (fn []
(when haptic-feedback
(haptic/trigger haptic-type)))
@@ -223,7 +225,7 @@
[component
(merge {:type :list-item
:disabled disabled
:bg-color active-background
:bg-color (when active-background-enabled active-background)
:accessibility-label accessibility-label}
(when on-press
{:on-press (fn []
@@ -233,7 +235,7 @@
{:on-long-press (fn []
(optional-haptic)
(on-long-press))}))
[container {:size size}
[container {:size size :container-style container-style}
[left-side {:icon-color icon-color
:text-color (if on-press
text-color
+23 -10
View File
@@ -5,7 +5,10 @@
["react-native" :as rn]
["@react-native-community/hooks" :as hooks]
["react-native-navigation" :refer (Navigation)]
["rn-emoji-keyboard" :refer (EmojiKeyboard)]))
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
["react-native-draggable-flatlist" :default DraggableFlatList]))
(def rn-draggable-flatlist (reagent/adapt-react-class DraggableFlatList))
(def emoji-keyboard (reagent/adapt-react-class EmojiKeyboard))
@@ -107,7 +110,13 @@
(defn- wrap-render-fn [f render-data]
(fn [data]
(reagent/as-element [f (.-item ^js data) (.-index ^js data) (.-separators ^js data) render-data])))
(reagent/as-element [f (.-item ^js data) (.-index ^js data)
(.-separators ^js data) render-data
(.-isActive ^js data) (.-drag ^js data)])))
(defn- wrap-on-drag-end-fn [f]
(fn [data]
(f (.-from ^js data) (.-to ^js data) (.-data ^js data))))
(defn- wrap-key-fn [f]
(fn [data index]
@@ -115,19 +124,23 @@
(f data index)))
(defn base-list-props
[{:keys [key-fn render-fn empty-component header footer separator data render-data] :as props}]
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn] :as props}]
(merge {:data (to-array data)}
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
(when header {:ListHeaderComponent (reagent/as-element header)})
(when footer {:ListFooterComponent (reagent/as-element footer)})
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn)))
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
(when header {:ListHeaderComponent (reagent/as-element header)})
(when footer {:ListFooterComponent (reagent/as-element footer)})
(when on-drag-end-fn {:onDragEnd (wrap-on-drag-end-fn on-drag-end-fn)})
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn :on-drag-end-fn)))
(defn flat-list [props]
[rn-flat-list (base-list-props props)])
(defn draggable-flat-list [props]
[rn-draggable-flatlist (base-list-props props)])
(defn animated-flat-list [props]
[animated-flat-list-class (base-list-props props)])
;; Hooks
+5 -4
View File
@@ -42,11 +42,15 @@
[{:keys [db]} community-id]
{:db (community-failed-to-resolve db community-id)})
(defn community-link [id]
(str "https://join.status.im/c/" id))
(fx/defn handle-community-resolved
{:events [::community-resolved]}
[{:keys [db] :as cofx} community-id community]
(fx/merge cofx
{:db (community-resolved db community-id)}
{:db (community-resolved db community-id)
:dispatch [::cache-link-preview-data (community-link community-id) community]}
(models.communities/handle-community community)))
(fx/defn resolve-community-info
@@ -78,9 +82,6 @@
:link-previews-cache
(assoc (get multiaccount :link-previews-cache {}) site data)))
(defn community-link [id]
(str "https://join.status.im/c/" id))
(defn cache-community-preview-data
[{:keys [id] :as community}]
(re-frame/dispatch [::cache-link-preview-data
+54 -19
View File
@@ -9,7 +9,8 @@
[status-im.utils.utils :as utils]
[status-im.native-module.core :as status]
[quo.react-native :as rn]
[quo.react :as react]))
[quo.react :as react]
[status-im.multiaccounts.core :as multiaccounts]))
(def at-sign "@")
@@ -170,11 +171,55 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn add-searchable-phrases
[{:keys [alias name nickname] :as user}]
(reduce
(fn [user s]
(if (nil? s)
user
(let [new-words (concat
[s]
(rest (string/split s " ")))]
(update user :searchable-phrases (fnil concat []) new-words))))
user
[alias name nickname]))
(defn add-searchable-phrases-to-contact
[{:keys [alias name added? blocked? identicon public-key nickname]} community-chat?]
(when (and alias
(not (string/blank? alias))
(or name
nickname
added?
community-chat?)
(not blocked?))
(add-searchable-phrases
{:alias alias
:name (or (utils/safe-replace name ".stateofus.eth" "") alias)
:identicon identicon
:nickname nickname
:public-key public-key})))
(defn mentionable-commmunity-members [contacts my-public-key community-members]
(reduce (fn [acc identity]
(let [contact (multiaccounts/contact-by-identity
contacts identity)
contact (if (string/blank? (:alias contact))
(assoc contact :alias
(get-in contact [:names :three-words-name]))
contact)
mentionable-contact (add-searchable-phrases-to-contact
contact true)]
(if (nil? mentionable-contact) acc
(assoc acc identity mentionable-contact))))
{}
(keys (dissoc community-members my-public-key))))
(defn get-mentionable-users
[{{:keys [current-chat-id]
:contacts/keys [contacts] :as db} :db}]
(let [{:keys [chat-type users] :as chat}
(get-in db [:chats current-chat-id])
(let [{:keys [chat-type community-id users] :as chat} (get-in db [:chats current-chat-id])
{:keys [name preferred-name public-key]} (:multiaccount db)
chat-specific-suggestions
(cond
(= chat-type constants/private-group-chat-type)
@@ -200,9 +245,12 @@
current-chat-id
(contact.db/public-key->contact contacts current-chat-id))
:else users)
{:keys [name preferred-name public-key]}
(:multiaccount db)]
(= chat-type constants/community-chat-type)
(merge users (mentionable-commmunity-members
contacts public-key
(get-in db [:communities community-id :members])))
:else users)]
(reduce
(fn [acc [key {:keys [alias name identicon]}]]
(let [name (utils/safe-replace name ".stateofus.eth" "")]
@@ -634,19 +682,6 @@
[_ ref cursor]
{::reset-text-input-cursor [ref cursor]})
(defn add-searchable-phrases
[{:keys [alias name nickname] :as user}]
(reduce
(fn [user s]
(if (nil? s)
user
(let [new-words (concat
[s]
(rest (string/split s " ")))]
(update user :searchable-phrases (fnil concat []) new-words))))
user
[alias name nickname]))
(defn is-valid-terminating-character? [c]
(case c
"\t" true ; tab
+26 -3
View File
@@ -288,7 +288,7 @@
(fx/defn edit-channel
{:events [::edit-channel-confirmation-pressed]}
[{:keys [db] :as cofx}]
(let [{:keys [name description color community-id emoji edit-channel-id category-id]}
(let [{:keys [name description color community-id emoji edit-channel-id category-id position]}
(get db :communities/create-channel)]
{::json-rpc/call [{:method "wakuext_editCommunityChat"
:params [community-id
@@ -298,6 +298,7 @@
:color color
:emoji emoji}
:category_id category-id
:position position
:permissions {:access constants/community-channel-access-no-membership}}]
:js-response true
:on-success #(re-frame/dispatch [::community-channel-edited %])
@@ -345,7 +346,7 @@
(fx/defn edit-channel-pressed
{:events [::edit-channel-pressed]}
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id]
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id position]
(let [{:keys [color emoji]} (if (string/blank? emoji)
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)
{:color color :emoji emoji})]
@@ -356,7 +357,8 @@
:community-id community-id
:emoji emoji
:edit-channel-id chat-id
:category-id category-id})}
:category-id category-id
:position position})}
(navigation/open-modal :edit-community-channel nil))))
(fx/defn community-created
@@ -564,6 +566,15 @@
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to remove chat from community" %)}]}))
(fx/defn delete-community-chat
{:events [:delete-community-chat]}
[_ community-id chat-id]
{::json-rpc/call [{:method "wakuext_deleteCommunityChat"
:params [community-id chat-id]
:js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to delete community chat" %)}]})
(fx/defn delete-category
{:events [:delete-community-category]}
[_ community-id category-id]
@@ -592,6 +603,18 @@
(navigation/navigate-back)
(remove-chat-from-category community-id id categoryID))))
(fx/defn reorder-category-chat
{:events [::reorder-community-category-chat]}
[_ community-id category-id chat-id new-position]
{::json-rpc/call [{:method "wakuext_reorderCommunityChat"
:params [{:communityId community-id
:categoryId category-id
:chatId chat-id
:position new-position}]
:js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/error "failed to reorder community category chat" %)}]})
(fx/defn reorder-category
{:events [::reorder-community-category]}
[_ community-id category-id new-position]
+1
View File
@@ -146,6 +146,7 @@
(def ^:const timeline-chat-id "@timeline70bd746ddcc12beb96b2c9d572d0784ab137ffc774f5383e50585a932080b57cca0484b259e61cecbaa33a4c98a300a")
(def ^:const two-mins (* 2 60))
(def ^:const one-day (* 60 60 24))
(def ^:const three-days (* one-day 3))
(def ^:const one-week (* one-day 7))
+1
View File
@@ -165,6 +165,7 @@
"wakuext_reorderCommunityChat" {}
"wakuext_editCommunityCategory" {}
"wakuext_deleteCommunityCategory" {}
"wakuext_deleteCommunityChat" {}
"wakuext_ensVerified" {}
"wakuext_dismissActivityCenterNotifications" {}
"wakuext_acceptActivityCenterNotifications" {}
+32 -5
View File
@@ -6,7 +6,7 @@
[status-im.async-storage.core :as async-storage]
status-im.backup.core
status-im.bootnodes.core
status-im.bottom-sheet.core
[status-im.bottom-sheet.core :as bottom-sheet]
status-im.browser.core
status-im.browser.permissions
[status-im.chat.models :as chat]
@@ -58,7 +58,9 @@
status-im.wallet.accounts.core
status-im.wallet.choose-recipient.core
[status-im.wallet.core :as wallet]
status-im.wallet.custom-tokens.core))
status-im.wallet.custom-tokens.core
[status-im.navigation.core :as navigation.core]
[status-im.multiaccounts.login.core :as login.core]))
(re-frame/reg-fx
:dismiss-keyboard
@@ -112,10 +114,35 @@
(fx/defn system-theme-mode-changed
{:events [:system-theme-mode-changed]}
[{:keys [db]} theme]
(let [cur-theme (get-in db [:multiaccount :appearance])]
[{:keys [db] :as cofx} theme]
(let [cur-theme (get-in db [:multiaccount :appearance])
current-tab (get db :current-tab :chat)
view-id (:view-id db)
screen-params (get-in db [:navigation/screen-params view-id])
root-id @navigation.core/root-id]
(navigation.core/dismiss-all-modals)
(when (or (nil? cur-theme) (zero? cur-theme))
{::multiaccounts/switch-theme (if (= :dark theme) 2 1)})))
(fx/merge cofx
{::multiaccounts/switch-theme (if (= :dark theme) 2 1)
:utils/dispatch-later
(cond-> [{:ms 2000 :dispatch
(if (= view-id :chat)
[:chat.ui/navigate-to-chat (:current-chat-id db)]
[:navigate-to view-id screen-params])}]
(some #(= view-id %) navigation.core/community-screens)
(conj {:ms 1000 :dispatch
[:navigate-to :community
(get-in db [:navigation/screen-params :community])]})
(= view-id :community-emoji-thumbnail-picker)
(conj {:ms 1500 :dispatch
[:navigate-to :create-community-channel
(get-in db [:navigation/screen-params :create-community-channel])]}))}
(bottom-sheet/hide-bottom-sheet)
(navigation/init-root root-id)
(when (= root-id :chat-stack)
(navigation/change-tab current-tab))))))
(def authentication-options
{:reason (i18n/label :t/biometric-auth-reason-login)})
+1 -1
View File
@@ -16,7 +16,7 @@
(fx/merge cofx
{:db (-> db
(assoc-in [:keycard :creating-backup?] backup-type))}
(when-not (:multiaccounts/login db)
(when (:multiaccount db)
(navigation/change-tab :profile))
(navigation/navigate-to-cofx :seed-phrase nil)))
+1 -1
View File
@@ -66,7 +66,7 @@
:error nil
:status nil))
:hide-popover nil})
(when-not (:multiaccounts/login db)
(when (:multiaccount db)
(navigation/change-tab :profile))
(when-not (:multiaccounts/login db)
(if (:popover/popover db)
+8 -2
View File
@@ -217,9 +217,15 @@
:t/keycard-access-reset :t/keycard-backup-success-title))
:content (i18n/label (if (= backup-type :recovery-card)
:t/keycard-can-use-with-new-passcode :t/keycard-backup-success-body))}}
(if (multiaccounts.model/logged-in? cofx)
(cond
(multiaccounts.model/logged-in? cofx)
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])
(return-to-keycard-login))))
(:multiaccounts/login db)
(return-to-keycard-login)
:else
(navigation/set-stack-root :onboarding [:get-your-keys]))))
(re-frame/reg-fx
::finish-migration
@@ -109,12 +109,15 @@
types/json->clj
:error
string/blank?
not)]
not)
onboarding? (not (or (:multiaccounts/login db) (:multiaccount db)))]
(if error?
(popover/show-popover cofx {:view :custom-seed-phrase})
{::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase)
;; Unique key-uid of the account for which we are going to move keys
:key-uid (or (-> db :multiaccounts/login :key-uid) (-> db :multiaccount :key-uid))}})))
:key-uid (or (-> db :multiaccounts/login :key-uid)
(-> db :multiaccount :key-uid)
(and onboarding? (-> db :keycard :application-info :key-uid)))}})))
(fx/defn choose-storage-pressed
{:events [::choose-storage-pressed]}
+37 -7
View File
@@ -1,6 +1,7 @@
(ns status-im.navigation.core
(:require
["react-native" :as rn]
[clojure.set :as clojure.set]
["react-native-gesture-handler" :refer (gestureHandlerRootHOC)]
["react-native-navigation" :refer (Navigation)]
[quo.components.text-input :as quo.text-input]
@@ -157,12 +158,14 @@
(.registerComponentDidDisappearListener
(.events Navigation)
(fn [^js evn]
(when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover"}
(.-componentName evn))
(doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs]
(.setNativeProps ^js ref (clj->js {:text value})))
(doseq [[^js text-input default-value] @react/text-input-refs]
(.setNativeProps text-input (clj->js {:text default-value})))))))
(let [view-id (keyword (.-componentName evn))]
(when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover"}
(.-componentName evn))
(re-frame/dispatch [::view-disappeared view-id])
(doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs]
(.setNativeProps ^js ref (clj->js {:text value})))
(doseq [[^js text-input default-value] @react/text-input-refs]
(.setNativeProps text-input (clj->js {:text default-value}))))))))
;; SET ROOT
(re-frame/reg-fx
@@ -277,7 +280,10 @@
(.registerBottomTabSelectedListener
(.events Navigation)
(fn [^js evn]
(let [comp (get tab-root-ids (.-selectedTabIndex evn))]
(let [selected-tab-index (.-selectedTabIndex evn)
comp (get tab-root-ids selected-tab-index)
tab-key (get (clojure.set/map-invert tab-key-idx) selected-tab-index)]
(re-frame/dispatch [:set :current-tab tab-key])
(when (and platform/android? (= @root-comp-id comp))
(.popToRoot Navigation (name comp)))
(reset! root-comp-id comp)))))
@@ -377,3 +383,27 @@
(log/debug :navigate-replace-fx view-id)
(.pop Navigation (name @root-comp-id))
(navigate view-id)))
(def community-screens '(:community-management
:community-members
:community-requests-to-join
:create-community-channel
:community-emoji-thumbnail-picker
:create-community-category
:community-edit-chats))
;; change view-id if it is still same after component is disappeared
;; https://github.com/wix/react-native-navigation/issues/5744#issuecomment-563226820
(fx/defn view-disappeared
{:events [::view-disappeared]}
[{:keys [db]} view-id]
(when (= view-id (:view-id db))
{:db (assoc db :view-id (cond
(= view-id :community-emoji-thumbnail-picker)
:create-community-channel
(some #(= view-id %) community-screens)
:community
:else
:home))}))
+9 -8
View File
@@ -19,15 +19,16 @@
{:unread-count (get db :activity.center/notifications-count 0)
:notifications (get-in db [:activity.center/notifications :notifications])}
activities)]
{:db (-> db
(assoc-in [:activity.center/notifications :notifications] notifications)
(assoc :activity.center/notifications-count (max 0 unread-count)))
:dispatch (cond
(= (:view-id db) :notifications-center)
[:mark-all-activity-center-notifications-as-read]
(merge
{:db (-> db
(assoc-in [:activity.center/notifications :notifications] notifications)
(assoc :activity.center/notifications-count (max 0 unread-count)))}
(cond
(= (:view-id db) :notifications-center)
{:dispatch [:mark-all-activity-center-notifications-as-read]}
(= (:view-id db) :chat)
[:accept-all-activity-center-notifications-from-chat (:current-chat-id db)])}))
(= (:view-id db) :chat)
{:dispatch [:accept-all-activity-center-notifications-from-chat (:current-chat-id db)]}))))
(fx/defn get-activity-center-notifications-count
{:events [:get-activity-center-notifications-count]}
+37 -24
View File
@@ -34,7 +34,6 @@
[status-im.utils.security :as security]
[status-im.wallet.db :as wallet.db]
[status-im.wallet.utils :as wallet.utils]
[status-im.utils.utils :as utils]
status-im.ui.screens.keycard.subs
[status-im.chat.models.mentions :as mentions]
[status-im.notifications.core :as notifications]
@@ -181,6 +180,12 @@
(reg-root-key-sub :wallet/fetching-collection-assets :wallet/fetching-collection-assets)
(reg-root-key-sub :wallet/collectible-assets :wallet/collectible-assets)
(reg-root-key-sub :wallet/selected-collectible :wallet/selected-collectible)
(reg-root-key-sub :wallet/modal-selecting-source-token? :wallet/modal-selecting-source-token?)
(reg-root-key-sub :wallet/swap-from-token :wallet/swap-from-token)
(reg-root-key-sub :wallet/swap-to-token :wallet/swap-to-token)
(reg-root-key-sub :wallet/swap-from-token-amount :wallet/swap-from-token-amount)
(reg-root-key-sub :wallet/swap-to-token-amount :wallet/swap-to-token-amount)
(reg-root-key-sub :wallet/swap-advanced-mode? :wallet/swap-advanced-mode?)
;;commands
(reg-root-key-sub :commands/select-account :commands/select-account)
@@ -877,6 +882,22 @@
(assoc :color colors/blue))
chats)))))
(re-frame/reg-sub
:chats/sorted-categories-by-community-id
(fn [[_ community-id]]
[(re-frame/subscribe [:chats/by-community-id community-id])
(re-frame/subscribe [:communities/community-chats community-id])])
(fn [[chats comm-chats] [_ community-id]]
(let [chat-cat (into {} (map (fn [{:keys [id categoryID position]}]
{(str community-id id) {:categoryID categoryID
:position position}})
(vals comm-chats)))]
(group-by :categoryID (sort-by :position
(map #(cond-> (merge % (chat-cat (:chat-id %)))
(= community-id constants/status-community-id)
(assoc :color colors/blue))
chats))))))
(re-frame/reg-sub
:chats/category-by-chat-id
(fn [[_ community-id _]]
@@ -903,7 +924,9 @@
:<- [:communities]
(fn [communities [_ id]]
(->> (get-in communities [id :categories])
(sort-by #(:position (get % 1))))))
(map #(assoc (get % 1) :community-id id))
(sort-by :position)
(into []))))
(re-frame/reg-sub
:chats/current-chat-ui-props
@@ -1400,22 +1423,11 @@
:<- [:contacts/contacts]
(fn [contacts]
(reduce
(fn [acc [key {:keys [alias name added? blocked? identicon public-key nickname]}]]
(if (and alias
(not= alias "")
(or name
nickname
added?)
(not blocked?))
(let [name (utils/safe-replace name ".stateofus.eth" "")]
(assoc acc public-key
(mentions/add-searchable-phrases
{:alias alias
:name (or name alias)
:identicon identicon
:nickname nickname
:public-key key})))
acc))
(fn [acc [key contact]]
(let [mentionable-contact (mentions/add-searchable-phrases-to-contact
contact false)]
(if (nil? mentionable-contact) acc
(assoc acc key mentionable-contact))))
{}
contacts)))
@@ -1425,7 +1437,9 @@
:<- [:chats/mentionable-contacts]
:<- [:contacts/blocked-set]
:<- [:multiaccount]
(fn [[{:keys [chat-id users contacts community-id chat-type] :as chat} mentionable-contacts blocked {:keys [name preferred-name public-key]}]]
:<- [:contacts/contacts]
(fn [[{:keys [chat-id users contacts community-id chat-type] :as chat}
mentionable-contacts blocked {:keys [public-key]} my-contacts]]
(let [community-members @(re-frame/subscribe [:communities/community-members
community-id])
contacts-with-one-to-one (if (= chat-type constants/one-to-one-chat-type)
@@ -1436,14 +1450,13 @@
members-left (into #{} (filter #(group-chat/member-removed? chat %) (keys users)))
filtered-contacts (select-keys contacts-with-one-to-one (if (nil? community-id)
(distinct (concat (seq contacts) (keys users) [chat-id]))
(keys community-members)))]
(keys community-members)))
mentionable-commmunity-members (mentions/mentionable-commmunity-members
my-contacts public-key community-members)]
(apply dissoc
(-> users
(merge filtered-contacts)
(assoc public-key (mentions/add-searchable-phrases
{:alias name
:name (or preferred-name name)
:public-key public-key})))
(merge mentionable-commmunity-members))
(conj (concat blocked members-left) public-key)))))
(re-frame/reg-sub
@@ -6,7 +6,8 @@
(defn emoji-thumbnail [emoji color size]
(when-not (string/blank? emoji)
[react/view (styles/emoji-thumbnail-icon color size)
[react/text {:style (styles/emoji-thumbnail-icon-text size)} emoji]]))
[react/text {:style (styles/emoji-thumbnail-icon-text size)
:accessibility-label :thumbnail-emoji} emoji]]))
(defn emoji-thumbnail-touchable [emoji color size func]
(when-not (string/blank? emoji)
@@ -17,7 +17,6 @@
(defn emoji-thumbnail-icon-text [size]
{:font-size (emoji-utils/emoji-font-size size)
:line-height size
:accessibility-label :thumbnail-emoji
:margin-top (emoji-utils/emoji-top-margin-for-vertical-alignment size)}) ;; Required for vertical alignment bug - Check function defination for more info
@@ -86,22 +86,4 @@
:style {:width 160 :height 160}}]]
[react/text {:style {:text-align :center :margin-bottom 16 :line-height 22}}
(i18n/label :t/public-chat-description)]
[chat-name-input topic error]]
[react/view {:margin-top 32}
(for [[section chats] (chat.models/chats)]
^{:key section}
[react/view
[react/view {:margin-right 16 :padding-left 16 :padding-vertical 3
:border-bottom-width 1 :border-bottom-color colors/gray-lighter
:border-top-width 1 :border-top-color colors/gray-lighter
:border-right-width 1 :border-right-color colors/gray-lighter
:border-bottom-right-radius 14 :border-top-right-radius 14}
[quo/text {:weight :medium} section]]
[react/view {:flex-direction :row :flex-wrap :wrap :margin-vertical 8 :padding-horizontal 16}
(let [lang-topic (get-language-topic)
chats (if (and (= section-featured section) lang-topic)
(conj chats lang-topic)
chats)]
(for [chat chats]
^{:key chat}
[render-topic chat]))]])]]))
[chat-name-input topic error]]]))
+21 -20
View File
@@ -12,28 +12,29 @@
(re-frame/dispatch [:chat.ui/fill-gaps chat-id gap-ids])))
(views/defview gap
[{:keys [gap-ids chat-id gap-parameters]}]
[{:keys [gap-ids chat-id gap-parameters public? community?]}]
(views/letsubs [in-progress? [:chats/fetching-gap-in-progress?
gap-ids
chat-id]
connected? [:mailserver/connected?]
first-gap? (= gap-ids #{:first-gap})]
[react/view {:style (style/gap-container)}
[react/touchable-highlight
{:on-press (when (and connected? (not in-progress?))
(on-press chat-id gap-ids))
:style style/touchable}
[react/view {:style style/label-container}
(if in-progress?
[react/activity-indicator]
[react/nested-text
{:style (style/gap-text connected?)}
(i18n/label (if first-gap? :t/load-more-messages :t/fetch-messages))
(when first-gap?
[{:style style/date}
(let [date (datetime/timestamp->long-date
(* 1000 (:from gap-parameters)))]
(str
"\n"
(i18n/label :t/load-messages-before
{:date date})))])])]]]))
(when (or (not first-gap?) public? community?)
[react/view {:style (style/gap-container)}
[react/touchable-highlight
{:on-press (when (and connected? (not in-progress?))
(on-press chat-id gap-ids))
:style style/touchable}
[react/view {:style style/label-container}
(if in-progress?
[react/activity-indicator]
[react/nested-text
{:style (style/gap-text connected?)}
(i18n/label (if first-gap? :t/load-more-messages :t/fetch-messages))
(when first-gap?
[{:style style/date}
(let [date (datetime/timestamp->long-date
(* 1000 (:from gap-parameters)))]
(str
"\n"
(i18n/label :t/load-messages-before
{:date date})))])])]]])))
@@ -80,7 +80,9 @@
(let [anim-opacity (animation/create-value 0)]
[react/animated-view {:style (style/message-timestamp-wrapper message) :opacity anim-opacity}
(when @show-timestamp? (message-timestamp-anim anim-opacity show-timestamp?))
[react/text {:style (style/message-timestamp-text)}
[react/text
{:style (style/message-timestamp-text)
:accessibility-label :message-timestamp}
timestamp-str]])))
(defview quoted-message
+5 -3
View File
@@ -4,11 +4,12 @@
[status-im.ui.screens.chat.styles.photos :as style]
[status-im.profile.db :as profile.db]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.image :as utils.image]))
[status-im.utils.image :as utils.image]
[quo.design-system.colors :as colors]))
(def memo-photo-rend
(memoize
(fn [photo-path size accessibility-label]
(fn [photo-path size accessibility-label _]
(let [identicon? (when photo-path (profile.db/base64-png? photo-path))]
[react/view {:style (style/photo-container size)}
[react/image {:source (utils.image/source photo-path)
@@ -18,8 +19,9 @@
(when identicon?
[react/view {:style (style/photo-border size)}])]))))
;; "(colors/dark?)" is passed to memoized function to avoid previous themes cache
(defn photo [photo-path {:keys [size accessibility-label]}]
[memo-photo-rend photo-path size accessibility-label])
[memo-photo-rend photo-path size accessibility-label (colors/dark?)])
;; We optionally pass identicon for perfomance reason, so it does not have to be calculated for each message
(defn member-photo [pub-key identicon]
+4 -1
View File
@@ -243,7 +243,8 @@
(defn render-fn [{:keys [outgoing type] :as message}
idx
_
{:keys [group-chat public? current-public-key space-keeper chat-id show-input? message-pin-enabled edit-enabled in-pinned-view?]}]
{:keys [group-chat public? community? current-public-key space-keeper
chat-id show-input? message-pin-enabled edit-enabled in-pinned-view?]}]
[react/view {:style (when (and platform/android? (not in-pinned-view?)) {:scaleY -1})}
(if (= type :datemark)
[message-datemark/chat-datemark (:value message)]
@@ -255,6 +256,7 @@
:incoming-group (and group-chat (not outgoing))
:group-chat group-chat
:public? public?
:community? community?
:current-public-key current-public-key
:show-input? show-input?
:message-pin-enabled message-pin-enabled
@@ -285,6 +287,7 @@
community-admin?))))]
{:group-chat group-chat
:public? public?
:community? (not (nil? community-id))
:current-public-key current-public-key
:space-keeper space-keeper
:chat-id chat-id
@@ -12,6 +12,7 @@
(fn []
(let [current-chat (<sub [:chat-by-id chat-id])
{:keys [chat-name color description community-id emoji]} current-chat
{:keys [position]} (<sub [:chats/community-chat-by-id community-id chat-id])
category (<sub [:chats/category-by-chat-id community-id chat-id])
{:keys [admin]} (<sub [:communities/community community-id])
pinned-messages (<sub [:chats/pinned chat-id])]
@@ -27,7 +28,8 @@
color
emoji
chat-id
(:id category)])}])
(:id category)
position])}])
:extended-header (profile-header/extended-header
{:title chat-name
:color color
@@ -22,7 +22,6 @@
[re-frame.core :as re-frame]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.components.accordion :as accordion]
[clojure.string :as string]
[status-im.ui.screens.communities.styles :as styles]))
(def request-cooldown-ms (* 60 1000))
@@ -139,12 +138,6 @@
:title (i18n/label :t/edit-chats)
:accessibility-label :community-edit-chats
:icon :main-icons/edit
:on-press #(hide-sheet-and-dispatch [:open-modal :community-edit-chats {:community-id id}])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/reorder-categories)
:accessibility-label :community-reorder-categories
:icon :main-icons/channel-category
:on-press #(hide-sheet-and-dispatch
[:open-modal :community-reorder-categories {:community-id id}])}]])]))
@@ -168,46 +161,28 @@
{:content (fn []
[sheets/actions home-item])}])}])
(defn categories-accordion [community-id chats categories edit data]
(defn categories-accordion [community-id chats categories data]
[:<>
(for [{:keys [name id state]} (vals categories)]
(for [{:keys [name id state]} categories]
^{:key (str "cat" name id)}
[:<>
[accordion/section
{:on-open #(>evt [::communities/store-category-state community-id id true])
:on-close #(>evt [::communities/store-category-state community-id id false])
:default state
:opened edit
:disabled edit
:title [rn/view styles/category-item
(if edit
[rn/touchable-opacity {:on-press #(>evt [:delete-community-category community-id id])}
[icons/icon :main-icons/delete-circle {:no-color true}]]
[icons/icon :main-icons/channel-category {:color colors/gray}])
[icons/icon :main-icons/channel-category {:color colors/gray}]
[rn/text {:style {:font-size 17 :margin-left 10 :color colors/black}} name]]
:content [rn/view
:content [:<>
(for [chat (get chats id)]
(if edit
^{:key (str "chat" chat id)}
[rn/view styles/category-item
[rn/touchable-opacity {:on-press #(>evt [:remove-chat-from-community-category
community-id
(string/replace (:chat-id chat) community-id "")
(:categoryID chat)])}
[icons/icon :main-icons/delete-circle {:no-color true}]]
[rn/view {:flex 1}
[inner-item/home-list-item
(assoc chat :public? true)]]]
^{:key (str "chat" chat id)}
[community-chat-item chat nil nil data]))]}]
^{:key (str "chat" chat id)}
[community-chat-item chat nil nil data])]}]
[quo/separator]])])
(defn community-chat-list [community-id categories edit from-chat]
(let [chats (<sub [:chats/categories-by-community-id community-id])]
(defn community-chat-list [community-id categories from-chat]
(let [chats (<sub [:chats/sorted-categories-by-community-id community-id])]
(if (and (empty? categories) (empty? chats))
(if edit
[blank-page (i18n/label :t/welcome-community-blank-message-edit-chats)]
[blank-page (i18n/label :t/welcome-community-blank-message)])
[blank-page (i18n/label :t/welcome-community-blank-message)]
[list/flat-list
{:key-fn :chat-id
:content-container-style {:padding-bottom 8}
@@ -215,7 +190,7 @@
:data (get chats "")
:render-data {:from-chat from-chat}
:render-fn community-chat-item
:header [categories-accordion community-id chats categories edit {:from-chat from-chat}]
:header [categories-accordion community-id chats categories {:from-chat from-chat}]
:footer [rn/view {:height 68}]}])))
(defn channel-preview-item [{:keys [id name]}]
@@ -267,23 +242,6 @@
[components.react/small-loading-indicator]
(i18n/label :t/fetch-community))]]]))
(defn community-edit []
(let [{:keys [community-id]} (<sub [:get-screen-params])]
(fn []
(let [{:keys [id name images members permissions color]} (<sub [:communities/community community-id])
categories (<sub [:communities/sorted-categories community-id])]
[:<>
[topbar/topbar
{:modal? true
:content [toolbar-content
id
name
color
images
(not= (:access permissions) constants/community-no-membership-access)
(count members)]}]
[community-chat-list id categories true false]]))))
(defn community []
(let [{:keys [community-id from-chat]} (<sub [:get-screen-params])]
(fn []
@@ -65,4 +65,4 @@
@category-name
(vec @selected-items)]
3000)}
(i18n/label :t/create)]}]]))))
(i18n/label :t/create)]}]]))))
@@ -1,60 +1,176 @@
(ns status-im.ui.screens.communities.reorder-categories
(:require [quo.core :as quo]
[clojure.walk :as walk]
[quo.react-native :as rn]
[reagent.core :as reagent]
[clojure.string :as string]
[clojure.set :as clojure.set]
[status-im.i18n.i18n :as i18n]
[status-im.utils.utils :as utils]
[status-im.constants :as constants]
[quo.design-system.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.utils.platform :as platform]
[status-im.ui.components.topbar :as topbar]
[status-im.communities.core :as communities]
[status-im.utils.handlers :refer [>evt <sub]]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.communities.styles :as styles]
[status-im.ui.screens.communities.community :as community]))
[status-im.ui.screens.communities.community :as community]
[status-im.ui.screens.home.views.inner-item :as inner-item]))
(defn category-change-positon [community-id key up? position]
(let [new-position (if up? (dec position) (inc position))]
(>evt [::communities/reorder-community-category community-id key new-position])))
(def collapse-chats? (reagent/atom false))
(def data (reagent/atom []))
(defn category-item-button [community-id up? disabled? key position]
(let [[margin-right icon] (if up?
[10 :main-icons/dropdown-up]
[25 :main-icons/dropdown])]
[react/touchable-opacity {:disabled disabled?
:on-press #(category-change-positon
community-id key up? position)}
[rn/view {:style (styles/reorder-categories-button margin-right)}
[icons/icon icon {:color colors/black}]]]))
(defn show-delete-chat-confirmation [community-id chat-id]
(utils/show-confirmation
{:title (i18n/label :t/delete-confirmation)
:content (i18n/label :t/delete-chat-confirmation)
:confirm-button-text (i18n/label :t/delete)
:on-accept #(>evt [:delete-community-chat community-id chat-id])}))
(defn category-item [community-id count {:keys [key name position]}]
(let [up-disabled? (= position 0)
down-disabled? (= position (dec count))]
(defn show-delete-catgory-confirmation [community-id category-id]
(utils/show-confirmation
{:title (i18n/label :t/delete-confirmation)
:content (i18n/label :t/delete-category-confirmation)
:confirm-button-text (i18n/label :t/delete)
:on-accept #(>evt [:delete-community-category community-id category-id])}))
(defn chat-item
[{:keys [id community-id] :as home-item} is-active? drag]
(let [chat-id (string/replace id community-id "")
background-color (if is-active? colors/gray-lighter colors/white)
home-item (clojure.set/rename-keys home-item {:id :chat-id})]
[rn/view {:accessibility-label :chat-item
:style (merge styles/category-item
{:background-color background-color})}
[rn/touchable-opacity
{:accessibility-label :delete-community-chat
:on-press #(show-delete-chat-confirmation community-id chat-id)}
[icons/icon :main-icons/delete-circle {:no-color true}]]
[rn/view {:flex 1}
[inner-item/home-list-item (assoc home-item :edit? true) {:active-opacity 1}]]
[rn/touchable-opacity {:on-long-press drag
:delay-long-press 100
:accessibility-label :chat-drag-handle
:style {:padding 20}}
[icons/icon :main-icons/reorder-handle {:no-color true :width 18 :height 12}]]]))
(defn category-item
[{:keys [id name community-id]} is-active? drag]
(let [background-color (if is-active? colors/gray-lighter colors/white)
category-none? (string/blank? id)]
[:<>
[rn/view {:style styles/reorder-categories-item}
[icons/icon :main-icons/channel-category {:color colors/gray}]
[rn/text {:style (styles/reorder-categories-text)} name]
[category-item-button community-id true up-disabled? key position]
[category-item-button community-id false down-disabled? key position]]
[quo/separator]]))
[quo/separator]
[rn/view {:accessibility-label :category-item
:style (merge styles/category-item
{:background-color background-color})}
(if category-none?
[icons/icon :main-icons/channel-category {:color colors/gray}]
[rn/touchable-opacity
{:accessibility-label :delete-category-button
:on-press #(show-delete-catgory-confirmation community-id id)}
[icons/icon :main-icons/delete-circle {:no-color true}]])
[rn/view {:flex 1}
[rn/text {:style {:font-size 17 :margin-left 10 :color colors/black}} name]]
(when (and (not category-none?) @collapse-chats?)
[rn/touchable-opacity {:accessibility-label :category-drag-handle
:on-long-press drag
:delay-long-press 100
:style {:padding 20}}
[icons/icon :main-icons/reorder-handle {:no-color true :width 18 :height 12}]])]]))
(defn categories-view [community-id categories count]
[rn/view {:accessibility-label :reorder-categories-list}
(for [category-vector categories]
(let [category (clojure.set/rename-keys (get category-vector 1) {:id :key})]
[category-item community-id count category]))])
(defn render-fn
[{:keys [chat-type] :as item} _ _ _ is-active? drag]
(if (= chat-type constants/community-chat-type)
[chat-item item is-active? drag]
[category-item item is-active? drag]))
(defn calculate-chat-new-position-and-category
[to second-call? old-category going-up?]
(let [{:keys [id chat-type categoryID position]} (get @data to)
[new-category new-position]
(if going-up?
(if (= chat-type constants/community-chat-type)
[categoryID (if second-call? (inc position) position)]
(if second-call? [id 0]
(calculate-chat-new-position-and-category (dec to) true old-category true)))
(if (= chat-type constants/community-chat-type)
(if (= categoryID old-category)
[categoryID position]
[categoryID (inc position)]) [id 0]))]
[new-category new-position]))
(defn update-local-atom [data-js]
(reset! data data-js)
(reagent/flush))
(defn on-drag-end-chat [from to data-js]
(let [{:keys [id community-id categoryID position]} (get @data from)
[new-category new-position] (calculate-chat-new-position-and-category
to false categoryID (> from to))
chat-id (string/replace id community-id "")]
(when-not (and (= new-position position) (= new-category categoryID))
(update-local-atom data-js)
(>evt [::communities/reorder-community-category-chat
community-id new-category chat-id new-position]))))
(defn on-drag-end-category [from to data-js]
(let [{:keys [id community-id position]} (get @data from)]
(when (and (< to (count @data)) (not= position to) (not= id ""))
(update-local-atom data-js)
(>evt [::communities/reorder-community-category community-id id to]))))
(defn on-drag-end-fn [from to data-js]
(if @collapse-chats?
(on-drag-end-category from to data-js)
(when-not (= to 0) (on-drag-end-chat from to data-js))))
(defn reset-data [categories chats]
(reset! data (if @collapse-chats? categories ;; If chats are collapsed then only show categories
(walk/postwalk-replace ;; else, categories and chats
{:chat-id :id}
(reduce (fn [acc category]
(-> acc
(conj category)
(into (get chats (:id category))))) [] categories)))))
(defn draggable-list []
[rn/draggable-flat-list
{:key-fn :id
:data @data
:render-fn render-fn
:autoscroll-threshold (if platform/android? 150 250)
:autoscroll-speed (if platform/android? 10 150) ;; TODO - Use same speed for both ios and android
:container-style {:margin-bottom 108} ;; after bumping react native version to > 0.64
:on-drag-end-fn on-drag-end-fn}])
(defn view []
(let [{:keys [community-id]} (<sub [:get-screen-params])
{:keys [id name images members permissions color]}
(<sub [:communities/community community-id])
categories (<sub [:communities/sorted-categories community-id])]
sorted-categories (<sub [:communities/sorted-categories community-id])
categories (if @collapse-chats? sorted-categories
(conj sorted-categories
{:id ""
:position (count sorted-categories)
:name (i18n/label :t/none)
:community-id community-id}))
chats (<sub [:chats/sorted-categories-by-community-id community-id])]
(reset-data categories chats)
[:<>
[topbar/topbar
{:modal? true
:content [community/toolbar-content id name color images
(not= (:access permissions) constants/community-no-membership-access)
(count members)]}]
(if (empty? categories)
[community/blank-page (i18n/label :t/welcome-community-blank-message-categories)]
[categories-view community-id categories (count categories)])]))
(if (and (empty? sorted-categories) (empty? chats))
[community/blank-page (i18n/label :t/welcome-community-blank-message-edit-chats)]
[:<>
[quo/list-item {:size :small
:title (i18n/label :t/rearrange-categories)
:active @collapse-chats?
:accessory :switch
:container-style {:padding-left 10}
:on-press #(reset! collapse-chats? (not @collapse-chats?))}]
[quo/separator]
[draggable-list]])]))
@@ -11,7 +11,8 @@
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.topbar :as topbar]
[status-im.i18n.i18n :as i18n]
[status-im.communities.core :as communities]))
[status-im.communities.core :as communities]
[quo.components.animated.pressable :as animation]))
(defn hide-sheet-and-dispatch [event]
(>evt [:bottom-sheet/hide])
@@ -19,11 +20,11 @@
(defn request-actions [community-id request-id]
[react/view {:flex-direction :row}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:communities.ui/accept-request-to-join-pressed community-id request-id])}
[animation/pressable {:on-press #(re-frame/dispatch [:communities.ui/accept-request-to-join-pressed community-id request-id])}
[icons/icon :main-icons/checkmark-circle {:width 35
:height 35
:color colors/green}]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:communities.ui/decline-request-to-join-pressed community-id request-id])}
[animation/pressable {:on-press #(re-frame/dispatch [:communities.ui/decline-request-to-join-pressed community-id request-id])}
[icons/icon :main-icons/cancel {:width 35
:height 35
:container-style {:margin-left 16}
@@ -41,7 +42,8 @@
:accessory (when can-manage-users?
[request-actions community-id id])
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo member)]}]))
(multiaccounts/displayed-photo member)]
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
(defn requests-to-join []
(let [{:keys [community-id]} (<sub [:get-screen-params])]
@@ -25,6 +25,7 @@
(let [{:keys [community-id chat]} (<sub [:get-screen-params])]
(fn []
(let [categories (<sub [:communities/sorted-categories community-id])
chats (<sub [:chats/sorted-categories-by-community-id community-id])
comm-chat (<sub [:chats/community-chat-by-id community-id (:chat-id chat)])
_ (reset! selected-item (:categoryID comm-chat))]
[:<>
@@ -44,7 +45,7 @@
:create-community-category
{:community-id community-id}])
:title (i18n/label :t/create-category)}]
:data (conj (vec (vals categories)) {:name (i18n/label :t/none) :id ""})
:data (conj categories {:name (i18n/label :t/none) :id ""})
:render-fn render-fn}]]
[toolbar/toolbar
{:show-border? true
@@ -54,6 +55,7 @@
[::communities/change-category-confirmation-pressed
community-id
@selected-item
comm-chat]
(assoc comm-chat :position
(count (get chats @selected-item)))] ;; Add as last item in new category
3000)}
(i18n/label :t/done)]}]]))))
@@ -1,34 +1,8 @@
(ns status-im.ui.screens.communities.styles
(:require [quo.design-system.colors :as colors]))
(ns status-im.ui.screens.communities.styles)
(def category-item
{:flex 1
:flex-direction :row
:align-items :center
:height 52
:margin-left 18})
(def reorder-categories-item
{:accessibility-label :reorder-categories-item
:flex-direction :row
:height 60
:align-items :center
:margin-left 18})
(defn reorder-categories-text []
{:font-size 17
:margin-left 10
:color (colors/get-color :text-01)
:flex 1})
(defn reorder-categories-button [margin-right]
{:accessibility-label :reorder-categories-button
:width 30
:height 30
:border-radius 15
:margin 10
:margin-right margin-right
:border-width 1
:justify-content :center
:align-items :center
:border-color colors/black})
:padding-left 18})
@@ -3,10 +3,12 @@
(:require [status-im.ui.components.react :as react]
[status-im.i18n.i18n :as i18n]
[status-im.constants :as constants]
[status-im.utils.config :as config]
[quo.core :as quo]
[re-frame.core :as re-frame]))
(def titles {constants/one-day (i18n/label :t/one-day)
(def titles {constants/two-mins (i18n/label :t/two-minutes)
constants/one-day (i18n/label :t/one-day)
constants/three-days (i18n/label :t/three-days)
constants/one-week (i18n/label :t/one-week)
constants/one-month (i18n/label :t/one-month)})
@@ -21,6 +23,8 @@
(views/defview default-sync-period-settings []
(views/letsubs [{:keys [default-sync-period]} [:multiaccount]]
[react/view {:margin-top 8}
(when config/two-minutes-syncing?
[radio-item constants/two-mins default-sync-period])
[radio-item constants/one-day default-sync-period]
[radio-item constants/three-days default-sync-period]
[radio-item constants/one-week default-sync-period]
+4 -26
View File
@@ -3,7 +3,6 @@
[reagent.core :as reagent]
[status-im.i18n.i18n :as i18n]
[status-im.react-native.resources :as resources]
[status-im.communities.core :as communities]
[status-im.ui.components.connectivity.view :as connectivity]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.list.views :as list]
@@ -13,7 +12,6 @@
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.screens.referrals.home-item :as referral-item]
[quo.design-system.colors :as colors]
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
[quo.core :as quo]
[status-im.add-new.core :as new-chat]
[status-im.ui.components.search-input.view :as search-input]
@@ -41,30 +39,10 @@
:accessibility-label :hide-home-button}
[icons/icon :main-icons/close-circle {:color colors/gray}]]
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]
[invite/button]
[react/view {:align-items :center :margin-bottom 16}
[react/view {:style (styles/hr-wrapper)}]
[react/i18n-text {:style (styles/or-text) :key :or}]]
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :follow-your-interests}]
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center
:margin-top 10
:margin-bottom 18}
(for [chat (new-public-chat/featured-public-chats)]
^{:key chat}
[new-public-chat/render-topic chat])]
(when @(re-frame/subscribe [:communities/enabled?])
[:<>
[react/i18n-text {:style {:margin-horizontal 16
:text-align :center}
:key :join-a-community}]
[react/view {:flex-direction :row :flex-wrap :wrap :justify-content :center
:margin-top 10
:margin-bottom 18}
(for [{:keys [id] :as community} communities/featured]
^{:key id}
[communities.views/render-featured-community community])]])])
[react/view {:align-items :center
:margin-top 8
:margin-bottom 12}
[invite/button]]])
(defn welcome-blank-page []
[react/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :center}}
@@ -149,13 +149,16 @@
:else
[icons/icon :main-icons/tiny-new-contact (icon-style)]))
(defn chat-item-title [chat-id muted group-chat chat-name]
(defn chat-item-title [chat-id muted group-chat chat-name edit?]
[quo/text {:weight :medium
:color (when muted :secondary)
:accessibility-label :chat-name-text
:ellipsize-mode :tail
:number-of-lines 1
:style {:position :absolute :left 92 :top 10 :right 90}}
:style {:position :absolute
:left 92
:top 10
:right (if edit? 50 90)}}
(if group-chat
(utils/truncate-str chat-name 30)
;; This looks a bit odd, but I would like only to subscribe
@@ -164,7 +167,7 @@
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))])
(defn home-list-item [home-item opts]
(let [{:keys [chat-id chat-name color group-chat public? timestamp last-message muted emoji highlight]} home-item
(let [{:keys [chat-id chat-name color group-chat public? timestamp last-message muted emoji highlight edit?]} home-item
background-color (when highlight (colors/get-color :interactive-02))]
[react/touchable-opacity (merge {:style {:height 64 :background-color background-color}} opts)
[:<>
@@ -178,13 +181,15 @@
:default-chat-icon-text (if (string/blank? emoji)
(chat-icon.styles/default-chat-icon-text 40)
(chat-icon.styles/emoji-chat-icon-text 40))}]
[chat-item-title chat-id muted group-chat chat-name]
[react/text {:style styles/datetime-text
:number-of-lines 1
:accessibility-label :last-message-time-text}
;;TODO (perf) move to event
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
(:whisper-timestamp last-message)
timestamp))]
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]
[unviewed-indicator home-item]]]))
[chat-item-title chat-id muted group-chat chat-name edit?]
(when-not edit?
[:<>
[react/text {:style styles/datetime-text
:number-of-lines 1
:accessibility-label :last-message-time-text}
;;TODO (perf) move to event
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
(:whisper-timestamp last-message)
timestamp))]
[unviewed-indicator home-item]])
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]]]))
+43 -21
View File
@@ -44,6 +44,17 @@
[status-im.ui.screens.currency-settings.views :as currency-settings]
[status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
[status-im.ui.screens.default-sync-period-settings.view :as default-sync-period-settings]
[status-im.ui.screens.wallet.settings.views :as wallet-settings]
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
[status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
[status-im.ui.screens.wallet.collectibles.views :as wallet.collectibles]
[status-im.ui.screens.wallet.account.views :as wallet.account]
[status-im.ui.screens.wallet.add-new.views :as add-account]
[status-im.ui.screens.wallet.account-settings.views :as account-settings]
[status-im.ui.screens.wallet.swap.views :as wallet.swap]
[status-im.ui.screens.status.views :as status.views]
[status-im.ui.screens.profile.user.views :as profile.user]
[status-im.ui.screens.ens.views :as ens]
[status-im.ui.screens.fleet-settings.views :as fleet-settings]
[status-im.ui.screens.glossary.view :as glossary]
@@ -91,7 +102,6 @@
[status-im.ui.screens.profile.contact.views :as contact]
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
[status-im.ui.screens.profile.seed.views :as profile.seed]
[status-im.ui.screens.profile.user.views :as profile.user]
[status-im.ui.screens.progress.views :as progress]
[status-im.ui.screens.qr-scanner.views :as qr-scanner]
[status-im.ui.screens.referrals.public-chat :as referrals.public-chat]
@@ -99,7 +109,6 @@
[status-im.ui.screens.reset-password.views :as reset-password]
[status-im.ui.screens.rpc-usage-info :as rpc-usage-info]
[status-im.ui.screens.status.new.views :as status.new]
[status-im.ui.screens.status.views :as status.views]
[status-im.ui.screens.stickers.views :as stickers]
[status-im.ui.screens.sync-settings.views :as sync-settings]
[status-im.ui.screens.terms-of-service.views :as terms-of-service]
@@ -107,18 +116,10 @@
:as
edit-wakuv2-node]
[status-im.ui.screens.wakuv2-settings.views :as wakuv2-settings]
[status-im.ui.screens.wallet.account-settings.views :as account-settings]
[status-im.ui.screens.wallet.account.views :as wallet.account]
[status-im.ui.screens.wallet.accounts-manage.views :as accounts-manage]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
[status-im.ui.screens.wallet.add-new.views :as add-account]
[status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
[status-im.ui.screens.wallet.collectibles.views :as wallet.collectibles]
[status-im.ui.screens.wallet.custom-tokens.views :as custom-tokens]
[status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send]
[status-im.ui.screens.wallet.settings.views :as wallet-settings]
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]))
[status-im.ui.screens.wallet.send.views :as wallet.send]))
(def components
[{:name :chat-toolbar
@@ -220,9 +221,9 @@
;Chat
{:name :chat
:options {:popGesture false
:topBar {:title {:component {:name :chat-toolbar :id :chat-toolbar}
:alignment :fill}
:rightButtons (right-button-options :chat :more)}}
:topBar {:title {:component {:name :chat-toolbar :id :chat-toolbar}
:alignment :fill}
:rightButtons (right-button-options :chat :more)}}
:right-handler chat/topbar-button
:component chat/chat}
@@ -288,11 +289,6 @@
;;TODO custom
:options {:topBar {:visible false}}
:component select-category/view}
{:name :community-edit-chats
;;TODO custom
:insets {:bottom true}
:options {:topBar {:visible false}}
:component community/community-edit}
{:name :community-reorder-categories
:insets {:top false}
:options {:topBar {:visible false}}
@@ -400,6 +396,32 @@
:options {:topBar {:title {:text (i18n/label :t/wallet-manage-accounts)}}}
:component accounts-manage/manage}
{:name :token-swap
;;TODO dynamic title
:options {:topBar {:visible false}}
:component wallet.swap/swap}
{:name :token-swap-advanced-nonce
:options {:topBar {:title {:text (i18n/label :t/nonce)}}}
:component wallet.swap/nonce-modal}
{:name :token-swap-advanced-approve-token
:options {:topBar {:title {:text (i18n/label :t/approve-token)}}}
:component wallet.swap/approve-token-modal}
{:name :token-swap-advanced-transaction-fee
:options {:topBar {:title {:text (i18n/label :t/transaction-fee)}}}
:component wallet.swap/transaction-fee-modal}
{:name :token-swap-advanced-swap-details
:options {:topBar {:title {:text (i18n/label :t/swap-details)}}}
:component wallet.swap/swap-details-modal}
{:name :swap-asset-selector
;;TODO dynamic title
:options {:topBar {:visible false}}
:component wallet.swap/asset-selector}
;;MY STATUS
{:name :status
@@ -708,8 +730,8 @@
:options {:topBar {:visible false}}
:component wallet.buy-crypto/website}
{:name :nft-details
:insets {:bottom true}
{:name :nft-details
:insets {:bottom true}
;;TODO dynamic title
:options {:topBar {:visible false}}
:component wallet.collectibles/nft-details-modal}
@@ -40,6 +40,8 @@
:chevron true
:accessory :text
:accessory-text (cond
(= default-sync-period constants/two-mins)
(i18n/label :t/two-minutes)
(= default-sync-period constants/one-day)
(i18n/label :t/one-day)
(= default-sync-period constants/three-days)
@@ -42,3 +42,19 @@
:duration 200
:easing (.-ease ^js animation/easing)
:useNativeDriver true}))
(def round-action-button
{:background-color colors/blue
:height 44
:flex 1
:justify-content :center
:align-items :center
:width 44
:border-radius 44})
(def top-actions
{:flex 1
:flex-direction :row
:justify-content :space-between
:width "60%"
:align-self :center})
@@ -7,16 +7,17 @@
[quo.design-system.colors :as colors]
[status-im.ui.components.icons.icons :as icons]
[quo.core :as quo]
[quo.design-system.spacing :as spacing]
[status-im.ui.components.react :as react]
[status-im.ui.components.topbar :as topbar]
[status-im.utils.config :as config]
[status-im.ui.screens.wallet.account.styles :as styles]
[status-im.ui.screens.wallet.accounts.sheets :as sheets]
[status-im.ui.screens.wallet.accounts.views :as accounts]
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
[status-im.ui.screens.wallet.transactions.views :as history]
[status-im.ui.components.tabs :as tabs]
[status-im.ui.screens.wallet.collectibles.views :as collectibles.views])
[status-im.ui.screens.wallet.collectibles.views :as collectibles.views]
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto])
(:require-macros [status-im.utils.views :as views]))
(def state (reagent/atom {:tab :assets}))
@@ -102,7 +103,6 @@
currency [:wallet/currency]
opensea-enabled? [:opensea-enabled?]
collectible-collection [:wallet/collectible-collection address]
mainnet? [:mainnet?]
ethereum-network? [:ethereum-network?]]
(let [{:keys [tab]} @state]
[react/view {:flex 1}
@@ -111,11 +111,10 @@
(when ethereum-network?
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
[quo/separator {:style {:margin-top -8}}]
(cond
(= tab :assets)
[:<>
(when mainnet?
[buy-crypto/banner])
(for [item tokens]
^{:key (:name item)}
[accounts/render-asset item nil nil (:code currency)])]
@@ -181,10 +180,31 @@
(styles/bottom-send-recv-buttons-lower anim-y button-group-height)
#(reset! to-show false))))))))
(defn round-action-button [{:keys [icon title on-press]}]
[react/view {:style {:flex 1
:align-items :center
:margin-vertical (:large spacing/spacing)}}
[react/touchable-opacity {:style styles/round-action-button
:on-press on-press}
(icons/icon icon {:color colors/white})]
[quo/text {:color :secondary
:size :small
:style {:margin-top (:tiny spacing/spacing)}}
title]])
(defn top-actions []
[react/view {:style styles/top-actions}
[round-action-button {:icon :main-icons/add
:title (i18n/label :t/buy-crypto)
:on-press #(re-frame/dispatch [:buy-crypto.ui/open-screen])}]
[round-action-button {:icon :main-icons/change
:title (i18n/label :t/swap)
:on-press #(re-frame/dispatch [:open-modal :token-swap])}]])
(views/defview account []
(views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account]
fetching-error [:wallet/fetching-error]]
(let [anim-y (animation/create-value button-group-height)
(let [anim-y (animation/create-value button-group-height)
scroll-y (animation/create-value 0)]
(anim-listener anim-y scroll-y)
[:<>
@@ -206,9 +226,9 @@
@accounts/updates-counter
@(re-frame/subscribe [:wallet/refreshing-history?])))}
(when fetching-error
[react/view {:style {:flex 1
[react/view {:style {:flex 1
:align-items :center
:margin 8}}
:margin 8}}
[icons/icon
:main-icons/warning
{:color :red
@@ -233,5 +253,8 @@
[react/scroll-view {:horizontal true}
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
[account-card account]]]]
(if config/swap-enabled?
[top-actions]
[buy-crypto/banner])
[assets-and-collections address]]
[bottom-send-recv-buttons account anim-y]])))
@@ -0,0 +1,433 @@
(ns status-im.ui.screens.wallet.swap.views
(:require [quo.core :as quo]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[status-im.ethereum.tokens :as tokens]
[status-im.i18n.i18n :as i18n]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.keyboard-avoid-presentation
:as
kb-presentation]
[status-im.ui.components.react :as react]
[status-im.ui.components.search-input.view :as search-input]
[status-im.ui.components.slider :as slider]
[status-im.wallet.swap.core :as wallet.swap]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.wallet.components.views :as wallet.components]
[status-im.utils.handlers :refer [<sub]]
[status-im.wallet.utils :as wallet.utils]
[clojure.string :as str]))
(defn render-asset [{{:keys
[icon decimals amount color value]
:as token} :token
currency :currency
on-press :on-press}]
[quo/list-item
{:title [quo/text {:weight :medium}
[quo/text {:weight :inherit}
(str (if amount
(wallet.utils/format-amount amount decimals)
"...")
" ")]
[quo/text {:color :secondary
:weight :inherit}
(wallet.utils/display-symbol token)]]
:on-press on-press
:subtitle (str (if value value "...") " " currency)
:accessibility-label
(str (:symbol token) "-asset-value")
:icon (if icon
[wallet.components/token-icon icon]
[chat-icon/custom-icon-view-list (:name token) color])}])
(defn asset-selector []
(let [{:keys [address]} (<sub [:multiaccount/current-account])
{:keys [tokens]} (<sub [:wallet/visible-assets-with-values address])
source? (<sub [:wallet/modal-selecting-source-token?])
currency (<sub [:wallet/currency])]
[:<>
[topbar/topbar
{:title (if source?
(i18n/label :t/select-token-to-swap)
(i18n/label :t/select-token-to-receive))
:modal? true}]
[search-input/search-input
{:search-active? true}]
[react/scroll-view
(for [token tokens]
^{:key (:name token)}
[render-asset {:token token
:on-press #(re-frame/dispatch
[(if source?
::wallet.swap/set-from-token
::wallet.swap/set-to-token)
(:symbol token)])
:currency (:code currency)}])]]))
(defn pill-button [{:keys [on-press label margin-left]}]
[react/touchable-opacity {:on-press on-press
:style {:background-color colors/blue-light
:padding-horizontal 12
:padding-vertical 2
:border-radius 24
:margin-left (or margin-left 8)}}
[quo/text {:color :link
:weight :medium} label]])
(defn token-display
"Show token and act as an anchor to open selector."
[{:keys [token source?]}]
(let [token-icon-source (-> token :icon :source)]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [::wallet.swap/open-asset-selector-modal source?])}
[react/view {:style {:flex-direction :row
:align-items :center
:border-width 1
:border-color colors/gray-lighter
:border-radius 8
:margin-left 16
:padding-horizontal 8
:padding-vertical 2}
:accessibility-label
:choose-asset-button}
[quo/text {:style {:margin-right 8}}
(-> token :symbol name)]
[react/image {:source (if (fn? token-icon-source)
(token-icon-source)
token-icon-source)}]]]))
(defn token-input
"Component to get the amount and type of tokens"
[{:keys [amount error label token max-from source?]}]
(let [window-width (<sub [:dimensions/window-width])]
[react/view {:style {:justify-content :space-between
:flex-direction :row
:align-items :center}}
[react/view {:flex 2}
[react/view {:flex-direction :row
:align-items :center}
[quo/text label]
(when max-from [pill-button {:on-press #()
:label "Max 0.043"}])]
[react/text-input
{:style {:font-size 38
:max-width (- (* (/ window-width 4) 3) 106)
:color (if error colors/red colors/black)}
:keyboard-type :decimal-pad
:auto-capitalize :words
:accessibility-label :amount-input
:default-value amount
:editable true
:auto-focus true
:on-change-text #(re-frame/dispatch [(when source?
::wallet.swap/set-from-token-amount)
%])
:placeholder "0.0"}]]
[token-display {:token token
:source? source?}]]))
(defn separator-with-icon []
[react/view
{:margin-vertical 8}
[quo/separator]
[react/touchable-opacity
{:on-press #(re-frame/dispatch [::wallet.swap/switch-from-token-with-to])}
[react/view {:style {:background-color colors/gray-lighter
:width 40
:height 40
:border-radius 40
:border-width 4
:border-color colors/white
:margin-top -20
:margin-bottom -20
:align-self :center
:align-items :center
:justify-content :center}}
[react/image {:source (icons/icon-source :main-icons/change)
:style {:tint-color colors/gray
:transform [{:rotate "90deg"}]}}]]]])
(defn floating-card [{:keys [icon title body on-press]}]
[react/view {:style {:border-width 1
:padding 2 ;; need a padding because border breaks otherwise
:border-radius 12
:margin-top 12
:border-color colors/gray-lighter}}
[quo/list-item {:title title
:subtitle body
:active-background-enabled
false
:on-press on-press
:theme :main
:chevron true
:icon [react/view {:style {:background-color colors/blue-light
:padding 8
:border-radius 4}}
(icons/icon icon {:color :dark})]}]])
(defn card-body-row [key value primary?]
[react/view {:flex-direction :row}
[quo/text {:color (when-not primary? :secondary)} key]
[quo/text {:style {:margin-right 4}
:color (when-not primary? :secondary)} ":"]
[quo/text {:ellipsize-mode :middle
:number-of-lines 1
:style {:width "50%"}
:color (when-not primary? :secondary)
:weight :semi-bold} value]])
(defn transaction-fee-card [{:keys [gas-amount price-limit tip-limit gas-in-eth gas-in-usd]}]
[floating-card {:title (i18n/label :t/transaction-fee)
:icon :main-icons/gas
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-transaction-fee])
:body [react/view
[card-body-row (i18n/label :t/gas-amount-limit) gas-amount]
[card-body-row (i18n/label :t/per-gas-price-limit) price-limit]
[card-body-row (i18n/label :t/per-gas-tip-limit) tip-limit]
[card-body-row (i18n/label :t/total-gas)
(str gas-in-eth " • $" gas-in-usd)
true]]}])
(defn swap-details-card [{:keys [slippage price-impact]}]
[floating-card {:title (i18n/label :t/swap-details)
:icon :main-icons/change
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-swap-details])
:body [react/view
[card-body-row (i18n/label :t/slippage) (str slippage " %")]
[card-body-row (i18n/label :t/price-impact) (str price-impact " %")]]}])
(defn nonce-card [{:keys [nonce]}]
[floating-card {:title (i18n/label :t/nonce)
:icon :main-icons/channel
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-nonce])
:body [react/view
[card-body-row (i18n/label :t/nonce) nonce]]}])
(defn approve-token-card [{:keys [token contract-address approve-limit]}]
[floating-card {:title (i18n/label :t/approve)
:icon :main-icons/check
:on-press #(re-frame/dispatch [:open-modal :token-swap-advanced-approve-token])
:body [react/view
[card-body-row (i18n/label :t/token) token]
[card-body-row (i18n/label :t/contract-address) contract-address]
[card-body-row (i18n/label :t/approve-limit) approve-limit]]}])
(defn advanced-input [{:keys [label label-help value on-change after]}]
[react/view {:style {:padding-horizontal 16
:margin-bottom 16}}
[react/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo/text {} label]
label-help]
[quo/text-input {:default-value (str value)
:show-cancel false
:style {:margin-top 12
:border-radius 8}
:after {:component after}
:on-change-text on-change}]])
(defn help-label-kv [{:keys [key value]}]
[react/view {:style {:flex-direction :row}}
[quo/text {:color :secondary} key]
[quo/text {:color :secondary
:style {:margin-right 4}} ":"]
[quo/text {:color :secondary} value]])
(defn nonce-modal []
(let [last-txn-nonce 22
nonce 23]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
:margin-top 16}
:ignore-offset true}
[advanced-input {:label (i18n/label :t/nonce)
:label-help [help-label-kv {:key (i18n/label :t/last-transaction)
:value last-txn-nonce}]
:value nonce
:on-change #()
:on-save #()}]
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary}
(i18n/label :t/cancel)]
:right [quo/button {:theme :accent}
(i18n/label :t/save)]}]]))
(defn approve-token-modal []
[quo/text "modal"])
(defn transaction-fee-modal []
(let [gas-amount-limit 21000
gas-amount 21000
per-gas-price-limit 7.3
current-avg-per-gas-price-limit 7.3
per-gas-tip-limit 150
current-avg-per-gas-tip-limit 150]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
:margin-top 16}
:ignore-offset true}
[react/view {:flex 1}
[advanced-input {:label (i18n/label :t/gas-amount-limit)
:label-help [help-label-kv {:key (i18n/label :t/limit)
:value gas-amount-limit}]
:value gas-amount
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
:on-change #()
:on-save #()}]
[advanced-input {:label (i18n/label :t/per-gas-price-limit)
:label-help [help-label-kv {:key (i18n/label :t/current-average)
:value current-avg-per-gas-price-limit}]
:value per-gas-price-limit
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
:on-change #()
:on-save #()}]
[advanced-input {:label (i18n/label :t/per-gas-price-limit)
:label-help [help-label-kv {:key (i18n/label :t/current-average)
:value current-avg-per-gas-tip-limit}]
:value per-gas-tip-limit
:after [quo/text {:color :secondary} (i18n/label :t/gwei)]
:on-change #()
:on-save #()}]
[quo/list-item {:title (i18n/label :t/maximum-fee)
:text-size :base
:title-text-weight :regular
:accessory :text
:accessory-text [quo/text "0.3 ETH"]
:container-style {:margin-top 16}}]
[quo/text {:color :secondary
:style {:padding-horizontal 16}}
(i18n/label :t/maximum-fee-desc)]]
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary}
(i18n/label :t/cancel)]
:right [quo/button {:theme :accent}
(i18n/label :t/save)]}]]))
(defn swap-details-modal []
(let [slippage-limit 20
slippage 0.5
price-impact 4]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1
:margin-top 16}
:ignore-offset true}
[react/view {:flex 1}
[advanced-input {:label (str (i18n/label :t/slippage) " %")
:label-help [help-label-kv {:key (i18n/label :t/limit)
:value (str slippage-limit "%")}]
:value slippage
:on-change #()
:on-save #()}]
[quo/list-item {:title (i18n/label :t/price-impact)
:text-size :base
:title-text-weight :regular
:accessory :text
:accessory-text (str price-impact "%")
:container-style {:margin-top 16}}]
[quo/text {:color :secondary
:style {:padding-horizontal 16}}
(i18n/label :t/price-impact-desc)]]
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary}
(i18n/label :t/cancel)]
:right [quo/button {:theme :accent}
(i18n/label :t/save)]}]]))
(defn advanced-settings []
[react/view {:style {:flex 1
:padding-horizontal 16}}
[react/view {:align-self :flex-start}
[pill-button {:label (i18n/label :t/switch-to-simple-interface)
:margin-left 0
:on-press #(re-frame/dispatch [::wallet.swap/set-advanced-mode false])}]]
[transaction-fee-card {:gas-amount 21000
:price-limit 74
:tip-limit 21
:gas-in-eth 0.0031
:gas-in-usd 34.28}]
[swap-details-card {:slippage 0.5
:price-impact 4}]
[approve-token-card {:token "USDC"
:contract-address "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2"
:approve-limit "unlimited"}]
[nonce-card {:nonce 22}]])
(defn swap []
(let [{:keys [name]}
(<sub [:multiaccount/current-account])
all-tokens (<sub [:wallet/all-tokens])
from-symbol (<sub [:wallet/swap-from-token])
to-symbol (<sub [:wallet/swap-to-token])
advanced-mode? (<sub [:wallet/swap-advanced-mode?])
amount "0.02"
from-token (tokens/symbol->token all-tokens (or from-symbol :DGX))
to-token (tokens/symbol->token all-tokens (or to-symbol :SNT))]
[kb-presentation/keyboard-avoiding-view {:style (merge
{:flex 1})
:ignore-offset true}
[topbar/topbar
{:title name
:subtitle (str/upper-case (i18n/label :t/powered-by-paraswap))
:modal? true}]
[react/view (merge {:padding-horizontal 16
:margin-vertical 32}
(when-not advanced-mode?
{:flex 1}))
[token-input {:amount amount
:error nil
:label (i18n/label :t/amount)
:token from-token
:source? true
:max-from 67.28}]
[separator-with-icon]
[token-input {:amount "0.01"
:error nil
:label (i18n/label :t/minimum-received)
:source? false
:token to-token}]]
(when-not advanced-mode?
[react/view {:style {:flex-direction :row
:justify-content :space-between
:padding-horizontal 16
:align-items :center}}
[react/view {:style {:flex-direction :row}}
[quo/text {} (i18n/label :t/priority)]
[pill-button {:label (i18n/label :t/advanced)
:on-press #(re-frame/dispatch [::wallet.swap/set-advanced-mode true])}]]
[quo/text {:color :secondary} "0.0034 ETH/ $ 8.09"]])
(comment
(re-frame/dispatch [::wallet.swap/set-advanced-mode false]))
(when-not advanced-mode?
[react/view {:style {:padding-horizontal 16}}
[slider/animated-slider
{:minimum-value 0
:maximum-value 100
:style {:margin-vertical 8}}]])
(when advanced-mode?
[quo/text "here"]
[advanced-settings])
[toolbar/toolbar
{:show-border? true
:right [quo/button {:theme :accent}
(i18n/label :t/swap)]}]]))
+2
View File
@@ -52,6 +52,8 @@
(def delete-message-enabled? (enabled? (get-config :DELETE_MESSAGE_ENABLED "0")))
(def collectibles-enabled? (enabled? (get-config :COLLECTIBLES_ENABLED "1")))
(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")))
;; CONFIG VALUES
(def log-level
+51
View File
@@ -0,0 +1,51 @@
(ns status-im.wallet.swap.core
(:require [status-im.utils.fx :as fx]
[re-frame.db :as re-frame.db]
[status-im.navigation :as navigation]))
(fx/defn open-asset-selector-modal
"source? true signinfies we are selecting the source asset. false implies selection of sink asset"
{:events [::open-asset-selector-modal]}
[{:keys [db]} source?]
(fx/merge {:db (assoc db :wallet/modal-selecting-source-token? source?)}
(navigation/open-modal :swap-asset-selector {})))
(fx/defn set-from-token
{:events [::set-from-token]}
[{:keys [db]} from-symbol]
(fx/merge {:db (assoc db :wallet/swap-from-token from-symbol)}
(navigation/navigate-back)))
(fx/defn set-to-token
{:events [::set-to-token]}
[{:keys [db]} to-symbol]
(fx/merge {:db (assoc db :wallet/swap-to-token to-symbol)}
(navigation/navigate-back)))
(fx/defn set-from-token-amount
[{:keys [db]} from-amount]
{:db (assoc db :wallet/swap-from-token-amount from-amount)})
(fx/defn set-max-from-token-amount
[{:keys [db]} _]
{:db (assoc db :wallet/swap-from-token-amount 0)})
(fx/defn switch-from-token-with-to
{:events [::switch-from-token-with-to]}
[{:keys [db]}]
{:db (assoc db
:wallet/swap-from-token (:wallet/swap-to-token db)
:wallet/swap-to-token (:wallet/swap-from-token db))})
(fx/defn set-advanced-mode
{:events [::set-advanced-mode]}
[{:keys [db]} mode]
{:db (assoc db :wallet/swap-advanced-mode? mode)})
(comment
(->> re-frame.db/app-db
deref
:wallet/all-tokens
vals
(map #(str (:name %) "-" (:symbol %)))))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.92.5",
"commit-sha1": "64589fbd1f81022c7f995a7d993f0c026ecc6923",
"src-sha256": "0d4zh9kmgi0vwgn1wsbjfnp7hiv2m0l1472wkjg23snskz2g5g14"
"version": "feat/node-config",
"commit-sha1": "3daf1ea073fe1aa636a9d301a8e2a04acd7adbca",
"src-sha256": "1vc70av6jvsch12hyr32hsnh5yqsaavmhy32d20zx3nfb3kxgv12"
}
+3 -3
View File
@@ -42,11 +42,11 @@ rlp==1.2.0
sauceclient==1.0.0
scrypt==0.8.17
selenium==3.14.1
six==1.10.0
six==1.11.0
urllib3==1.26.3
yarl==1.6.3
zbarlight==3.0
docker==4.4.0
influxdb==5.3.1
web3
imagehash
web3==5.25.0
imagehash
+2 -2
View File
@@ -12,14 +12,14 @@ RERUN_ERRORS = [
'failed to start the browser or device',
'ERROR The test with session id',
"503 Service Unavailable",
# "object has no attribute",
"object has no attribute",
"[Errno 104] Connection reset by peer",
"Sauce could not start your job",
"HTTP Error 303",
"http.client.RemoteDisconnected: Remote end closed connection without response",
"[Errno 110] Connection timed out",
"replacement transaction underpriced",
# "StaleElementReferenceException",
"StaleElementReferenceException",
"'GetStartedButton' is not found on the screen",
"'AccessKeyButton' is not found on the screen",
"'SignInPhraseText' is not found on the screen"
+4 -3
View File
@@ -97,10 +97,11 @@ class TestrailReport(BaseTestReport):
def get_regression_cases(self):
test_cases = dict()
test_cases['critical'] = 734
test_cases['high'] = 735
test_cases['critical'] = 730
test_cases['medium'] = 736
test_cases['upgrade'] = 881
test_cases['public_chat'] = 50654
test_cases['one_to_one_chat'] = 50655
case_ids = list()
for arg in argv:
if "run_testrail_ids" in arg:
@@ -108,7 +109,7 @@ class TestrailReport(BaseTestReport):
case_ids = value.split(',')
if len(case_ids) == 0:
if 'critical or high' in argv:
for case in self.get_cases([test_cases['critical'], test_cases['high']]):
for case in self.get_cases([test_cases['critical'], test_cases['public_chat'], test_cases['one_to_one_chat']]):
case_ids.append(case['id'])
elif 'upgrade' in argv and 'not upgrade' not in argv:
for case in self.get_cases([test_cases['upgrade']]):
@@ -96,7 +96,7 @@ class TestCreateAccount(SingleDeviceTestCase):
sign_in.get_started_button.click()
if sign_in.generate_key_button.is_element_displayed():
self.errors.append("Agree with ToS is not mandatory to proceed onboarding!")
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click_until_presence_of_element(sign_in.generate_key_button)
sign_in.generate_key_button.click()
from views.sign_in_view import MultiAccountButton
@@ -141,7 +141,7 @@ class TestCreateAccount(SingleDeviceTestCase):
@marks.high
def test_pass_phrase_validation(self):
sign_in = SignInView(self.driver)
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click_until_presence_of_element(sign_in.access_key_button)
sign_in.access_key_button.click()
validations = [
@@ -219,7 +219,7 @@ class TestCreateAccount(SingleDeviceTestCase):
@marks.medium
def test_create_account_short_and_mismatch_password(self):
sign_in = SignInView(self.driver)
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click()
sign_in.generate_key_button.click()
sign_in.next_button.click()
@@ -179,7 +179,7 @@ class TestCreateAccount(SingleDeviceTestCase):
sign_in = SignInView(self.driver)
sign_in.just_fyi('Cancel on PIN code setup stage')
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click()
sign_in.generate_key_button.click()
username = sign_in.first_username_on_choose_chat_name.text
@@ -232,7 +232,7 @@ class TestCreateAccount(SingleDeviceTestCase):
@marks.flaky
def test_keycard_interruption_access_key_onboarding_flow(self):
sign_in = SignInView(self.driver)
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click()
sign_in.access_key_button.click()
@@ -277,7 +277,7 @@ class TestCreateAccount(SingleDeviceTestCase):
recovered_user = transaction_senders['A']
sign_in.just_fyi('Recover multiaccount')
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click_until_presence_of_element(sign_in.access_key_button)
sign_in.access_key_button.click()
sign_in.recover_with_keycard_button.click()
@@ -324,7 +324,7 @@ class TestCreateAccount(SingleDeviceTestCase):
sign_in.toggle_airplane_mode()
sign_in.just_fyi('Recover multiaccount offline')
sign_in.accept_tos_checkbox.click()
sign_in.accept_tos_checkbox.enable()
sign_in.get_started_button.click_until_presence_of_element(sign_in.access_key_button)
sign_in.access_key_button.click()
sign_in.recover_with_keycard_button.click()
@@ -673,7 +673,7 @@ class TestKeycardCreateMultiaccountMultipleDevice(MultipleDeviceTestCase):
device_1, device_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
device_1.just_fyi("Create keycard account and save seed phrase")
device_1.accept_tos_checkbox.click()
device_1.accept_tos_checkbox.enable()
device_1.get_started_button.click()
device_1.generate_key_button.click_until_presence_of_element(device_1.next_button)
device_1.next_button.click_until_absense_of_element(device_1.element_by_translation_id("intro-wizard-title2"))
@@ -1219,7 +1219,7 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase):
@marks.testrail_id(695856)
@marks.medium
@marks.flaky
#@marks.flaky
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])
@@ -1296,12 +1296,12 @@ class TestProfileMultipleDevice(MultipleDeviceTestCase):
[home.home_button.double_click() for home in (home_1, home_2)]
home_1.get_chat(comm_before_sync_name, community=True).click()
comm_before_1.leave_community()
if not home_2.get_chat(comm_before_sync_name).is_element_disappeared(30):
if not home_2.element_by_text_part(comm_before_sync_name).is_element_disappeared(30):
self.errors.append("Leaving community was not synced!")
device_1.just_fyi("Adding new community and check it will be synced")
home_1.create_community(comm_after_sync_name)
if not home_2.get_chat(comm_after_sync_name, community=True).is_element_displayed(30):
if not home_2.element_by_text(comm_after_sync_name).is_element_displayed(30):
self.errors.append('Added community was not appeared after initial sync')
# TODO: skip until #11558 (rechecked 23.11.21, valid)
@@ -168,7 +168,10 @@ class TestWalletManagement(SingleDeviceTestCase):
self.errors.append('%s asset is not shown in wallet after relogin' % asset)
sign_in.just_fyi("Deselecting asset")
wallet.select_asset(asset)
wallet.multiaccount_more_options.click()
wallet.manage_assets_button.click()
wallet.asset_checkbox_by_name(asset).click()
wallet.cross_icon.click()
if wallet.asset_by_name(asset).is_element_displayed():
self.errors.append('%s asset is shown in wallet but was deselected' % asset)
self.errors.verify_no_errors()
@@ -696,7 +696,6 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
if public_chat_after_block_1.chat_element_by_text(message_after_block_2).is_element_displayed():
self.errors.append("Message from blocked user '%s' is received" % device_2.driver.number)
public_chat_after_block_1.get_back_to_home_view()
if home_1.notifications_unread_badge.is_element_displayed():
device_1.driver.fail("Unread badge is shown after receiving new message from blocked user")
if blocked_chat_user.is_element_displayed():
@@ -718,6 +717,7 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
device_1.click_system_home_button()
self.drivers[0].launch_app()
device_1.sign_in()
public_chat_after_block_1.home_button.double_click()
if home_1.notifications_unread_badge.is_element_displayed():
device_1.driver.fail("Unread badge is shown after after fetching new messages from offline")
if blocked_chat_user.is_element_displayed():
@@ -45,7 +45,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
chat_2 = home_2.get_chat(sender['username']).click()
receiver_message = chat_2.get_incoming_transaction(account_name)
timestamp_sender = sender_message.timestamp_message.text
timestamp_sender = sender_message.timestamp_command_message.text
if not receiver_message.is_element_displayed():
self.drivers[0].fail('No message about incoming transaction in 1-1 chat is shown for receiver')
receiver_message.transaction_status.wait_for_element_text(receiver_message.address_requested)
@@ -68,7 +68,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
send_bottom_sheet = sender_message.sign_and_send.click()
send_bottom_sheet.next_button.click()
send_bottom_sheet.sign_transaction()
updated_timestamp_sender = sender_message.timestamp_message.text
updated_timestamp_sender = sender_message.timestamp_command_message.text
if updated_timestamp_sender == timestamp_sender:
self.errors.append("Timestamp of message is not updated after signing transaction")
chat_1.wallet_button.click()
@@ -40,7 +40,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
chat_2 = home_2.get_chat(sender['username']).click()
receiver_message = chat_2.get_incoming_transaction()
timestamp_sender = sender_message.timestamp_message.text
timestamp_sender = sender_message.timestamp_command_message.text
if not receiver_message.is_element_displayed():
self.drivers[0].fail('No message about incoming transaction in 1-1 chat is shown for receiver')
receiver_message.transaction_status.wait_for_element_text(receiver_message.address_requested)
@@ -63,7 +63,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
send_message = sender_message.sign_and_send.click()
send_message.next_button.click()
send_message.sign_transaction(keycard=True)
updated_timestamp_sender = sender_message.timestamp_message.text
updated_timestamp_sender = sender_message.timestamp_command_message.text
if updated_timestamp_sender == timestamp_sender:
self.errors.append("Timestamp of message is not updated after signing transaction")
@@ -109,8 +109,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
home_1.just_fyi('go back online and check that 1-1 chat will be fetched')
home_1.toggle_airplane_mode()
chat_element = home_1.get_chat(username_2)
chat_element.wait_for_visibility_of_element(30)
chat_element = home_1.get_chat(username_2, wait_time=60)
chat_1 = chat_element.click()
chat_1.chat_element_by_text(message_1).wait_for_visibility_of_element(2)
@@ -162,13 +161,14 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase):
if device_2_chat.user_name_text.text != default_username_1:
self.errors.append("Default username '%s' is not shown in one-to-one chat" % default_username_1)
profile_1.just_fyi("Check timestamps for sender and receiver")
for chat in device_1_chat, device_2_chat:
chat.verify_message_is_under_today_text(timestamp_message, self.errors)
timestamp = chat.chat_element_by_text(timestamp_message).timestamp_message.text
if timestamp not in sent_time_variants:
self.errors.append(
"Timestamp is not shown, expected '%s', in fact '%s'" % (sent_time_variants.join(","), timestamp))
# TODO: disabled until https://github.com/status-im/status-react/issues/12936 fix
# profile_1.just_fyi("Check timestamps for sender and receiver")
# for chat in device_1_chat, device_2_chat:
# chat.verify_message_is_under_today_text(timestamp_message, self.errors)
# timestamp = chat.chat_element_by_text(timestamp_message).timestamp_message.text
# if timestamp not in sent_time_variants:
# self.errors.append(
# "Timestamp is not shown, expected '%s', in fact '%s'" % (sent_time_variants.join(","), timestamp))
device_2_home.just_fyi("Add user to contact and verify his default username")
device_2_chat.add_to_contacts.click()
@@ -883,7 +883,7 @@ class TestMessagesOneToOneChatSingle(SingleDeviceTestCase):
chat.send_message_button.click()
message_bubble = chat.chat_element_by_text(formatted_message[message])
message_bubble.timestamp_message.long_press_element()
message_bubble.sent_status_checkmark.long_press_element()
chat.element_by_text('Copy').click()
message_input.paste_text_from_clipboard()
@@ -964,13 +964,10 @@ class TestMessagesOneToOneChatSingle(SingleDeviceTestCase):
self.errors.append('"%s" is not show in chat preview on home screen!' % message)
home.get_chat('@%s' % ens).click()
home.just_fyi('Check redirect to user profile on mention by ENS tap')
chat.chat_element_by_text(message).click()
if not chat.profile_block_contact.is_element_displayed():
self.errors.append('No redirect to user profile after tapping on message with mention (ENS) in 1-1 chat')
home.just_fyi('Set nickname and mention user by nickname in 1-1 chat')
russian_nickname = 'МОЙ дорогой ДРУх'
chat.chat_options.click()
chat.view_profile_button.click()
chat.set_nickname(russian_nickname)
chat.select_mention_from_suggestion_list(russian_nickname + ' @' + ens)
+66 -108
View File
@@ -9,7 +9,6 @@ from dateutil import parser
from tests import marks
from tests.base_test_case import MultipleDeviceTestCase, SingleDeviceTestCase, create_shared_drivers, \
MultipleSharedDeviceTestCase
from views.home_view import HomeView
from views.sign_in_view import SignInView
@@ -20,104 +19,102 @@ class TestPublicChatMultipleDeviceMerged(MultipleSharedDeviceTestCase):
def setup_class(cls):
cls.drivers, cls.loop = create_shared_drivers(2)
device_1, device_2 = SignInView(cls.drivers[0]), SignInView(cls.drivers[1])
home_1, home_2 = device_1.create_user(), device_2.create_user()
profile_1 = home_1.profile_button.click()
cls.home_1, cls.home_2 = device_1.create_user(), device_2.create_user()
profile_1 = cls.home_1.profile_button.click()
cls.username_1 = profile_1.default_username_text.text
profile_1.home_button.click()
home_2.home_button.click()
cls.home_2.home_button.click()
cls.public_chat_name = cls.home_1.get_random_chat_name()
cls.chat_1, cls.chat_2 = cls.home_1.join_public_chat(cls.public_chat_name), cls.home_2.join_public_chat(cls.public_chat_name)
@marks.testrail_id(5313)
@marks.critical
def test_public_chat_messaging_emojis_timestamps(self):
home_1, home_2 = HomeView(self.drivers[0]), HomeView(self.drivers[1])
home_1.just_fyi("Check preselected chats, redirect to status chat")
home_1.plus_button.click_until_presence_of_element(home_1.join_public_chat_button)
home_1.join_public_chat_button.click()
preselected_chats = ['#status', '#chitchat', '#defi', '#crypto', '#markets', '#dap-ps']
for chat in preselected_chats:
if not home_1.element_by_text(chat).is_element_displayed():
self.errors.append("'%s' text is not in the list of preselected chats" % chat)
home_1.element_by_text(preselected_chats[0]).click()
status_chat = home_1.get_chat_view()
if not status_chat.user_name_text != preselected_chats[0]:
self.errors.append('No redirect to chat if tap on #status chat')
status_chat.home_button.click()
def test_public_chat_text_timestamps_while_on_different_tab(self):
message = 'hello'
self.chat_2.dapp_tab_button.click()
self.chat_1.send_message(message)
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))
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)
if self.chat_2.chat_element_by_text(message).username.text != self.username_1:
self.errors.append("Default username '%s' is not shown next to the received message" % self.username_1)
self.errors.verify_no_errors()
public_chat_name = home_1.get_random_chat_name()
chat_1, chat_2 = home_1.join_public_chat(public_chat_name), home_2.join_public_chat(public_chat_name)
home_1.just_fyi("Check sending text messages, emojis, usernames and timestamps on messages")
@marks.testrail_id(700719)
@marks.critical
def test_public_emoji(self):
emoji_name = random.choice(list(emoji.EMOJI_UNICODE))
emoji_unicode = emoji.EMOJI_UNICODE[emoji_name]
message, emoji_message = 'hello', emoji.emojize(emoji_name)
chat_1.send_message(message)
sent_time_variants = chat_1.convert_device_time_to_chat_timestamp()
for chat in chat_1, chat_2:
chat.verify_message_is_under_today_text(message, self.errors)
timestamp = chat.chat_element_by_text(message).timestamp_message.text
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 chat_2.chat_element_by_text(message).username.text != self.username_1:
self.errors.append("Default username '%s' is not shown next to the received message" % self.username_1)
chat_1.send_message(emoji_message)
for chat in chat_1, chat_2:
if not chat.chat_element_by_text(emoji_unicode).is_element_displayed():
emoji_message = emoji.emojize(emoji_name)
self.chat_1.send_message(emoji_message)
for chat in self.chat_1, self.chat_2:
if not chat.chat_element_by_text(emoji_unicode).is_element_displayed(30):
self.errors.append('Message with emoji was not sent or received in public chat')
self.chat_1.just_fyi("Can copy and paste emojis")
self.chat_1.element_by_text_part(emoji_unicode).long_press_element()
self.chat_1.element_by_text('Copy').click()
self.chat_1.chat_message_input.paste_text_from_clipboard()
if self.chat_1.chat_message_input.text != emoji_unicode:
self.errors.append('Emoji message was not copied')
self.chat_1.just_fyi("Can reply to emojis")
self.chat_2.quote_message(emoji_unicode)
message_text = 'test message'
self.chat_2.chat_message_input.send_keys(message_text)
self.chat_2.send_message_button.click()
chat_element_1 = self.chat_1.chat_element_by_text(message_text)
if not chat_element_1.is_element_displayed(sec=10) or chat_element_1.replied_message_text != emoji_unicode:
self.errors.append('Reply message was not received by the sender')
self.errors.verify_no_errors()
@marks.testrail_id(5360)
@marks.critical
def test_unread_messages_counter_public_chat(self):
home_1, home_2 = HomeView(self.drivers[0]), HomeView(self.drivers[1])
home_1.get_back_to_home_view()
home_2.get_back_to_home_view()
home_1.home_button.click()
home_2.home_button.click()
chat_name = home_1.get_random_chat_name()
chat_1, chat_2 = home_1.join_public_chat(chat_name), home_2.join_public_chat(chat_name)
chat_1.send_message('пиу')
chat_1.home_button.click()
message, message_2 = 'test message', 'test message2'
chat_2.send_message(message)
home_1.just_fyi(
"Check unread message indicator on home, on chat element and that it is not shown after reading messages")
if not home_1.home_button.public_unread_messages.is_element_displayed():
def test_public_unread_messages_counter(self):
self.chat_1.send_message('пиу')
home_1 = self.chat_1.home_button.click()
message = 'test message'
self.chat_2.send_message(message)
if not self.chat_1.home_button.public_unread_messages.is_element_displayed():
self.errors.append('New messages public chat badge is not shown on Home button')
chat_element = home_1.get_chat('#' + chat_name)
chat_element = home_1.get_chat('#' + self.public_chat_name)
if not chat_element.new_messages_public_chat.is_element_displayed():
self.errors.append('New messages counter is not shown in public chat')
self.errors.verify_no_errors()
home_1.just_fyi("Check unread message counter when mentioned in public chat")
chat_2 = home_2.get_chat_view()
chat_2.select_mention_from_suggestion_list(self.username_1, self.username_1[:2])
chat_2.send_message_button.click()
@marks.testrail_id(700718)
@marks.critical
def test_public_unread_messages_counter_for_mentions_relogin(self):
message = 'test message2'
[chat.home_button.double_click() for chat in (self.chat_1, self.chat_2)]
chat_element = self.home_1.get_chat('#' + self.public_chat_name)
self.home_2.get_chat('#' + self.public_chat_name).click()
self.chat_2.select_mention_from_suggestion_list(self.username_1, self.username_1[:2])
self.chat_2.send_message_button.click()
chat_element.new_messages_counter.wait_for_element(30)
chat_element.new_messages_counter.wait_for_element_text("1", 60)
chat_element.click()
home_1.home_button.double_click()
if home_1.home_button.public_unread_messages.is_element_displayed():
self.home_1.home_button.double_click()
if self.home_1.home_button.public_unread_messages.is_element_displayed():
self.errors.append('New messages public chat badge is shown on Home button')
if chat_element.new_messages_public_chat.is_element_displayed():
self.errors.append('Unread messages badge is shown in public chat while there are no unread messages')
[home.get_chat('#' + chat_name).click() for home in (home_1, home_2)]
chat_1.send_message(message_2)
chat_2.chat_element_by_text(message_2).wait_for_element(20)
[home.get_chat('#' + self.public_chat_name).click() for home in (self.home_1, self.home_2)]
self.chat_1.send_message(message)
self.chat_2.chat_element_by_text(message).wait_for_element(20)
home_2.just_fyi("Check that unread message indicator is not reappeared after relogin")
self.chat_2.just_fyi("Check that unread messages counter doesn't reappear after relogin")
driver_2 = self.drivers[1]
driver_2.close_app()
driver_2.launch_app()
SignInView(driver_2).sign_in()
chat_element = home_2.get_chat('#' + chat_name)
chat_element = self.home_2.get_chat('#' + self.public_chat_name)
if chat_element.new_messages_public_chat.is_element_displayed():
self.errors.append('New messages counter is shown after relogin')
self.drivers[0].fail('New messages counter is shown after relogin')
self.errors.verify_no_errors()
@@ -152,45 +149,6 @@ class TestPublicChatMultipleDevice(MultipleDeviceTestCase):
self.errors.verify_no_errors()
@marks.testrail_id(6275)
@marks.medium
def test_receive_message_while_in_different_tab_and_emoji_messages_long_press(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_chat_name = home_1.get_random_chat_name()
chat_1, chat_2 = home_1.join_public_chat(public_chat_name), home_2.join_public_chat(public_chat_name)
device_2.just_fyi("Switch to different tab out from chat")
device_2.dapp_tab_button.click()
emoji_name = random.choice(list(emoji.EMOJI_UNICODE))
emoji_unicode = emoji.EMOJI_UNICODE[emoji_name]
chat_1.chat_message_input.send_keys(emoji.emojize(emoji_name))
chat_1.send_message_button.click()
device_1.just_fyi("Long press emoji message actions")
chat_1.element_by_text_part(emoji_unicode).long_press_element()
chat_1.element_by_text('Copy').click()
chat_1.chat_message_input.paste_text_from_clipboard()
if chat_1.chat_message_input.text != emoji_unicode:
self.errors.append('Emoji message was not copied')
home_2.home_button.click(desired_view='chat')
chat_element_2 = chat_2.element_by_text_part(emoji_unicode)
if not chat_element_2.is_element_displayed(sec=10):
self.errors.append('Message with emoji was not received in public chat by the recipient')
chat_2.quote_message(emoji_unicode)
message_text = 'test message'
chat_2.chat_message_input.send_keys(message_text)
chat_2.send_message_button.click()
chat_element_1 = chat_1.chat_element_by_text(message_text)
if not chat_element_1.is_element_displayed(sec=10) or chat_element_1.replied_message_text != emoji_unicode:
self.errors.append('Reply message was not received by the sender')
self.errors.verify_no_errors()
@marks.testrail_id(6342)
@marks.medium
def test_different_status_in_timeline(self):
+22 -14
View File
@@ -91,6 +91,20 @@ class BaseElement(object):
self.driver.info('Tap on found: %s' % self.name)
return self.navigate()
def click_until_presence_of_element(self, desired_element, attempts=4):
counter = 0
self.driver.info("Click until '%s' by '%s': `%s` will be presented" % (
desired_element.name, desired_element.by, desired_element.locator))
while not desired_element.is_element_present(1) and counter <= attempts:
try:
self.find_element().click()
desired_element.wait_for_element(5)
return self.navigate()
except (NoSuchElementException, TimeoutException):
counter += 1
else:
self.driver.info("%s element not found" % desired_element.name)
def double_click(self):
self.driver.info('Double tap on: %s' % self.name)
[self.find_element().click() for _ in range(2)]
@@ -352,19 +366,6 @@ class Button(BaseElement):
self.wait_for_visibility_of_element(sec)
self.click()
def click_until_presence_of_element(self, desired_element, attempts=4):
counter = 0
self.driver.info("Click until '%s' by '%s': `%s` will be presented" % (
desired_element.name, desired_element.by, desired_element.locator))
while not desired_element.is_element_present(1) and counter <= attempts:
try:
self.find_element().click()
desired_element.wait_for_element(5)
return self.navigate()
except (NoSuchElementException, TimeoutException):
counter += 1
else:
self.driver.info("%s element not found" % desired_element.name)
def click_until_absense_of_element(self, desired_element, attempts=3):
counter = 0
@@ -402,6 +403,13 @@ class SilentButton(Button):
class CheckBox(Button):
def click(self):
def __init__(self, driver, **kwargs):
super(Button, self).__init__(driver, **kwargs)
def enable(self):
super(CheckBox, self).click_until_presence_of_element(Button(self.driver, accessibility_id="checkbox-on"))
return self.navigate()
def disable(self):
super(CheckBox, self).click_until_presence_of_element(Button(self.driver, accessibility_id="checkbox-off"))
return self.navigate()
+1
View File
@@ -84,6 +84,7 @@ class HomeButton(TabButton):
return self.navigate()
class DappTabButton(TabButton):
def __init__(self, driver):
super().__init__(driver, xpath="//*[contains(@content-desc,'tab, 2 out of 5')]")
+18 -2
View File
@@ -143,13 +143,25 @@ class ChatElementByText(Text):
return ''
@property
def timestamp_message(self):
class TimeStampText(Text):
def timestamp_command_message(self):
class TimeStampText(Button):
def __init__(self, driver, parent_locator: str):
super().__init__(driver, xpath="(%s//android.widget.TextView)[last()]" % parent_locator)
return TimeStampText(self.driver, self.locator)
@property
def timestamp_on_tap(self):
timestamp_element = Text(self.driver, xpath="//*[@content-desc='message-timestamp']")
try:
self.sent_status_checkmark.wait_for_element(30)
except NoSuchElementException:
return ''
self.sent_status_checkmark.click_until_presence_of_element(timestamp_element)
return timestamp_element.text
@property
def member_photo(self):
class MemberPhoto(Button):
@@ -191,6 +203,10 @@ class ChatElementByText(Text):
status = 'delivered'
return status
@property
def sent_status_checkmark(self) -> object:
return Text(self.driver, prefix=self.locator, xpath="//*[@content-desc='sent']")
@property
def replied_message_text(self):
class RepliedMessageText(Text):
+3 -3
View File
@@ -195,7 +195,7 @@ class HomeView(BaseView):
self.notifications_accept_and_add_button = Button(self.driver,
accessibility_id="accept-and-add-activity-center")
self.notifications_select_all = Button(self.driver, xpath="(//android.widget.CheckBox["
"@content-desc='checkbox'])[1]")
"@content-desc='checkbox-off'])[1]")
# Options on long tap
self.chats_menu_invite_friends_button = Button(self.driver, accessibility_id="chats-menu-invite-friends-button")
@@ -231,11 +231,11 @@ class HomeView(BaseView):
except TimeoutException:
break
def get_chat(self, username, community=False):
def get_chat(self, username, community=False,wait_time=30):
self.driver.info("Looking for chat: '%s'" % username)
chat_element = ChatElement(self.driver, username[:25], community=community)
if not chat_element.is_element_displayed():
self.notifications_unread_badge.wait_and_click(30)
self.notifications_unread_badge.wait_and_click(wait_time)
chat_in_ac = ActivityCenterChatElement(self.driver, username[:25])
chat_in_ac.wait_for_element(20)
chat_in_ac.click()
+1
View File
@@ -38,6 +38,7 @@ class KeycardView(BaseView):
def get_recovery_word(self, word_id):
word_element = SilentButton(self.driver, accessibility_id="word%s" % word_id)
word_element.wait_for_visibility_of_element()
return word_element.text
def get_required_word_number(self):
+2 -2
View File
@@ -176,7 +176,7 @@ class SignInView(BaseView):
self.driver.info("## Creating new multiaccount (password:'%s', keycard:'%s')" % (password, str(keycard)),
device=False)
if not second_user:
self.accept_tos_checkbox.click()
self.accept_tos_checkbox.enable()
self.get_started_button.click_until_presence_of_element(self.generate_key_button)
self.generate_key_button.click()
@@ -204,7 +204,7 @@ class SignInView(BaseView):
enable_notifications=False, second_user=False):
self.driver.info("## Recover access(password:%s, keycard:%s)" % (password, str(keycard)), device=False)
if not second_user:
self.accept_tos_checkbox.click()
self.accept_tos_checkbox.enable()
self.get_started_button.click_until_presence_of_element(self.access_key_button)
self.access_key_button.click()
self.enter_seed_phrase_button.click()
+3 -5
View File
@@ -18,9 +18,9 @@ class AssetCheckBox(CheckBox):
def __init__(self, driver, asset_name):
super().__init__(driver, xpath="//*[@text='%s']" % asset_name)
def click(self):
def enable(self):
self.scroll_to_element(12)
super().click()
super().enable()
class BackupRecoveryPhrase(Button):
@@ -102,8 +102,6 @@ class WalletView(BaseView):
self.manage_assets_button = Button(self.driver, accessibility_id="wallet-manage-assets")
self.manage_accounts_button = Button(self.driver, accessibility_id="wallet-manage-accounts")
self.scan_tokens_button = Button(self.driver, accessibility_id="wallet-scan-token")
self.stt_check_box = CheckBox(self.driver,
xpath="//*[@text='STT']/../android.view.ViewGroup[@content-desc='checkbox-off']")
self.all_assets_full_names = Text(self.driver,
xpath="//*[@content-desc='checkbox-off']/../android.widget.TextView[1]")
self.all_assets_symbols = Button(self.driver,
@@ -270,7 +268,7 @@ class WalletView(BaseView):
self.multiaccount_more_options.click()
self.manage_assets_button.click()
for asset in args:
self.asset_checkbox_by_name(asset).click()
self.asset_checkbox_by_name(asset).enable()
self.cross_icon.click()
def scan_tokens(self, *args):
+29 -3
View File
@@ -184,7 +184,7 @@
"membership-request-pending": "Membership request pending",
"create-community": "Create a community",
"create-category": "Create category",
"reorder-categories": "Reorder categories",
"rearrange-categories": "Rearrange Categories",
"edited": "Edited",
"edit-community": "Edit community",
"editing-message": "Editing message",
@@ -412,6 +412,7 @@
"delete-bootnode-title": "Delete bootnode",
"delete-chat": "Delete chat",
"delete-chat-confirmation": "Are you sure you want to delete this chat?",
"delete-category-confirmation": "Are you sure you want to delete this category?",
"delete-confirmation": "Delete?",
"delete-mailserver": "Delete Status node",
"delete-mailserver-are-you-sure": "Are you sure you want to delete this Status node?",
@@ -1344,7 +1345,6 @@
"welcome-blank-message": "Your chats will appear here. To start new chats press the ⊕ button",
"welcome-community-blank-message": "Your channels will appear here. To create a new channel, click on the ⊕ button and select \"Create a channel\"",
"welcome-community-blank-message-edit-chats": "Your channels will appear here. To create a new channel, go back to the community screen, click on the ⊕ button and select \"Create a channel\"",
"welcome-community-blank-message-categories": "Your categories will appear here. To create a new category, go back to the community screen, click on the ⊕ button and select \"Create category\"",
"welcome-blank-community-message": "Your communities will appear here.",
"fetch-community": "Fetch community",
"fetching-community": "Fetching community...",
@@ -1703,5 +1703,31 @@
"status-dnd-subtitle": "Mutes all notifications",
"status-always-online": "Always Online",
"status-inactive": "Inactive",
"status-inactive-subtitle": "Hides your online status"
"status-inactive-subtitle": "Hides your online status",
"two-minutes": "two minutes",
"swap": "Swap",
"select-token-to-swap": "Select token to Swap",
"select-token-to-receive": "Select token to receive",
"minimum-received": "Minimum received",
"powered-by-paraswap": "Powered by Paraswap",
"priority": "Priority",
"switch-to-simple-interface":"Switch to simple interface",
"transaction-fee": "Transaction fee",
"swap-details": "Swap details",
"slippage": "Slippage",
"price-impact": "Price impact",
"total-gas": "Total gas",
"token": "Token",
"approve-limit": "Approve limit",
"approve-token": "Approve token",
"approve-token-contract-desc": "Approving a token with a contract allows it to spend your token balance. If you feel that a project is untrustworthy, dont approve the token with them, or approve only the amount you will use with them.",
"unlimited": "Unlimited",
"approve": "Approve",
"limit": "Limit",
"last-transaction": "Last transaction",
"price-impact-desc": "Estimated price impact for this transaction. If the current block base fee exceeds this, your transaction will be included in a following block with a lower base fee.",
"safe-estimate": "Safe estimate",
"current-average": "Current average",
"current-base": "Current base",
"maximum-fee-desc": "Maximum overall price for the transaction. If the current block base fee exceeds this, your transaction will be included in a following block with a lower base fee."
}
+5
View File
@@ -6618,6 +6618,11 @@ react-native-dialogs@^1.0.4:
resolved "https://registry.yarnpkg.com/react-native-dialogs/-/react-native-dialogs-1.1.0.tgz#8f7ee7f9d96574fc878fb7c1be101611fb4af517"
integrity sha512-clnxO0nMyML/6+G5dja3Yt34gPxegLY2OHTwb8BwYTEvQ2UhRKR49Uq91XqU0q6g7Ur9DiYxC0tqV3rcZWUrjQ==
react-native-draggable-flatlist@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/react-native-draggable-flatlist/-/react-native-draggable-flatlist-3.0.3.tgz#e85503585253be01ad251f78d5b341ac22f9d952"
integrity sha512-bDro6aqQMvvTm/CuHre9dAjSBKosAfZRLDx3nmrjOz799kxcn0bq+uCB6yF6m+g1Xd/gVPl7E3Ss4uX+oPUlHg==
react-native-fast-image@8.5.11:
version "8.5.11"
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz#e3dc969d0e4e8df026646bf18194465aa55cbc2b"