Compare commits

...
28 Commits
Author SHA1 Message Date
ibrkhalil 09d1293010 Add case for transparent 2022-11-22 14:52:23 +02:00
ibrkhalil 8f7537f0e7 User list component
Signed-off-by: ibrkhalil <vampirekid017@gmail.com>
2022-11-22 14:41:51 +02:00
Brian Sztamfater 4a87122336 feat: author component
Signed-off-by: Brian Sztamfater <brian@status.im>
2022-11-21 15:46:56 -03:00
Roman Volosovskyi d18c3ad102 [#14381] Wrap texts with view to ensure separate accessibility labels 2022-11-21 15:40:29 +01:00
Icaro Motta e53f58d8c0 Fix various Activity Log layout issues (#14405) 2022-11-21 11:19:50 -03:00
Omar Basem 5492fb472f Group Details Screen (#14377)
* feat: group details screen
2022-11-21 16:03:49 +04:00
flexsurfer c08d58577d move quo preview (#14409) 2022-11-21 11:03:07 +01:00
Yevheniia Berdnyk 946640339a e2e: pin messages in 1-1 and group chats 2022-11-21 06:49:53 +02:00
Jamie CapraniandErik Seppanen 72d43ba745 Visual tests setup (#14329)
feat: configuration setup for visual tests

Co-authored-by: Erik Seppanen <esep@protonmail.com>
2022-11-20 15:46:04 -08:00
Icaro Motta f4d9162ff8 Fix reconciliation for new filter type :all (#14401) 2022-11-18 06:15:39 -03:00
Omar Basem 73bbfa7d31 Fix Metro Warnings ⚠️ (#14389)
* fix: metro warnings ⚠️
2022-11-17 21:19:54 +04:00
Mohamed Javid 84da3128bf [Fix] Activity Centre UI bug (#14398)
* [Fix] Activity Centre UI bug

* [Fix] Namespace update for config

* [Chore] Moved navigation to Activity Center as reframe event

* [Chore] Code Format
2022-11-18 00:15:49 +08:00
flexsurfer 3777ebc36e move communities 2 (#14394) 2022-11-17 16:43:02 +01:00
Roman Volosovskyi 4c6b4e2d02 [#14388] Re-enable bug reporting 2022-11-17 15:01:45 +01:00
Roman Volosovskyi e469d97702 [#14372] Fix message content type on editing 2022-11-17 08:23:53 +01:00
Roman Volosovskyi cf753a0892 [#14381] Add accessibility lables for chat key and timestamp in message 2022-11-17 07:16:30 +01:00
Icaro Motta 0f7ccce3df Implement identity verification flow (#14365) 2022-11-16 16:46:04 -03:00
Mohamed Javid 509ffc2a01 [Feature] Added messages skeleton (#14072)
* [Feature][#14025] Added Messages Skeleton while loading messages

* [Improvements][#14025] Added animation to message skeleton

* [Improvements][#14025] Changed to Reanimated2 for message skeleton animation

* [Chores][#14025] Removed unused code

* [Improvements][#14025] Added preview screen for messages skeleton

* [Improvements][#14025] Style update for messages skeleton

* [Chore][#14025] Indentation for message skeleton

* [Improvements][#14025] On Layout calculation cleanup

* [Fix][#14025] Added Skeleton on New UI only

* [Chore] Moved Message Skeleton to new UI

* [Feature][#14025] Added Message Skeleton on message gap

* [TEMP][#14025] Added delay of preloading messages for testing

* [Lint][#14025] Lint fixes for Message Gap component

* [Chore][#14025] Reanimated namespace update

* [Chore][#14025] React native namespace update

* [Chore][#14025] Rollback preload messages
2022-11-17 00:43:58 +08:00
John Ngei e44d4c83c0 communites home screen context actions (#14371) 2022-11-16 17:48:18 +03:00
flexsurfer cc733a379c move communities (#14384) 2022-11-16 14:09:16 +01:00
flexsurfer 803328dc4c move switcher (#14378)
* move switcher
2022-11-16 12:00:16 +01:00
Roman Volosovskyi 255049c312 Fix uniq :key warning on opening chat 2022-11-16 10:46:32 +01:00
flexsurfer 31b6e076be new structure continue, move utils, move fx macro to re-frame utils n… (#14373)
* new structure continue, move utils, move fx macro to re-frame utils namespace
2022-11-16 09:09:25 +01:00
frank 433f9185c8 Use WakuNodes in ClusterConfig for Waku V2 (#14283) 2022-11-16 00:27:19 +08:00
Andrea Maria Piana 04408af45c Fix logout & upgrade status-go 2022-11-15 15:17:59 +00:00
Omar Basem ea7548d54a Confirmation Dialog (#14348)
* feat: confirmation dialog
2022-11-15 17:34:38 +04:00
Andrea Maria Piana c7ac53fdd0 Add icons & mentions/unread counts to community list 2022-11-15 13:03:48 +00:00
Roman Volosovskyi 48f86ff862 [#14311] Fix icons in message actions bottom sheet 2022-11-15 13:29:12 +01:00
197 changed files with 6228 additions and 3724 deletions
+2 -1
View File
@@ -2,12 +2,13 @@
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:invalid-arity {:skip-args [status-im.utils.fx/defn]}
:linters {:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;;TODO remove number when this is fixed
;;https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY number]}}}
+37
View File
@@ -0,0 +1,37 @@
module.exports = {
"testRunner": "jest",
"testRegex": "\\.visual\\.js$",
"runner-config": "visual-test/config.json",
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 11 Pro"
}
}
},
"apps": {
"ios.release": {
"name": "StatusIm",
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/StatusIm.app",
"build": "make release-ios"
},
"ios.debug": {
"name": "StatusIm",
"type": "ios.app",
"binaryPath": process.env.TEST_BINARY_PATH,
"build": "make run-ios SIMULATOR='iPhone 11 Pro'"
}
},
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "ios.release"
},
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
}
}
}
+3
View File
@@ -175,3 +175,6 @@ test/appium/tests/users.py
##node bindings
/bin/
/lib/
## visual tests
/artifacts
+11 -1
View File
@@ -48,7 +48,7 @@ export _NIX_GCROOTS = /nix/var/nix/gcroots/per-user/$(USER)/status-mobile
# Defines which variables will be kept for Nix pure shell, use semicolon as divider
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,STATUS_GO_SRC_OVERRIDE
# Useful for Andoird release builds
# Useful for Android release builds
TMP_BUILD_NUMBER := $(shell ./scripts/version/gen_build_no.sh | cut -c1-10)
# MacOS root is read-only, read nix/README.md for details
@@ -313,6 +313,16 @@ test: ##@test Run tests once in NodeJS
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js target/test/test.js
run-visual-test-ios: export TARGET := clojure
run-visual-test-ios: XCODE_DERIVED_DATA := $(HOME)/Library/Developer/Xcode/DerivedData
run-visual-test-ios: APPLICATION_NAME := $(shell ls $(XCODE_DERIVED_DATA) | grep -E '\bStatusIm-')
run-visual-test-ios: export TEST_BINARY_PATH := $(XCODE_DERIVED_DATA)/$(APPLICATION_NAME)/Build/Products/Debug-iphonesimulator/StatusIm.app
run-visual-test-ios: ##@test Run tests once in NodeJS
yarn install
detox build --configuration ios.sim.debug && \
detox test --configuration ios.sim.debug
#--------------
# Other
#--------------
+1 -1
View File
@@ -62,7 +62,7 @@ pipeline {
--rerun_count=2 \
--testrail_report=True \
-m testrail_id \
-m \"new_ui_critical\" \
-m \"new_ui_critical or new_ui_medium\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_NAME}
"""
+179 -179
View File
@@ -4,14 +4,14 @@ PODS:
- React
- CryptoSwift (1.5.1)
- DoubleConversion (1.1.6)
- FBLazyVector (0.63.4)
- FBReactNativeSpec (0.63.4):
- FBLazyVector (0.63.5)
- FBReactNativeSpec (0.63.5):
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.4)
- RCTTypeSafety (= 0.63.4)
- React-Core (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- RCTRequired (= 0.63.5)
- RCTTypeSafety (= 0.63.5)
- React-Core (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
@@ -40,172 +40,172 @@ PODS:
- RNPermissions
- Permission-Microphone (2.1.5):
- RNPermissions
- RCTRequired (0.63.4)
- RCTTypeSafety (0.63.4):
- FBLazyVector (= 0.63.4)
- RCTRequired (0.63.5)
- RCTTypeSafety (0.63.5):
- FBLazyVector (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.4)
- React-Core (= 0.63.4)
- React (0.63.4):
- React-Core (= 0.63.4)
- React-Core/DevSupport (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-RCTActionSheet (= 0.63.4)
- React-RCTAnimation (= 0.63.4)
- React-RCTBlob (= 0.63.4)
- React-RCTImage (= 0.63.4)
- React-RCTLinking (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- React-RCTSettings (= 0.63.4)
- React-RCTText (= 0.63.4)
- React-RCTVibration (= 0.63.4)
- React-callinvoker (0.63.4)
- React-Core (0.63.4):
- RCTRequired (= 0.63.5)
- React-Core (= 0.63.5)
- React (0.63.5):
- React-Core (= 0.63.5)
- React-Core/DevSupport (= 0.63.5)
- React-Core/RCTWebSocket (= 0.63.5)
- React-RCTActionSheet (= 0.63.5)
- React-RCTAnimation (= 0.63.5)
- React-RCTBlob (= 0.63.5)
- React-RCTImage (= 0.63.5)
- React-RCTLinking (= 0.63.5)
- React-RCTNetwork (= 0.63.5)
- React-RCTSettings (= 0.63.5)
- React-RCTText (= 0.63.5)
- React-RCTVibration (= 0.63.5)
- React-callinvoker (0.63.5)
- React-Core (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-Core/Default (= 0.63.5)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/CoreModulesHeaders (0.63.4):
- React-Core/CoreModulesHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/Default (0.63.4):
- React-Core/Default (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/DevSupport (0.63.4):
- React-Core/DevSupport (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-jsinspector (= 0.63.4)
- React-Core/Default (= 0.63.5)
- React-Core/RCTWebSocket (= 0.63.5)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- React-jsinspector (= 0.63.5)
- Yoga
- React-Core/RCTActionSheetHeaders (0.63.4):
- React-Core/RCTActionSheetHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTAnimationHeaders (0.63.4):
- React-Core/RCTAnimationHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTBlobHeaders (0.63.4):
- React-Core/RCTBlobHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTImageHeaders (0.63.4):
- React-Core/RCTImageHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTLinkingHeaders (0.63.4):
- React-Core/RCTLinkingHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTNetworkHeaders (0.63.4):
- React-Core/RCTNetworkHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTSettingsHeaders (0.63.4):
- React-Core/RCTSettingsHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTTextHeaders (0.63.4):
- React-Core/RCTTextHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTVibrationHeaders (0.63.4):
- React-Core/RCTVibrationHeaders (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-Core/RCTWebSocket (0.63.4):
- React-Core/RCTWebSocket (0.63.5):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-Core/Default (= 0.63.5)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsiexecutor (= 0.63.5)
- Yoga
- React-CoreModules (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- React-CoreModules (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/CoreModulesHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTImage (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-cxxreact (0.63.4):
- RCTTypeSafety (= 0.63.5)
- React-Core/CoreModulesHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- React-RCTImage (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-cxxreact (0.63.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2020.01.13.00)
- glog
- React-callinvoker (= 0.63.4)
- React-jsinspector (= 0.63.4)
- React-jsi (0.63.4):
- React-callinvoker (= 0.63.5)
- React-jsinspector (= 0.63.5)
- React-jsi (0.63.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2020.01.13.00)
- glog
- React-jsi/Default (= 0.63.4)
- React-jsi/Default (0.63.4):
- React-jsi/Default (= 0.63.5)
- React-jsi/Default (0.63.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2020.01.13.00)
- glog
- React-jsiexecutor (0.63.4):
- React-jsiexecutor (0.63.5):
- DoubleConversion
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsinspector (0.63.4)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- React-jsinspector (0.63.5)
- react-native-background-timer (2.2.0):
- React
- react-native-blob-util (0.13.18):
@@ -243,66 +243,66 @@ PODS:
- React
- react-native-webview (11.16.0):
- React-Core
- React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4)
- React-RCTAnimation (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- React-RCTActionSheet (0.63.5):
- React-Core/RCTActionSheetHeaders (= 0.63.5)
- React-RCTAnimation (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTAnimationHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTBlob (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- RCTTypeSafety (= 0.63.5)
- React-Core/RCTAnimationHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTBlob (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTImage (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- React-Core/RCTBlobHeaders (= 0.63.5)
- React-Core/RCTWebSocket (= 0.63.5)
- React-jsi (= 0.63.5)
- React-RCTNetwork (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTImage (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTImageHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTLinking (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- React-Core/RCTLinkingHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTNetwork (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- RCTTypeSafety (= 0.63.5)
- React-Core/RCTImageHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- React-RCTNetwork (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTLinking (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- React-Core/RCTLinkingHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTNetwork (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTNetworkHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTSettings (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- RCTTypeSafety (= 0.63.5)
- React-Core/RCTNetworkHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTSettings (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTSettingsHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTText (0.63.4):
- React-Core/RCTTextHeaders (= 0.63.4)
- React-RCTVibration (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- RCTTypeSafety (= 0.63.5)
- React-Core/RCTSettingsHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- React-RCTText (0.63.5):
- React-Core/RCTTextHeaders (= 0.63.5)
- React-RCTVibration (0.63.5):
- FBReactNativeSpec (= 0.63.5)
- Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- ReactCommon/turbomodule/core (0.63.4):
- React-Core/RCTVibrationHeaders (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactCommon/turbomodule/core (= 0.63.5)
- ReactCommon/turbomodule/core (0.63.5):
- DoubleConversion
- Folly (= 2020.01.13.00)
- glog
- React-callinvoker (= 0.63.4)
- React-Core (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-callinvoker (= 0.63.5)
- React-Core (= 0.63.5)
- React-cxxreact (= 0.63.5)
- React-jsi (= 0.63.5)
- ReactNativeAudioToolkit (2.0.3):
- React
- ReactNativeNavigation (7.27.1):
@@ -637,25 +637,25 @@ SPEC CHECKSUMS:
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CryptoSwift: c4f2debceb38bf44c80659afe009f71e23e4a082
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
FBLazyVector: 352a8ca9bbc8e2f097d680747a8c97ecef12d469
FBReactNativeSpec: 7dfb84f624136a45727c813ed21d130cd3e61beb
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 997518ea2aa2d8cd5df9797b641b758d52ecf2bc
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c
RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e
RCTTypeSafety: 8c9c544ecbf20337d069e4ae7fd9a377aadf504b
React: b0a957a2c44da4113b0c4c9853d8387f8e64e615
React-callinvoker: c3f44dd3cb195b6aa46621fff95ded79d59043fe
React-Core: d3b2a1ac9a2c13c3bcde712d9281fc1c8a5b315b
React-CoreModules: 0581ff36cb797da0943d424f69e7098e43e9be60
React-cxxreact: c1480d4fda5720086c90df537ee7d285d4c57ac3
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
RCTRequired: 5520387431beaa5f32aa8726bf746cd5353119fe
RCTTypeSafety: bc90d6e287fa427c50ed770922bac30faf0bbfa3
React: 83a7f231f462b09260a53c5c51005e7659c66890
React-callinvoker: 1c3fdb5562c792212e149637b8a167516bb4b58e
React-Core: 8baca8644a516e772c77e3923697cfe2b58c1606
React-CoreModules: 200c931e17b332024c2e9d878f67b87c00c2c83b
React-cxxreact: 9096ebaeebf6a1475a14448fa8bfc380c13d7882
React-jsi: 7d908b17758178b076a05a254523f1a4227b53d2
React-jsiexecutor: e06a32e42affb2bd89e4c8369349b5fcf787710c
React-jsinspector: fdbc08866b34ae8e1b788ea1cbd9f9d1ca2aa3d6
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: 4568dd93d1d82748c180df8beb2d929c97b13b47
@@ -673,16 +673,16 @@ SPEC CHECKSUMS:
react-native-status: 21f75d492fd311dc111303da38a7a2b23a8a8466
react-native-status-keycard: f60ca57d789aad6875c64ece81ab06ef0609e0d3
react-native-webview: 28a8636d97ee641f2ee8f20492d7a6c269c1d703
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
React-RCTImage: c1b1f2d3f43a4a528c8946d6092384b5c880d2f0
React-RCTLinking: 35ae4ab9dc0410d1fcbdce4d7623194a27214fb2
React-RCTNetwork: 29ec2696f8d8cfff7331fac83d3e893c95ef43ae
React-RCTSettings: 60f0691bba2074ef394f95d4c2265ec284e0a46a
React-RCTText: 5c51df3f08cb9dedc6e790161195d12bac06101c
React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d
ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b
React-RCTActionSheet: e911b99f0d6fa7711ffc2f62d236b12a32771835
React-RCTAnimation: ad8b853170a059faf31d6add34f67d22391bbe01
React-RCTBlob: 134c7270b6672c9c05383b2e0f7f044ba39d7dda
React-RCTImage: c5c74ba8850a193d73aef8efb8fcbb4f9cad7653
React-RCTLinking: 12468e952704555c8cb4e3de94c7b5a266811326
React-RCTNetwork: e9cfaeb9f3657ae91f895e798734141db6e1af5b
React-RCTSettings: 9a09419bd5e8494f6e146e2c9f5c8e2c6e90ed58
React-RCTText: 393f059d7ec02c733da57240694201e734f0dc84
React-RCTVibration: 3e83f53610d63d3c1fc4db303305e934e73047cc
ReactCommon: b9ff54b6dd22ba4a776eda22d7f83ec27544ca35
ReactNativeAudioToolkit: de9610f323e855ac6574be8c99621f3d57c5df06
ReactNativeNavigation: 94979dd1572a3f093fc85d4599360530a1bed8c8
RNCAsyncStorage: b2489b49e38c85e10ed45a888d13a2a4c7b32ea1
@@ -708,7 +708,7 @@ SPEC CHECKSUMS:
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
Yoga: 0276e9f20976c8568e107cfc1163a8629051adc0
PODFILE CHECKSUM: a1de9468266e7f0b5273acea713782ab759690f1
+4 -1
View File
@@ -84,7 +84,10 @@
"@babel/preset-env": "7.1.0",
"@babel/register": "7.0.0",
"@mapbox/node-pre-gyp": "^1.0.9",
"jest": "^25.1.0",
"@types/jest": "^28.1.6",
"detox": "^19.9.1",
"jest-image-snapshot": "^5.1.0",
"jest": "^28.1.3",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
"process": "0.11.10",
+161 -127
View File
@@ -1,131 +1,165 @@
{
"fleets": {
"eth.prod": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.prod": "enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443",
"boot-01.do-ams3.eth.prod": "enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443",
"boot-01.gc-us-central1-a.eth.prod": "enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443",
"boot-02.ac-cn-hongkong-c.eth.prod": "enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443",
"boot-02.do-ams3.eth.prod": "enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443",
"boot-02.gc-us-central1-a.eth.prod": "enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.prod": "enode://606ae04a71e5db868a722c77a21c8244ae38f1bd6e81687cc6cfe88a3063fa1c245692232f64f45bd5408fed5133eab8ed78049332b04f9c110eac7f71c1b429@47.75.247.214:443",
"mail-01.do-ams3.eth.prod": "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@178.128.142.54:443",
"mail-01.gc-us-central1-a.eth.prod": "enode://ee2b53b0ace9692167a410514bca3024695dbf0e1a68e1dff9716da620efb195f04a4b9e873fb9b74ac84de801106c465b8e2b6c4f0d93b8749d1578bfcaf03e@104.197.238.144:443",
"mail-02.ac-cn-hongkong-c.eth.prod": "enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443",
"mail-02.do-ams3.eth.prod": "enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@178.128.142.26:443",
"mail-02.gc-us-central1-a.eth.prod": "enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443",
"mail-03.ac-cn-hongkong-c.eth.prod": "enode://e85f1d4209f2f99da801af18db8716e584a28ad0bdc47fbdcd8f26af74dbd97fc279144680553ec7cd9092afe683ddea1e0f9fc571ebcb4b1d857c03a088853d@47.244.129.82:443",
"mail-03.do-ams3.eth.prod": "enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@178.128.142.94:443",
"mail-03.gc-us-central1-a.eth.prod": "enode://44160e22e8b42bd32a06c1532165fa9e096eebedd7fa6d6e5f8bbef0440bc4a4591fe3651be68193a7ec029021cdb496cfe1d7f9f1dc69eb99226e6f39a7a5d4@35.225.221.245:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.prod": "/ip4/47.75.99.169/tcp/30703/ethv4/16Uiu2HAmV8Hq9e3zm9TMVP4zrVHo3BjqW5D6bDVV6VQntQd687e4",
"boot-01.do-ams3.eth.prod": "/ip4/178.128.138.128/tcp/30703/ethv4/16Uiu2HAmRHPzF3rQg55PgYPcQkyvPVH9n2hWsYPhUJBZ6kVjJgdV",
"boot-01.gc-us-central1-a.eth.prod": "/ip4/34.70.75.208/tcp/30703/ethv4/16Uiu2HAm6ZsERLx2BwVD2UM9SVPnnMU6NBycG8XPtu8qKys5awsU",
"boot-02.ac-cn-hongkong-c.eth.prod": "/ip4/47.52.106.107/tcp/30703/ethv4/16Uiu2HAmEHiptiDDd9gqNY8oQqo8hHUWMHJzfwt5aLRdD6W2zcXR",
"boot-02.do-ams3.eth.prod": "/ip4/178.128.140.188/tcp/30703/ethv4/16Uiu2HAmLqTXuY4Sb6G28HNooaFUXUKzpzKXCcgyJxgaEE2i5vnf",
"boot-02.gc-us-central1-a.eth.prod": "/ip4/35.223.215.156/tcp/30703/ethv4/16Uiu2HAmQEUFE2YaJohavWtHxPTEFv3sEGJtDqvtGEv78DFoEWQF"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.prod": "enode://b957e51f41e4abab8382e1ea7229e88c6e18f34672694c6eae389eac22dab8655622bbd4a08192c321416b9becffaab11c8e2b7a5d0813b922aa128b82990dab@47.75.222.178:443",
"node-01.do-ams3.eth.prod": "enode://66ba15600cda86009689354c3a77bdf1a97f4f4fb3ab50ffe34dbc904fac561040496828397be18d9744c75881ffc6ac53729ddbd2cdbdadc5f45c400e2622f7@178.128.141.87:443",
"node-01.gc-us-central1-a.eth.prod": "enode://182ed5d658d1a1a4382c9e9f7c9e5d8d9fec9db4c71ae346b9e23e1a589116aeffb3342299bdd00e0ab98dbf804f7b2d8ae564ed18da9f45650b444aed79d509@34.68.132.118:443",
"node-02.ac-cn-hongkong-c.eth.prod": "enode://8bebe73ddf7cf09e77602c7d04c93a73f455b51f24ae0d572917a4792f1dec0bb4c562759b8830cc3615a658d38c1a4a38597a1d7ae3ba35111479fc42d65dec@47.75.85.212:443",
"node-02.do-ams3.eth.prod": "enode://4ea35352702027984a13274f241a56a47854a7fd4b3ba674a596cff917d3c825506431cf149f9f2312a293bb7c2b1cca55db742027090916d01529fe0729643b@134.209.136.79:443",
"node-02.gc-us-central1-a.eth.prod": "enode://fbeddac99d396b91d59f2c63a3cb5fc7e0f8a9f7ce6fe5f2eed5e787a0154161b7173a6a73124a4275ef338b8966dc70a611e9ae2192f0f2340395661fad81c0@34.67.230.193:443",
"node-03.ac-cn-hongkong-c.eth.prod": "enode://ac3948b2c0786ada7d17b80cf869cf59b1909ea3accd45944aae35bf864cc069126da8b82dfef4ddf23f1d6d6b44b1565c4cf81c8b98022253c6aea1a89d3ce2@47.75.88.12:443",
"node-03.do-ams3.eth.prod": "enode://ce559a37a9c344d7109bd4907802dd690008381d51f658c43056ec36ac043338bd92f1ac6043e645b64953b06f27202d679756a9c7cf62fdefa01b2e6ac5098e@134.209.136.123:443",
"node-03.gc-us-central1-a.eth.prod": "enode://c07aa0deea3b7056c5d45a85bca42f0d8d3b1404eeb9577610f386e0a4744a0e7b2845ae328efc4aa4b28075af838b59b5b3985bffddeec0090b3b7669abc1f3@35.226.92.155:443",
"node-04.ac-cn-hongkong-c.eth.prod": "enode://385579fc5b14e04d5b04af7eee835d426d3d40ccf11f99dbd95340405f37cf3bbbf830b3eb8f70924be0c2909790120682c9c3e791646e2d5413e7801545d353@47.244.221.249:443",
"node-04.do-ams3.eth.prod": "enode://4e0a8db9b73403c9339a2077e911851750fc955db1fc1e09f81a4a56725946884dd5e4d11258eac961f9078a393c45bcab78dd0e3bc74e37ce773b3471d2e29c@134.209.136.101:443",
"node-04.gc-us-central1-a.eth.prod": "enode://0624b4a90063923c5cc27d12624b6a49a86dfb3623fcb106801217fdbab95f7617b83fa2468b9ae3de593ff6c1cf556ccf9bc705bfae9cb4625999765127b423@35.222.158.246:443",
"node-05.ac-cn-hongkong-c.eth.prod": "enode://b77bffc29e2592f30180311dd81204ab845e5f78953b5ba0587c6631be9c0862963dea5eb64c90617cf0efd75308e22a42e30bc4eb3cd1bbddbd1da38ff6483e@47.75.10.177:443",
"node-05.do-ams3.eth.prod": "enode://a8bddfa24e1e92a82609b390766faa56cf7a5eef85b22a2b51e79b333c8aaeec84f7b4267e432edd1cf45b63a3ad0fc7d6c3a16f046aa6bc07ebe50e80b63b8c@178.128.141.249:443",
"node-05.gc-us-central1-a.eth.prod": "enode://a5fe9c82ad1ffb16ae60cb5d4ffe746b9de4c5fbf20911992b7dd651b1c08ba17dd2c0b27ee6b03162c52d92f219961cc3eb14286aca8a90b75cf425826c3bd8@104.154.230.58:443",
"node-06.ac-cn-hongkong-c.eth.prod": "enode://cf5f7a7e64e3b306d1bc16073fba45be3344cb6695b0b616ccc2da66ea35b9f35b3b231c6cf335fdfaba523519659a440752fc2e061d1e5bc4ef33864aac2f19@47.75.221.196:443",
"node-06.do-ams3.eth.prod": "enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@178.128.141.0:443",
"node-06.gc-us-central1-a.eth.prod": "enode://282e009967f9f132a5c2dd366a76319f0d22d60d0c51f7e99795a1e40f213c2705a2c10e4cc6f3890319f59da1a535b8835ed9b9c4b57c3aad342bf312fd7379@35.223.240.17:443",
"node-07.ac-cn-hongkong-c.eth.prod": "enode://13d63a1f85ccdcbd2fb6861b9bd9d03f94bdba973608951f7c36e5df5114c91de2b8194d71288f24bfd17908c48468e89dd8f0fb8ccc2b2dedae84acdf65f62a@47.244.210.80:443",
"node-07.do-ams3.eth.prod": "enode://2b01955d7e11e29dce07343b456e4e96c081760022d1652b1c4b641eaf320e3747871870fa682e9e9cfb85b819ce94ed2fee1ac458904d54fd0b97d33ba2c4a4@134.209.136.112:443",
"node-07.gc-us-central1-a.eth.prod": "enode://b706a60572634760f18a27dd407b2b3582f7e065110dae10e3998498f1ae3f29ba04db198460d83ed6d2bfb254bb06b29aab3c91415d75d3b869cd0037f3853c@35.239.5.162:443",
"node-08.ac-cn-hongkong-c.eth.prod": "enode://32915c8841faaef21a6b75ab6ed7c2b6f0790eb177ad0f4ea6d731bacc19b938624d220d937ebd95e0f6596b7232bbb672905ee12601747a12ee71a15bfdf31c@47.75.59.11:443",
"node-08.do-ams3.eth.prod": "enode://0d9d65fcd5592df33ed4507ce862b9c748b6dbd1ea3a1deb94e3750052760b4850aa527265bbaf357021d64d5cc53c02b410458e732fafc5b53f257944247760@178.128.141.42:443",
"node-08.gc-us-central1-a.eth.prod": "enode://e87f1d8093d304c3a9d6f1165b85d6b374f1c0cc907d39c0879eb67f0a39d779be7a85cbd52920b6f53a94da43099c58837034afa6a7be4b099bfcd79ad13999@35.238.106.101:443"
}
},
"eth.staging": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.staging": "enode://630b0342ca4e9552f50714b6c8e28d6955bc0fd14e7950f93bc3b2b8cc8c1f3b6d103df66f51a13d773b5db0f130661fb5c7b8fa21c48890c64c79b41a56a490@47.91.229.44:443",
"boot-01.do-ams3.eth.staging": "enode://f79fb3919f72ca560ad0434dcc387abfe41e0666201ebdada8ede0462454a13deb05cda15f287d2c4bd85da81f0eb25d0a486bbbc8df427b971ac51533bd00fe@174.138.107.239:443",
"boot-01.gc-us-central1-a.eth.staging": "enode://10a78c17929a7019ef4aa2249d7302f76ae8a06f40b2dc88b7b31ebff4a623fbb44b4a627acba296c1ced3775d91fbe18463c15097a6a36fdb2c804ff3fc5b35@35.238.97.234:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.staging": "enode://b74859176c9751d314aeeffc26ec9f866a412752e7ddec91b19018a18e7cca8d637cfe2cedcb972f8eb64d816fbd5b4e89c7e8c7fd7df8a1329fa43db80b0bfe@47.52.90.156:443",
"mail-01.do-ams3.eth.staging": "enode://69f72baa7f1722d111a8c9c68c39a31430e9d567695f6108f31ccb6cd8f0adff4991e7fdca8fa770e75bc8a511a87d24690cbc80e008175f40c157d6f6788d48@206.189.240.16:443",
"mail-01.gc-us-central1-a.eth.staging": "enode://e4fc10c1f65c8aed83ac26bc1bfb21a45cc1a8550a58077c8d2de2a0e0cd18e40fd40f7e6f7d02dc6cd06982b014ce88d6e468725ffe2c138e958788d0002a7f@35.239.193.41:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.staging": "/ip4/47.91.229.44/tcp/30703/ethv4/16Uiu2HAmRnt2Eyoknh3auxh4fJwkRgqkH1gqrWGes8Pk1k3MV4xu",
"boot-01.do-ams3.eth.staging": "/ip4/174.138.107.239/tcp/30703/ethv4/16Uiu2HAm8UZXUHEPZrpJbcQ3yVFH6UtKrwsG6jH4ai72PsbLfVFb",
"boot-01.gc-us-central1-a.eth.staging": "/ip4/35.238.97.234/tcp/30703/ethv4/16Uiu2HAm6G9sDMkrB4Xa5EH3Zx2dysCxFgBTSRzghic3Z9tRFRNE"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.staging": "enode://088cf5a93c576fae52f6f075178467b8ff98bacf72f59e88efb16dfba5b30f80a4db78f8e3cb3d87f2f6521746ef4a8768465ef2896c6af24fd77a425e95b6dd@47.52.226.137:443",
"node-01.do-ams3.eth.staging": "enode://914c0b30f27bab30c1dfd31dad7652a46fda9370542aee1b062498b1345ee0913614b8b9e3e84622e84a7203c5858ae1d9819f63aece13ee668e4f6668063989@167.99.19.148:443",
"node-01.gc-us-central1-a.eth.staging": "enode://d3878441652f010326889f28360e69f2d09d06540f934fada0e17b374ce5319de64279aba3c44a5bf807d9967c6d705b3b4c6b03fa70763240e2ee6af01a539e@35.192.0.86:443"
}
},
"eth.test": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.test": "enode://daae2e72820e86e942fa2a8aa7d6e9954d4043a753483d8bd338e16be82cf962392d5c0e1ae57c3d793c3d3dddd8fd58339262e4234dc966f953cd73b535f5fa@47.52.188.149:443",
"boot-01.do-ams3.eth.test": "enode://9e0988575eb7717c25dea72fd11c7b37767dc09c1a7686f7c2ec577d308d24b377ceb675de4317474a1a870e47882732967f4fa785b02ba95d669b31d464dec0@206.189.243.164:443",
"boot-01.gc-us-central1-a.eth.test": "enode://c1e5018887c863d64e431b69bf617561087825430e4401733f5ba77c70db14236df381fefb0ebe1ac42294b9e261bbe233dbdb83e32c586c66ae26c8de70cb4c@35.188.168.137:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.test": "enode://619dbb5dda12e85bf0eb5db40fb3de625609043242737c0e975f7dfd659d85dc6d9a84f9461a728c5ab68c072fed38ca6a53917ca24b8e93cc27bdef3a1e79ac@47.52.188.196:443",
"mail-01.do-ams3.eth.test": "enode://e4865fe6c2a9c1a563a6447990d8e9ce672644ae3e08277ce38ec1f1b690eef6320c07a5d60c3b629f5d4494f93d6b86a745a0bf64ab295bbf6579017adc6ed8@206.189.243.161:443",
"mail-01.gc-us-central1-a.eth.test": "enode://707e57453acd3e488c44b9d0e17975371e2f8fb67525eae5baca9b9c8e06c86cde7c794a6c2e36203bf9f56cae8b0e50f3b33c4c2b694a7baeea1754464ce4e3@35.192.229.172:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.test": "/ip4/47.52.188.149/tcp/30703/ethv4/16Uiu2HAm9Vatqr4GfVCqnyeaPtCF3q8fz8kDDUgqXVfFG7ZfSA7w",
"boot-01.do-ams3.eth.test": "/ip4/206.189.243.164/tcp/30703/ethv4/16Uiu2HAmBCh5bgYr6V3fDuLqUzvtSAsFTQJCQ3TVHT8ta8bTu2Jm",
"boot-01.gc-us-central1-a.eth.test": "/ip4/35.188.168.137/tcp/30703/ethv4/16Uiu2HAm3MUqtGjmetyZ9L4SN2R8oHDWvACUcec25LjtDD5euiRH"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.test": "enode://ad38f94030a846cc7005b7a1f3b6b01bf4ef59d34e8d3d6f4d12df23d14ba8656702a435d34cf4df3b412c0c1923df5adcce8461321a0d8ffb9435b26e572c2a@47.52.255.194:443",
"node-01.do-ams3.eth.test": "enode://1d193635e015918fb85bbaf774863d12f65d70c6977506187ef04420d74ec06c9e8f0dcb57ea042f85df87433dab17a1260ed8dde1bdf9d6d5d2de4b7bf8e993@206.189.243.163:443",
"node-01.gc-us-central1-a.eth.test": "enode://f593a27731bc0f8eb088e2d39222c2d59dfb9bf0b3950d7a828d51e8ab9e08fffbd9916a82fd993c1a080c57c2bd70ed6c36f489a969de697aff93088dbee1a9@35.194.31.108:443"
}
},
"wakuv2.prod": {
"waku": {
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/ip4/8.210.222.231/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
"node-01.do-ams3.wakuv2.prod": "/ip4/188.166.135.145/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/ip4/34.121.100.108/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
}
},
"wakuv2.test": {
"waku": {
"node-01.ac-cn-hongkong-c.wakuv2.test": "/ip4/47.242.210.73/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
"node-01.do-ams3.wakuv2.test": "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/ip4/104.154.239.128/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
}
}
"fleets": {
"eth.prod": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.prod": "enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443",
"boot-01.do-ams3.eth.prod": "enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443",
"boot-01.gc-us-central1-a.eth.prod": "enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443",
"boot-02.ac-cn-hongkong-c.eth.prod": "enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443",
"boot-02.do-ams3.eth.prod": "enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443",
"boot-02.gc-us-central1-a.eth.prod": "enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.prod": "enode://606ae04a71e5db868a722c77a21c8244ae38f1bd6e81687cc6cfe88a3063fa1c245692232f64f45bd5408fed5133eab8ed78049332b04f9c110eac7f71c1b429@47.75.247.214:443",
"mail-01.do-ams3.eth.prod": "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@178.128.142.54:443",
"mail-01.gc-us-central1-a.eth.prod": "enode://ee2b53b0ace9692167a410514bca3024695dbf0e1a68e1dff9716da620efb195f04a4b9e873fb9b74ac84de801106c465b8e2b6c4f0d93b8749d1578bfcaf03e@104.197.238.144:443",
"mail-02.ac-cn-hongkong-c.eth.prod": "enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443",
"mail-02.do-ams3.eth.prod": "enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@178.128.142.26:443",
"mail-02.gc-us-central1-a.eth.prod": "enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443",
"mail-03.ac-cn-hongkong-c.eth.prod": "enode://e85f1d4209f2f99da801af18db8716e584a28ad0bdc47fbdcd8f26af74dbd97fc279144680553ec7cd9092afe683ddea1e0f9fc571ebcb4b1d857c03a088853d@47.244.129.82:443",
"mail-03.do-ams3.eth.prod": "enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@178.128.142.94:443",
"mail-03.gc-us-central1-a.eth.prod": "enode://44160e22e8b42bd32a06c1532165fa9e096eebedd7fa6d6e5f8bbef0440bc4a4591fe3651be68193a7ec029021cdb496cfe1d7f9f1dc69eb99226e6f39a7a5d4@35.225.221.245:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.prod": "/ip4/47.75.99.169/tcp/30703/ethv4/16Uiu2HAmV8Hq9e3zm9TMVP4zrVHo3BjqW5D6bDVV6VQntQd687e4",
"boot-01.do-ams3.eth.prod": "/ip4/178.128.138.128/tcp/30703/ethv4/16Uiu2HAmRHPzF3rQg55PgYPcQkyvPVH9n2hWsYPhUJBZ6kVjJgdV",
"boot-01.gc-us-central1-a.eth.prod": "/ip4/34.70.75.208/tcp/30703/ethv4/16Uiu2HAm6ZsERLx2BwVD2UM9SVPnnMU6NBycG8XPtu8qKys5awsU",
"boot-02.ac-cn-hongkong-c.eth.prod": "/ip4/47.52.106.107/tcp/30703/ethv4/16Uiu2HAmEHiptiDDd9gqNY8oQqo8hHUWMHJzfwt5aLRdD6W2zcXR",
"boot-02.do-ams3.eth.prod": "/ip4/178.128.140.188/tcp/30703/ethv4/16Uiu2HAmLqTXuY4Sb6G28HNooaFUXUKzpzKXCcgyJxgaEE2i5vnf",
"boot-02.gc-us-central1-a.eth.prod": "/ip4/35.223.215.156/tcp/30703/ethv4/16Uiu2HAmQEUFE2YaJohavWtHxPTEFv3sEGJtDqvtGEv78DFoEWQF"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.prod": "enode://b957e51f41e4abab8382e1ea7229e88c6e18f34672694c6eae389eac22dab8655622bbd4a08192c321416b9becffaab11c8e2b7a5d0813b922aa128b82990dab@47.75.222.178:443",
"node-01.do-ams3.eth.prod": "enode://66ba15600cda86009689354c3a77bdf1a97f4f4fb3ab50ffe34dbc904fac561040496828397be18d9744c75881ffc6ac53729ddbd2cdbdadc5f45c400e2622f7@178.128.141.87:443",
"node-01.gc-us-central1-a.eth.prod": "enode://182ed5d658d1a1a4382c9e9f7c9e5d8d9fec9db4c71ae346b9e23e1a589116aeffb3342299bdd00e0ab98dbf804f7b2d8ae564ed18da9f45650b444aed79d509@34.68.132.118:443",
"node-02.ac-cn-hongkong-c.eth.prod": "enode://8bebe73ddf7cf09e77602c7d04c93a73f455b51f24ae0d572917a4792f1dec0bb4c562759b8830cc3615a658d38c1a4a38597a1d7ae3ba35111479fc42d65dec@47.75.85.212:443",
"node-02.do-ams3.eth.prod": "enode://4ea35352702027984a13274f241a56a47854a7fd4b3ba674a596cff917d3c825506431cf149f9f2312a293bb7c2b1cca55db742027090916d01529fe0729643b@134.209.136.79:443",
"node-02.gc-us-central1-a.eth.prod": "enode://fbeddac99d396b91d59f2c63a3cb5fc7e0f8a9f7ce6fe5f2eed5e787a0154161b7173a6a73124a4275ef338b8966dc70a611e9ae2192f0f2340395661fad81c0@34.67.230.193:443",
"node-03.ac-cn-hongkong-c.eth.prod": "enode://ac3948b2c0786ada7d17b80cf869cf59b1909ea3accd45944aae35bf864cc069126da8b82dfef4ddf23f1d6d6b44b1565c4cf81c8b98022253c6aea1a89d3ce2@47.75.88.12:443",
"node-03.do-ams3.eth.prod": "enode://ce559a37a9c344d7109bd4907802dd690008381d51f658c43056ec36ac043338bd92f1ac6043e645b64953b06f27202d679756a9c7cf62fdefa01b2e6ac5098e@134.209.136.123:443",
"node-03.gc-us-central1-a.eth.prod": "enode://c07aa0deea3b7056c5d45a85bca42f0d8d3b1404eeb9577610f386e0a4744a0e7b2845ae328efc4aa4b28075af838b59b5b3985bffddeec0090b3b7669abc1f3@35.226.92.155:443",
"node-04.ac-cn-hongkong-c.eth.prod": "enode://385579fc5b14e04d5b04af7eee835d426d3d40ccf11f99dbd95340405f37cf3bbbf830b3eb8f70924be0c2909790120682c9c3e791646e2d5413e7801545d353@47.244.221.249:443",
"node-04.do-ams3.eth.prod": "enode://4e0a8db9b73403c9339a2077e911851750fc955db1fc1e09f81a4a56725946884dd5e4d11258eac961f9078a393c45bcab78dd0e3bc74e37ce773b3471d2e29c@134.209.136.101:443",
"node-04.gc-us-central1-a.eth.prod": "enode://0624b4a90063923c5cc27d12624b6a49a86dfb3623fcb106801217fdbab95f7617b83fa2468b9ae3de593ff6c1cf556ccf9bc705bfae9cb4625999765127b423@35.222.158.246:443",
"node-05.ac-cn-hongkong-c.eth.prod": "enode://b77bffc29e2592f30180311dd81204ab845e5f78953b5ba0587c6631be9c0862963dea5eb64c90617cf0efd75308e22a42e30bc4eb3cd1bbddbd1da38ff6483e@47.75.10.177:443",
"node-05.do-ams3.eth.prod": "enode://a8bddfa24e1e92a82609b390766faa56cf7a5eef85b22a2b51e79b333c8aaeec84f7b4267e432edd1cf45b63a3ad0fc7d6c3a16f046aa6bc07ebe50e80b63b8c@178.128.141.249:443",
"node-05.gc-us-central1-a.eth.prod": "enode://a5fe9c82ad1ffb16ae60cb5d4ffe746b9de4c5fbf20911992b7dd651b1c08ba17dd2c0b27ee6b03162c52d92f219961cc3eb14286aca8a90b75cf425826c3bd8@104.154.230.58:443",
"node-06.ac-cn-hongkong-c.eth.prod": "enode://cf5f7a7e64e3b306d1bc16073fba45be3344cb6695b0b616ccc2da66ea35b9f35b3b231c6cf335fdfaba523519659a440752fc2e061d1e5bc4ef33864aac2f19@47.75.221.196:443",
"node-06.do-ams3.eth.prod": "enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@178.128.141.0:443",
"node-06.gc-us-central1-a.eth.prod": "enode://282e009967f9f132a5c2dd366a76319f0d22d60d0c51f7e99795a1e40f213c2705a2c10e4cc6f3890319f59da1a535b8835ed9b9c4b57c3aad342bf312fd7379@35.223.240.17:443",
"node-07.ac-cn-hongkong-c.eth.prod": "enode://13d63a1f85ccdcbd2fb6861b9bd9d03f94bdba973608951f7c36e5df5114c91de2b8194d71288f24bfd17908c48468e89dd8f0fb8ccc2b2dedae84acdf65f62a@47.244.210.80:443",
"node-07.do-ams3.eth.prod": "enode://2b01955d7e11e29dce07343b456e4e96c081760022d1652b1c4b641eaf320e3747871870fa682e9e9cfb85b819ce94ed2fee1ac458904d54fd0b97d33ba2c4a4@134.209.136.112:443",
"node-07.gc-us-central1-a.eth.prod": "enode://b706a60572634760f18a27dd407b2b3582f7e065110dae10e3998498f1ae3f29ba04db198460d83ed6d2bfb254bb06b29aab3c91415d75d3b869cd0037f3853c@35.239.5.162:443",
"node-08.ac-cn-hongkong-c.eth.prod": "enode://32915c8841faaef21a6b75ab6ed7c2b6f0790eb177ad0f4ea6d731bacc19b938624d220d937ebd95e0f6596b7232bbb672905ee12601747a12ee71a15bfdf31c@47.75.59.11:443",
"node-08.do-ams3.eth.prod": "enode://0d9d65fcd5592df33ed4507ce862b9c748b6dbd1ea3a1deb94e3750052760b4850aa527265bbaf357021d64d5cc53c02b410458e732fafc5b53f257944247760@178.128.141.42:443",
"node-08.gc-us-central1-a.eth.prod": "enode://e87f1d8093d304c3a9d6f1165b85d6b374f1c0cc907d39c0879eb67f0a39d779be7a85cbd52920b6f53a94da43099c58837034afa6a7be4b099bfcd79ad13999@35.238.106.101:443"
}
},
"meta": {
"hostname": "node-01.do-ams3.proxy.misc",
"timestamp": "2021-06-07T00:00:09.836740"
"eth.staging": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.staging": "enode://630b0342ca4e9552f50714b6c8e28d6955bc0fd14e7950f93bc3b2b8cc8c1f3b6d103df66f51a13d773b5db0f130661fb5c7b8fa21c48890c64c79b41a56a490@47.91.229.44:443",
"boot-01.do-ams3.eth.staging": "enode://f79fb3919f72ca560ad0434dcc387abfe41e0666201ebdada8ede0462454a13deb05cda15f287d2c4bd85da81f0eb25d0a486bbbc8df427b971ac51533bd00fe@174.138.107.239:443",
"boot-01.gc-us-central1-a.eth.staging": "enode://10a78c17929a7019ef4aa2249d7302f76ae8a06f40b2dc88b7b31ebff4a623fbb44b4a627acba296c1ced3775d91fbe18463c15097a6a36fdb2c804ff3fc5b35@35.238.97.234:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.staging": "enode://b74859176c9751d314aeeffc26ec9f866a412752e7ddec91b19018a18e7cca8d637cfe2cedcb972f8eb64d816fbd5b4e89c7e8c7fd7df8a1329fa43db80b0bfe@47.52.90.156:443",
"mail-01.do-ams3.eth.staging": "enode://69f72baa7f1722d111a8c9c68c39a31430e9d567695f6108f31ccb6cd8f0adff4991e7fdca8fa770e75bc8a511a87d24690cbc80e008175f40c157d6f6788d48@206.189.240.16:443",
"mail-01.gc-us-central1-a.eth.staging": "enode://e4fc10c1f65c8aed83ac26bc1bfb21a45cc1a8550a58077c8d2de2a0e0cd18e40fd40f7e6f7d02dc6cd06982b014ce88d6e468725ffe2c138e958788d0002a7f@35.239.193.41:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.staging": "/ip4/47.91.229.44/tcp/30703/ethv4/16Uiu2HAmRnt2Eyoknh3auxh4fJwkRgqkH1gqrWGes8Pk1k3MV4xu",
"boot-01.do-ams3.eth.staging": "/ip4/174.138.107.239/tcp/30703/ethv4/16Uiu2HAm8UZXUHEPZrpJbcQ3yVFH6UtKrwsG6jH4ai72PsbLfVFb",
"boot-01.gc-us-central1-a.eth.staging": "/ip4/35.238.97.234/tcp/30703/ethv4/16Uiu2HAm6G9sDMkrB4Xa5EH3Zx2dysCxFgBTSRzghic3Z9tRFRNE"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.staging": "enode://088cf5a93c576fae52f6f075178467b8ff98bacf72f59e88efb16dfba5b30f80a4db78f8e3cb3d87f2f6521746ef4a8768465ef2896c6af24fd77a425e95b6dd@47.52.226.137:443",
"node-01.do-ams3.eth.staging": "enode://914c0b30f27bab30c1dfd31dad7652a46fda9370542aee1b062498b1345ee0913614b8b9e3e84622e84a7203c5858ae1d9819f63aece13ee668e4f6668063989@167.99.19.148:443",
"node-01.gc-us-central1-a.eth.staging": "enode://d3878441652f010326889f28360e69f2d09d06540f934fada0e17b374ce5319de64279aba3c44a5bf807d9967c6d705b3b4c6b03fa70763240e2ee6af01a539e@35.192.0.86:443"
}
},
"eth.test": {
"boot": {
"boot-01.ac-cn-hongkong-c.eth.test": "enode://daae2e72820e86e942fa2a8aa7d6e9954d4043a753483d8bd338e16be82cf962392d5c0e1ae57c3d793c3d3dddd8fd58339262e4234dc966f953cd73b535f5fa@47.52.188.149:443",
"boot-01.do-ams3.eth.test": "enode://9e0988575eb7717c25dea72fd11c7b37767dc09c1a7686f7c2ec577d308d24b377ceb675de4317474a1a870e47882732967f4fa785b02ba95d669b31d464dec0@206.189.243.164:443",
"boot-01.gc-us-central1-a.eth.test": "enode://c1e5018887c863d64e431b69bf617561087825430e4401733f5ba77c70db14236df381fefb0ebe1ac42294b9e261bbe233dbdb83e32c586c66ae26c8de70cb4c@35.188.168.137:443"
},
"mail": {
"mail-01.ac-cn-hongkong-c.eth.test": "enode://619dbb5dda12e85bf0eb5db40fb3de625609043242737c0e975f7dfd659d85dc6d9a84f9461a728c5ab68c072fed38ca6a53917ca24b8e93cc27bdef3a1e79ac@47.52.188.196:443",
"mail-01.do-ams3.eth.test": "enode://e4865fe6c2a9c1a563a6447990d8e9ce672644ae3e08277ce38ec1f1b690eef6320c07a5d60c3b629f5d4494f93d6b86a745a0bf64ab295bbf6579017adc6ed8@206.189.243.161:443",
"mail-01.gc-us-central1-a.eth.test": "enode://707e57453acd3e488c44b9d0e17975371e2f8fb67525eae5baca9b9c8e06c86cde7c794a6c2e36203bf9f56cae8b0e50f3b33c4c2b694a7baeea1754464ce4e3@35.192.229.172:443"
},
"rendezvous": {
"boot-01.ac-cn-hongkong-c.eth.test": "/ip4/47.52.188.149/tcp/30703/ethv4/16Uiu2HAm9Vatqr4GfVCqnyeaPtCF3q8fz8kDDUgqXVfFG7ZfSA7w",
"boot-01.do-ams3.eth.test": "/ip4/206.189.243.164/tcp/30703/ethv4/16Uiu2HAmBCh5bgYr6V3fDuLqUzvtSAsFTQJCQ3TVHT8ta8bTu2Jm",
"boot-01.gc-us-central1-a.eth.test": "/ip4/35.188.168.137/tcp/30703/ethv4/16Uiu2HAm3MUqtGjmetyZ9L4SN2R8oHDWvACUcec25LjtDD5euiRH"
},
"whisper": {
"node-01.ac-cn-hongkong-c.eth.test": "enode://ad38f94030a846cc7005b7a1f3b6b01bf4ef59d34e8d3d6f4d12df23d14ba8656702a435d34cf4df3b412c0c1923df5adcce8461321a0d8ffb9435b26e572c2a@47.52.255.194:443",
"node-01.do-ams3.eth.test": "enode://1d193635e015918fb85bbaf774863d12f65d70c6977506187ef04420d74ec06c9e8f0dcb57ea042f85df87433dab17a1260ed8dde1bdf9d6d5d2de4b7bf8e993@206.189.243.163:443",
"node-01.gc-us-central1-a.eth.test": "enode://f593a27731bc0f8eb088e2d39222c2d59dfb9bf0b3950d7a828d51e8ab9e08fffbd9916a82fd993c1a080c57c2bd70ed6c36f489a969de697aff93088dbee1a9@35.194.31.108:443"
}
},
"status.prod": {
"waku": {
"node-01.ac-cn-hongkong-c.status.prod": "/dns4/node-01.ac-cn-hongkong-c.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAkvEZgh3KLwhLwXg95e5ojM8XykJ4Kxi2T7hk22rnA7pJC",
"node-01.do-ams3.status.prod": "/dns4/node-01.do-ams3.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D",
"node-01.gc-us-central1-a.status.prod": "/dns4/node-01.gc-us-central1-a.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAkwBp8T6G77kQXSNMnxgaMky1JeyML5yqoTHRM8dbeCBNb",
"node-02.ac-cn-hongkong-c.status.prod": "/dns4/node-02.ac-cn-hongkong-c.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmFy8BrJhCEmCYrUfBdSNkrPw6VHExtv4rRp1DSBnCPgx8",
"node-02.do-ams3.status.prod": "/dns4/node-02.do-ams3.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmSve7tR5YZugpskMv2dmJAsMUKmfWYEKRXNUxRaTCnsXV",
"node-02.gc-us-central1-a.status.prod": "/dns4/node-02.gc-us-central1-a.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmDQugwDHM3YeUp86iGjrUvbdw3JPRgikC7YoGBsT2ymMg"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.status.prod": "/dns4/node-01.ac-cn-hongkong-c.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvEZgh3KLwhLwXg95e5ojM8XykJ4Kxi2T7hk22rnA7pJC",
"node-01.do-ams3.status.prod": "/dns4/node-01.do-ams3.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D",
"node-01.gc-us-central1-a.status.prod": "/dns4/node-01.gc-us-central1-a.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAkwBp8T6G77kQXSNMnxgaMky1JeyML5yqoTHRM8dbeCBNb",
"node-02.ac-cn-hongkong-c.status.prod": "/dns4/node-02.ac-cn-hongkong-c.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmFy8BrJhCEmCYrUfBdSNkrPw6VHExtv4rRp1DSBnCPgx8",
"node-02.do-ams3.status.prod": "/dns4/node-02.do-ams3.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmSve7tR5YZugpskMv2dmJAsMUKmfWYEKRXNUxRaTCnsXV",
"node-02.gc-us-central1-a.status.prod": "/dns4/node-02.gc-us-central1-a.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmDQugwDHM3YeUp86iGjrUvbdw3JPRgikC7YoGBsT2ymMg"
},
"waku-nodes": ["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@prod.nodes.status.im"]
},
"status.test": {
"waku": {
"node-01.ac-cn-hongkong-c.status.test": "/dns4/node-01.ac-cn-hongkong-c.status.test.statusim.net/tcp/30303/p2p/16Uiu2HAm2BjXxCp1sYFJQKpLLbPbwd5juxbsYofu3TsS3auvT9Yi",
"node-01.do-ams3.status.test": "/dns4/node-01.do-ams3.status.test.statusim.net/tcp/30303/p2p/16Uiu2HAkukebeXjTQ9QDBeNDWuGfbaSg79wkkhK4vPocLgR6QFDf",
"node-01.gc-us-central1-a.status.test": "/dns4/node-01.gc-us-central1-a.status.test.statusim.net/tcp/30303/p2p/16Uiu2HAmGDX3iAFox93PupVYaHa88kULGqMpJ7AEHGwj3jbMtt76"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.status.test": "/dns4/node-01.ac-cn-hongkong-c.status.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm2BjXxCp1sYFJQKpLLbPbwd5juxbsYofu3TsS3auvT9Yi",
"node-01.do-ams3.status.test": "/dns4/node-01.do-ams3.status.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkukebeXjTQ9QDBeNDWuGfbaSg79wkkhK4vPocLgR6QFDf",
"node-01.gc-us-central1-a.status.test": "/dns4/node-01.gc-us-central1-a.status.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmGDX3iAFox93PupVYaHa88kULGqMpJ7AEHGwj3jbMtt76"
},
"waku-nodes": ["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.nodes.status.im"]
},
"wakuv2.prod": {
"waku": {
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/ip4/8.210.222.231/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
"node-01.do-ams3.wakuv2.prod": "/ip4/188.166.135.145/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/ip4/34.121.100.108/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
"node-01.gc-us-central1-a.wakuv2.prod": "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
},
"waku-nodes": ["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@prod.waku.nodes.status.im"]
},
"wakuv2.test": {
"waku": {
"node-01.ac-cn-hongkong-c.wakuv2.test": "/ip4/47.242.210.73/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
"node-01.do-ams3.wakuv2.test": "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/ip4/104.154.239.128/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
},
"waku-websocket": {
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"node-01.gc-us-central1-a.wakuv2.test": "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
},
"waku-nodes": ["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im"]
}
},
"meta": {
"hostname": "node-01.do-ams3.proxy.misc",
"timestamp": "2021-06-07T00:00:09.836740"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

+2 -2
View File
@@ -2,10 +2,10 @@
CHANGES=$(git diff --no-ext-diff --diff-filter=d --cached --unified=0 --no-prefix --minimal --exit-code src/quo src/quo2 | grep '^+' || echo '')
INVALID_CHANGES=$(echo "$CHANGES" | grep -E '(re-frame/dispatch|rf/dispatch|re-frame/subscribe|rf/subscribe|rf/sub|<sub|>evt)')
INVALID_CHANGES=$(echo "$CHANGES" | grep -E '(re-frame/dispatch|rf/dispatch|re-frame/subscribe|rf/subscribe|rf/sub|<sub|>evt|status-im)')
if test -n "$INVALID_CHANGES"; then
echo "re-frame dispatch/subscribe is not allowed in quo/quo2 components"
echo "re-frame dispatch/subscribe and status-im are not allowed in quo/quo2 components"
echo ''
echo "$INVALID_CHANGES"
exit 1
+2 -2
View File
@@ -56,7 +56,7 @@
(defn button [{:keys [on-press disabled type theme before after
haptic-feedback haptic-type on-long-press on-press-start
accessibility-label loading border-radius style]
accessibility-label loading border-radius style test-ID]
:or {theme :main
type :primary
haptic-feedback true
@@ -92,7 +92,7 @@
{:on-press-start (fn []
(optional-haptic)
(on-press-start))}))
[rn/view {:style (merge (style-container type) style)}
[rn/view {:test-ID test-ID :style (merge (style-container type) style)}
(when before
[rn/view
[icons/icon before {:color icon-color}]])
+44
View File
@@ -0,0 +1,44 @@
const waitToNavigate = duration => new Promise(resolve => setTimeout(() => resolve(), duration));
const SUPER_SECRET_PASSWORD = 'password'
const loginToHomePage = async () => {
if (device.getPlatform() === 'ios') {
await device.setStatusBar({ time: '12:34', dataNetwork: 'wifi', wifiBars: '3', batteryState: 'charging', batteryLevel: '100' });
}
await device.reloadReactNative();
await element(by.id('terms-of-service')).tap();
await waitToNavigate(400);
await element(by.id('get-started')).tap();
await waitToNavigate(300);
await element(by.id('generate-keys')).tap();
await waitToNavigate(200);
await element(by.text('Next')).tap();
await waitToNavigate(700);
await element(by.text('Next')).tap();
await waitToNavigate(700);
await element(by.id('password-placeholder')).typeText(SUPER_SECRET_PASSWORD);
await element(by.id('confirm-password-placeholder')).typeText(SUPER_SECRET_PASSWORD);
await element(by.text('Next')).tap();
await waitToNavigate(200);
await element(by.id("browser-stack")).tap();
await waitToNavigate(400);
await element(by.text("Quo2.0 Preview")).tap();
await waitToNavigate(400);
}
describe('Default Renders', () => {
beforeAll(async () => loginToHomePage())
beforeEach(async () => {
});
afterEach(async () => {
await element(by.id("back-button")).tap();
await waitToNavigate(200);
});
it(`button page should match image render`, async () => {
await element(by.id(`quo2-:button`)).tap();
await waitToNavigate(200);
const res = await jestExpect(`button`).toMatchImageSnapshot();
})
});
+11 -13
View File
@@ -4,25 +4,23 @@
[react-native.core :as rn]))
(def sizes
{:icon {:small 12
:medium 16
:large 20}
:container {:small 20
{:icon {:small 12
:medium 16
:large 20}
:container {:small 20
:medium 32
:large 48}})
:large 48}})
;; TODO: this implementation does not support group display picture (can only display default group icon).
(defn group-avatar [_]
(fn [{:keys [color size override-theme]}]
(let [theme (or override-theme (if (colors/dark?) :dark :light))
container-size (get-in sizes [:container size])
(fn [{:keys [color size]}]
(let [container-size (get-in sizes [:container size])
icon-size (get-in sizes [:icon size])]
[rn/view {:width container-size
:height container-size
:align-items :center
:justify-content :center
:border-radius (/ container-size 2)
:background-color (if (= theme :light)
(colors/custom-color color 50)
(colors/custom-color color 60))}
[icon/icon :total-members {:size icon-size
:color colors/white-opa-70}]])))
:background-color (colors/theme-alpha color 0.5 0.6)}
[icon/icon :i/group {:size icon-size ; TODO: group icon sizes 12 and 20 (small and large) are missing
:color colors/white-opa-70}]])))
+7 -7
View File
@@ -122,20 +122,20 @@
first-initial-letter
initials)
"")]
[rn/view {:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
[rn/view {:accessibility-label :user-avatar
:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
(when (and ring? identicon?)
[icons/icon :main-icons/identicon-ring {:width outer-dimensions
:height outer-dimensions
:size outer-dimensions
:no-color true}])
[icons/icon :i/identicon-ring {:size outer-dimensions
:no-color true}])
(if profile-picture
;; display image
[fast-image/fast-image {:source {:uri profile-picture}
:style (container-styling inner-dimensions outer-dimensions)}]
;; else display initials
[container inner-dimensions outer-dimensions
^{:key :icon-text}
[text/text {:weight :semi-bold
:size font-size
:style {:color colors/white-opa-70}}
+3 -2
View File
@@ -186,7 +186,7 @@
(let [pressed (reagent/atom false)]
(fn [{:keys [on-press disabled type size before after above width
override-theme override-background-color
on-long-press accessibility-label icon icon-no-color style]
on-long-press accessibility-label icon icon-no-color style test-ID]
:or {type :primary
size 40}}
children]
@@ -197,7 +197,8 @@
state (cond disabled :disabled @pressed :pressed :else :default)
icon-size (when (= 24 size) 12)
icon-secondary-color (or icon-secondary-color icon-color)]
[rn/touchable-without-feedback (merge {:disabled disabled
[rn/touchable-without-feedback (merge {:test-ID test-ID
:disabled disabled
:accessibility-label accessibility-label}
(when on-press
{:on-press (fn []
@@ -6,10 +6,49 @@
[quo2.components.counter.counter :as counter]
[quo2.components.icon :as icons]
[quo2.components.community.style :as style]
[react-native.fast-image :as fast-image]
[react-native.core :as rn]))
(defn communities-list-view-item [props {:keys [name locked? status notifications
tokens background-color]}]
(defn community-icon-view [community-icon]
[rn/view {:width 32
:height 32}
[fast-image/fast-image {:source {:uri community-icon}
:style {:height 32
:border-radius 16
:width 32}}]])
(defn notification-view [{:keys [muted?
unread-messages?
unread-mentions-count]}]
(cond
muted?
[icons/icon :i/muted {:container-style {:align-items :center
:justify-content :center}
:resize-mode :center
:size 20
:color (colors/theme-colors
colors/neutral-40
colors/neutral-50)}]
(pos? unread-mentions-count)
[counter/counter {:type :default} unread-mentions-count]
unread-messages?
[rn/view {:style {:width 8
:height 8
:border-radius 4
:background-color (colors/theme-colors
colors/neutral-40
colors/neutral-60)}}]))
(defn communities-list-view-item [props {:keys [name
locked?
status
muted?
unread-messages?
unread-mentions-count
community-icon
tokens
background-color]}]
[rn/view {:style (merge (style/community-card 16)
{:margin-bottom 12
:margin-horizontal 20})}
@@ -24,8 +63,8 @@
:padding-vertical 8
:background-color background-color}
[rn/view]
;;TODO new pure component based on quo2 should be implemented without status-im usage
;[communities.icon/community-icon-redesign community 32]]
(when community-icon
[community-icon-view community-icon])
[rn/view {:flex 1
:margin-horizontal 12}
[text/text {:weight :semi-bold
@@ -33,7 +72,7 @@
:accessibility-label :community-name-text
:number-of-lines 1
:ellipsize-mode :tail
:style {:color (when (= notifications :muted)
:style {:color (when muted?
(colors/theme-colors
colors/neutral-40
colors/neutral-60))}}
@@ -42,28 +81,18 @@
(if (= status :gated)
[community-view/permission-tag-container {:locked? locked?
:tokens tokens}]
(cond
(= notifications :unread-messages-count)
[rn/view {:style {:width 8
:height 8
:border-radius 4
:background-color (colors/theme-colors
colors/neutral-40
colors/neutral-60)}}]
[notification-view {:muted? muted?
:unread-mentions-count unread-mentions-count
:unread-messages? unread-messages?}])]]]])
(= notifications :unread-mentions-count)
[counter/counter {:type :default} 5]
(= notifications :muted)
[icons/icon :i/muted {:container-style {:align-items :center
:justify-content :center}
:resize-mode :center
:size 20
:color (colors/theme-colors
colors/neutral-40
colors/neutral-50)}]))]]]])
(defn communities-membership-list-item [props {:keys [name status tokens locked?]}]
(defn communities-membership-list-item [props {:keys [name
muted?
unread-messages?
unread-mentions-count
status
community-icon
tokens
locked?]}]
[rn/view {:margin-bottom 20}
[rn/touchable-highlight (merge {:underlay-color colors/primary-50-opa-5
:style {:border-radius 12}}
@@ -72,8 +101,9 @@
[rn/view {:flex-direction :row
:border-radius 16
:align-items :center}
;;TODO new pure component based on quo2 should be implemented without status-im usage
;[communities.icon/community-icon-redesign community 32]
(when community-icon
[community-icon-view community-icon])
[rn/view {:flex 1
:margin-left 12
:justify-content :center}
@@ -84,8 +114,12 @@
:weight :semi-bold
:size :paragraph-1}
name]]
(when (= status :gated)
[rn/view {:justify-content :center
:margin-right 12}
[rn/view {:justify-content :center
:margin-right 16}
(if (= status :gated)
[community-view/permission-tag-container {:locked? locked?
:tokens tokens}]])]]]])
:tokens tokens}]
[notification-view {:muted? muted?
:unread-mentions-count unread-mentions-count
:unread-messages? unread-messages?}])]]]]])
+55 -53
View File
@@ -9,54 +9,6 @@
(colors/theme-colors colors/danger-50 colors/danger-60)
(colors/theme-colors colors/neutral-50 colors/neutral-40)))
(defn action [{:keys [icon
label
sub-label
right-icon
danger?
on-press] :as action-props}]
(when action-props
[rn/touchable-opacity {:on-press on-press}
[rn/view {:style
{:height (if sub-label 56 47)
:margin-horizontal 20
:flex-direction :row}}
[rn/view {:style
{:height 20
:margin-top :auto
:margin-bottom :auto
:margin-right 12
:width 20}}
[icon/icon icon
{:color (get-icon-color danger?)
:size 20}]]
[rn/view
{:style
{:flex 1
:justify-content :center}}
[text/text
{:size :paragraph-1
:weight :medium
:style {:color
(when danger?
(colors/theme-colors colors/danger-50 colors/danger-60))}}
label]
(when sub-label
[text/text
{:size :paragraph-2
:style {:color
(colors/theme-colors colors/neutral-50 colors/neutral-40)}}
sub-label])]
(when right-icon
[rn/view {:style
{:height 20
:margin-top :auto
:margin-bottom :auto
:width 20}}
[icon/icon right-icon
{:color (get-icon-color danger?)
:size 20}]])]]))
(defn divider []
[rn/view {:style {:border-top-width 1
:border-top-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
@@ -65,10 +17,60 @@
:align-items :center
:flex-direction :row}}])
(defn action [{:keys [icon
label
sub-label
right-icon
danger?
on-press
add-divider?] :as action-props}]
(when action-props
[:<> {:key label}
(when add-divider? [divider])
[rn/touchable-opacity {:on-press on-press}
[rn/view {:style
{:height (if sub-label 56 47)
:margin-horizontal 20
:flex-direction :row}}
[rn/view {:style
{:height 20
:margin-top :auto
:margin-bottom :auto
:margin-right 12
:width 20}}
[icon/icon icon
{:color (get-icon-color danger?)
:size 20}]]
[rn/view
{:style
{:flex 1
:justify-content :center}}
[text/text
{:size :paragraph-1
:weight :medium
:style {:color
(when danger?
(colors/theme-colors colors/danger-50 colors/danger-60))}}
label]
(when sub-label
[text/text
{:size :paragraph-2
:style {:color
(colors/theme-colors colors/neutral-50 colors/neutral-40)}}
sub-label])]
(when right-icon
[rn/view {:style
{:height 20
:margin-top :auto
:margin-bottom :auto
:width 20}}
[icon/icon right-icon
{:color (get-icon-color danger?)
:size 20}]])]]]))
(defn action-drawer [sections]
[:<> {:style
{:flex 1}}
(interpose
[divider]
[:<>
(doall
(for [actions sections]
(map action actions)))])
(doall
(map action actions))))])
+2 -1
View File
@@ -30,4 +30,5 @@
(get-icons 12)
(get-icons 16)
(get-icons 20)
(get-icons 24)))
(get-icons 24)
(get-icons 32)))
@@ -0,0 +1,40 @@
(ns quo2.components.list-items.user-list.style
(:require [quo2.foundations.colors :as colors]))
(defn user-list-wrapper [can-be-invited? background-type]
(let [height (if can-be-invited? 56 80)]
{:width 359
:border-radius 12
:padding-vertical 8
:padding-horizontal 12
:height height
:background-color (case background-type
:5 colors/primary-50-opa-5
:10 colors/primary-50-opa-10
:transparent :transparent)
:flex-direction :column
:justify-content :center}))
(def ml-8 {:margin-left 8})
(def row-centered {:flex-direction :row
:align-items :center})
(def icon-container-styles {:width 32
:height 32
:border-radius 10
:border-width 1
:border-color (colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10)
:justify-content :center
:align-items :center})
(def container (assoc row-centered :justify-content :space-between))
(def cant-be-invited {:flex-direction :row
:margin-top 8
:margin-left 40})
(def icon-container {:margin-right 2
:margin-top 2})
(def cant-be-invited-text-style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})
@@ -0,0 +1,67 @@
(ns quo2.components.list-items.user-list.view
(:require [quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.icon :as icons]
[quo2.components.list-items.user-list.style :as style]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[quo2.components.selectors.selectors :as selectors]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.utils :as utils]))
(def ^:private icon-types {:options :i/options
:close :i/close})
(defn- cant-be-invited-msg []
[rn/view {:style style/cant-be-invited
:accessibility-label "user can't be invite"}
[icons/icon :i/info {:size 12
:color colors/neutral-40
:container-style style/icon-container}]
[text/text {:weight :regular
:size :label
:style style/cant-be-invited-text-style}
"Cant be invited due to their privacy settings"]])
(defn- right-section [{:keys [id button-type on-press checked?]}]
(if (= button-type :checkbox)
[selectors/checkbox {:default-checked? checked?}]
[rn/touchable-opacity
{:on-press on-press
:accessibility-label (str (or id "user-list") "-" (if (= button-type :options)
"options"
"close"))}
[rn/view {:style (when (= button-type :close)
style/icon-container-styles)}
[icons/icon (button-type icon-types) {:size 20
:color (colors/theme-colors colors/neutral-100 colors/white)}]]]))
(defn- user-info [{:keys [id contact on-press checked? button-type]}]
[rn/view {:style style/container}
[rn/view style/row-centered
[user-avatar/user-avatar {:size :small
:ring? true
:online? true
:profile-picture (multiaccounts/displayed-photo contact)
:status-indicator? true}]
[rn/view {:style style/ml-8}
[text/text {:weight :semi-bold
:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-100 colors/white)}} (-> contact
(multiaccounts/contact-two-names false))]
[text/text {:weight :regular
:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} (utils/get-shortened-address (:public-key contact))]]]
[right-section {:id id
:button-type button-type
:on-press on-press
:checked? checked?}]])
(defn user-list [{:keys [id contact on-press background-type checked? button-type can-be-invited?]}]
[rn/view {:style (style/user-list-wrapper can-be-invited? background-type)}
[user-info {:id id
:on-press on-press
:checked? checked?
:button-type button-type
:contact contact}]
(when-not can-be-invited? [cant-be-invited-msg])])
@@ -0,0 +1,39 @@
(ns quo2.components.messages.author.style
(:require [quo2.foundations.colors :as colors]))
(def container
{:flex 1
:flex-wrap :wrap
:height 18
:flex-direction :row
:align-items :center})
(defn ens-text []
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(defn nickname-text []
{:color (colors/theme-colors colors/neutral-100 colors/white)})
(def middle-dot-nickname
{:color colors/neutral-50
:margin-horizontal 4})
(def chat-key-text
{:color colors/neutral-50
:margin-left 8})
(def middle-dot-chat-key
{:color colors/neutral-50
:margin-left 4})
(defn profile-name-text [nickname?]
{:color (if nickname?
(colors/theme-colors colors/neutral-60 colors/neutral-40)
(colors/theme-colors colors/neutral-100 colors/white))})
(def icon-container
{:margin-left 4})
(defn time-text [ens?]
{:color colors/neutral-50
:margin-left (if ens? 8 4)})
@@ -0,0 +1,66 @@
(ns quo2.components.messages.author.view
(:require
[quo2.components.messages.author.style :as style]
[react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.icon :as icons]
[status-im.utils.utils :as utils]
[clojure.string :as string]))
(def middle-dot "·")
(defn author [{:keys [profile-name nickname chat-key ens-name time-str contact? verified? untrustworthy?]}]
[:f>
(fn []
(let [ens? (-> ens-name string/blank? not)
nickname? (-> nickname string/blank? not)]
[rn/view {:style style/container}
(if ens?
[text/text {:weight :semi-bold
:size :paragraph-2
:style (style/ens-text)}
ens-name]
[:<>
(when nickname?
[:<>
[text/text {:weight :semi-bold
:size :paragraph-2
:style (style/nickname-text)}
nickname]
[text/text {:size :paragraph-2
:style style/middle-dot-nickname}
middle-dot]])
[text/text {:weight (if nickname? :medium :semi-bold)
:size :paragraph-2
:style (style/profile-name-text nickname?)}
profile-name]])
(when contact?
[icons/icon :main-icons2/contact
{:size 12
:no-color true
:container-style style/icon-container}])
(cond
verified?
[icons/icon :main-icons2/verified
{:size 12
:no-color true
:container-style style/icon-container}]
untrustworthy?
[icons/icon :main-icons2/untrustworthy
{:size 12
:no-color true
:container-style style/icon-container}])
(when-not ens?
[text/text {:monospace true
:size :paragraph-2
:style style/chat-key-text}
(utils/get-shortened-address chat-key)])
(when-not ens?
[text/text {:monospace true
:size :paragraph-2
:style style/middle-dot-chat-key}
middle-dot])
[text/text {:monospace true
:size :paragraph-2
:style (style/time-text ens?)}
time-str]]))])
@@ -6,7 +6,7 @@
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[utils :as utils]))
[utils.string :as utils]))
(def themes-landed {:pinned colors/primary-50-opa-5
:added colors/primary-50-opa-5
@@ -26,7 +26,7 @@
:icon-color-anim reanimated shared value
"
[{:keys [icon new-notifications? notification-indicator counter-label
on-press pass-through? icon-color-anim accessibility-label]}]
on-press pass-through? icon-color-anim accessibility-label test-ID]}]
[:f>
(fn []
(let [icon-animated-style (reanimated/apply-animations-to-style
@@ -40,7 +40,8 @@
:height 40
:border-radius 10})]
[rn/touchable-without-feedback
{:on-press on-press
{:test-ID test-ID
:on-press on-press
:on-press-in #(toggle-background-color background-color false pass-through?)
:on-press-out #(toggle-background-color background-color true pass-through?)
:accessibility-label accessibility-label}
@@ -63,6 +63,7 @@
:right 20
:top 12
:flex-direction :row}}
;; TODO component shouldn't know anything about parent system, we should pass buttons as parameters
[base-button :i/search open-search :open-search-button button-common-props]
[base-button :i/scan open-scanner :open-scanner-button button-common-props]
[base-button :i/qr-code show-qr :show-qr-button button-common-props]
@@ -0,0 +1,76 @@
(ns quo2.components.notifications.activity-log.style
(:require [quo2.foundations.colors :as colors]))
(def container
{:flex-direction :row
:flex-grow 1
:align-items :flex-start
:padding-top 8
:padding-horizontal 12
:padding-bottom 12})
(def icon
{:height 32
:width 32
:border-radius 100
:margin-top 10
:border-width 1
:border-color colors/white-opa-5
:align-items :center
:justify-content :center})
(def message-title
{:color colors/white-opa-40
:margin-bottom 2})
(def message-body
{:color colors/white})
(def message-container
{:border-radius 12
:margin-top 12
:padding-horizontal 12
:padding-vertical 8
:background-color colors/white-opa-5})
(def buttons-container
{:margin-top 12
:flex-direction :row
:align-items :flex-start})
(def status
{:margin-top 12
:align-items :flex-start
:flex 1})
(defn title [replying?]
{:color colors/white
:flex-shrink 1
:max-width (when-not replying? "60%")})
(def timestamp
{:text-transform :none
:flex-grow 1
:margin-left 8
:color colors/neutral-40})
(def unread-dot
{:background-color colors/primary-50
:border-radius 4
:width 8
:height 8})
(def unread-dot-container
{:margin-left 8
:padding-horizontal 12
:padding-vertical 7})
(def context-container
{:flex-direction :row
:align-items :center
:justify-content :flex-start
:flex-wrap :wrap})
(def top-section-container
{:align-items :center
:flex-direction :row})
@@ -0,0 +1,178 @@
(ns quo2.components.notifications.activity-log.view
(:require [clojure.string :as string]
[quo.core :as quo]
[quo2.components.buttons.button :as button]
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.components.tags.status-tags :as status-tags]
[quo2.foundations.colors :as colors]
[quo2.components.notifications.activity-log.style :as style]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.i18n.i18n :as i18n]))
(def ^:private max-reply-length
280)
(defn- valid-reply?
[reply]
(<= (count reply) max-reply-length))
(defn- activity-reply-text-input
[reply-input on-update-reply]
[rn/view
[rn/view {:style {:margin-top 16
:margin-bottom 8
:flex-direction :row}}
[text/text {:weight :medium
:style {:flex-grow 1
:color colors/neutral-40}}
(i18n/label :t/your-answer)]
[text/text {:style {:flex-shrink 1
:color (if (valid-reply? @reply-input)
colors/neutral-40
colors/danger-60)}}
(str (count @reply-input) "/" max-reply-length)]]
[rn/view
;; TODO(@ilmotta): Replace with quo2 component when available.
;; https://github.com/status-im/status-mobile/issues/14364
[quo/text-input
{:on-change-text #(do (reset! reply-input %)
(when on-update-reply
(on-update-reply %)))
:auto-capitalize :none
:auto-focus true
:accessibility-label :identity-verification-reply-text-input
:placeholder (i18n/label :t/type-something)
:return-key-type :none
:multiline false
:auto-correct false}]]])
(defn- activity-icon
[icon]
[rn/view {:style style/icon}
[icon/icon icon {:color colors/white}]])
(defn- activity-context
[context replying?]
(let [first-line-offset (if replying? 4 0)
gap-between-lines 4]
(into [rn/view {:style (assoc style/context-container :margin-top first-line-offset)}]
(mapcat (fn [detail]
^{:key (hash detail)}
(if (string? detail)
(map (fn [s]
[rn/view {:style {:margin-right 4
:margin-top 0}}
[text/text {:size :paragraph-2}
s]])
(string/split detail #"\s+"))
[[rn/view {:margin-right 4
:margin-top gap-between-lines}
detail]]))
context))))
(defn- activity-message
[{:keys [title body]}]
[rn/view {:style style/message-container}
(when title
[text/text {:size :paragraph-2
:accessibility-label :activity-message-title
:style style/message-title}
title])
(if (string? body)
[text/text {:style style/message-body
:accessibility-label :activity-message-body
:size :paragraph-1}
body]
body)])
(defn- activity-buttons
[button-1 button-2 replying? reply-input]
(let [size (if replying? 40 24)
common-style (when replying?
{:padding-vertical 9
:flex-grow 1
:flex-basis 0})]
[rn/view style/buttons-container
(when button-1
[button/button (-> button-1
(assoc :size size)
(update :style merge common-style {:margin-right 8}))
(:label button-1)])
(when button-2
[button/button (-> button-2
(assoc :size size)
(assoc :disabled (and replying? (not (valid-reply? @reply-input))))
(update :style merge common-style))
(:label button-2)])]))
(defn- activity-status
[status]
[rn/view {:style style/status
:accessibility-label :activity-status}
[status-tags/status-tag {:size :small
:label (:label status)
:status status}]])
(defn- activity-title
[title replying?]
[text/text {:weight :semi-bold
:accessibility-label :activity-title
:style (style/title replying?)
:size (if replying? :heading-2 :paragraph-1)}
title])
(defn- activity-timestamp
[timestamp]
[text/text {:size :label
:accessibility-label :activity-timestamp
:style style/timestamp}
timestamp])
(defn- activity-unread-dot
[]
[rn/view {:accessibility-label :activity-unread-indicator
:style style/unread-dot-container}
[rn/view {:style style/unread-dot}]])
(defn- footer
[_]
(let [reply-input (reagent/atom "")]
(fn [{:keys [replying? on-update-reply status button-1 button-2]}]
[:<>
(when replying?
[activity-reply-text-input reply-input on-update-reply])
(cond (some? status)
[activity-status status]
(or button-1 button-2)
[activity-buttons button-1 button-2 replying? reply-input])])))
(defn view
[{:keys [icon
message
context
timestamp
title
replying?
unread?]
:as props}]
[rn/view {:accessibility-label :activity
:style style/container}
(when-not replying?
[activity-icon icon])
[rn/view {:style {:padding-left (when-not replying? 8)
:flex 1}}
[rn/view
[rn/view {:style style/top-section-container}
[activity-title title replying?]
(when-not replying?
[activity-timestamp timestamp])
(when (and unread? (not replying?))
[activity-unread-dot])]
(when context
[activity-context context replying?])]
(when message
[activity-message message])
[footer props]]])
@@ -1,157 +0,0 @@
(ns quo2.components.notifications.activity-logs
(:require [react-native.core :as rn]
[quo2.components.buttons.button :as button]
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.components.tags.status-tags :as status-tags]
[quo2.foundations.colors :as colors]))
(defn- activity-icon
[icon]
[rn/view {:height 32
:width 32
:border-radius 100
:margin-top 10
:border-width 1
:border-color colors/white-opa-5
:flex-direction :column
:align-items :center
:justify-content :center}
[icon/icon icon {:color colors/white}]])
(defn- activity-unread-dot
[]
[rn/view {:margin-left 14
:margin-right 6
:background-color colors/primary-50
:width 8
:height 8
:border-radius 4}])
(defn- activity-context
[context]
(let [margin-top 4]
(into [rn/view {:flex 1
:flex-direction :row
:align-items :center
:flex-wrap :wrap
:margin-top (+ 4 (- margin-top))}]
(map-indexed (fn [index detail]
^{:key index}
[rn/view {:margin-right 4
:margin-top margin-top}
(if (string? detail)
[text/text {:size :paragraph-2}
detail]
detail)])
context))))
(defn- activity-message
[{:keys [title body]}]
[rn/view {:border-radius 12
:margin-top 12
:padding-horizontal 12
:padding-vertical 8
:background-color colors/white-opa-5
:flex 1
:flex-direction :column}
(when title
[text/text {:size :paragraph-2
:style {:color colors/white-opa-40}}
title])
(if (string? body)
[text/text {:style {:color colors/white}
:size :paragraph-1}
body]
body)])
(defn- activity-buttons
[button-1 button-2]
(let [size 24
common-style {:padding-top 3
:padding-right 8
:padding-bottom 4
:padding-left 8}]
[rn/view {:margin-top 12
:flex 1
:flex-direction :row
:align-items :flex-start}
(when button-1
[button/button (-> button-1
(assoc :size size)
(assoc-in [:style :margin-right] 8)
(update :style merge common-style))
(:label button-1)])
(when button-2
[button/button (-> button-2
(assoc :size size)
(update :style merge common-style))
(:label button-2)])]))
(defn- activity-status
[status]
[rn/view {:margin-top 12
:align-items :flex-start
:flex 1}
[status-tags/status-tag {:size :small
:label (:label status)
:status status}]])
(defn- activity-title
[title]
[text/text {:weight :semi-bold
:style {:color colors/white}
:size :paragraph-1}
title])
(defn- activity-timestamp
[timestamp]
[rn/view {:margin-left 8}
[text/text {:size :label
:style {:text-transform :none
:color colors/neutral-40}}
timestamp]])
(defn activity-log
[{:keys [button-1
button-2
icon
message
status
context
timestamp
title
unread?]}]
[rn/view {:flex-direction :row
:flex 1
:border-radius 16
:padding-top 8
:padding-horizontal 12
:padding-bottom 12
:background-color (when unread?
colors/primary-50-opa-10)}
[activity-icon icon]
[rn/view {:flex-direction :column
:padding-left 8
:flex 1}
[rn/view {:flex 1
:align-items :center
:flex-direction :row}
[rn/view {:flex 1
:align-items :center
:flex-direction :row}
[rn/view {:flex-shrink 1}
[activity-title title]]
[activity-timestamp timestamp]]
(when unread?
[activity-unread-dot])]
(when context
[activity-context context])
(when message
[activity-message message])
(cond
(some? status)
[activity-status status]
(or button-1 button-2)
[activity-buttons button-1 button-2])]])
+4 -3
View File
@@ -3,7 +3,8 @@
[react-native.core :as rn]
[quo2.components.tabs.tab :as tab]
[reagent.core :as reagent]
[utils :as utils]
[utils.number :as utils.number]
[utils.collection :as utils.collection]
[quo2.foundations.colors :as colors]
[quo2.components.notifications.notification-dot :refer [notification-dot]]
[react-native.masked-view :as masked-view]
@@ -50,7 +51,7 @@
;; Truncate to avoid unnecessary rendering.
(if (> fade-percentage 0.99)
0.99
(utils/naive-round fade-percentage 2))))
(utils.number/naive-round fade-percentage 2))))
(defn scrollable-tabs
"Just like the component `tabs`, displays horizontally scrollable tabs with
@@ -120,7 +121,7 @@
:scroll-on-press?
:size)
(when scroll-on-press?
{:initial-scroll-index (utils/first-index #(= @active-tab-id (:id %)) data)})
{:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)})
{:ref #(reset! flat-list-ref %)
:extra-data (str @active-tab-id)
:horizontal true
+18 -4
View File
@@ -28,12 +28,18 @@
quo2.components.messages.gap
quo2.components.messages.system-message
quo2.components.reactions.reaction
quo2.components.notifications.activity-logs
quo2.components.notifications.activity-log.view
quo2.components.notifications.info-count
quo2.components.notifications.notification-dot
quo2.components.tags.tags
quo2.components.tags.context-tags
quo2.components.tabs.tabs
quo2.components.tabs.account-selector))
quo2.components.tabs.account-selector
quo2.components.navigation.top-nav
quo2.components.navigation.floating-shell-button
quo2.components.tags.status-tags
quo2.components.navigation.page-nav
quo2.components.selectors.disclaimer))
(def button quo2.components.buttons.button/button)
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
@@ -50,9 +56,16 @@
(def system-message quo2.components.messages.system-message/system-message)
(def reaction quo2.components.reactions.reaction/reaction)
(def tags quo2.components.tags.tags/tags)
(def user-avatar-tag quo2.components.tags.context-tags/user-avatar-tag)
(def context-tag quo2.components.tags.context-tags/context-tag)
(def tabs quo2.components.tabs.tabs/tabs)
(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs)
(def account-selector quo2.components.tabs.account-selector/account-selector)
(def top-nav quo2.components.navigation.top-nav/top-nav)
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
(def status-tag quo2.components.tags.status-tags/status-tag)
(def page-nav quo2.components.navigation.page-nav/page-nav)
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
;;;; AVATAR
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
@@ -70,6 +83,7 @@
(def community-stats quo2.components.community.community-view/community-stats)
(def community-tags quo2.components.community.community-view/community-tags)
(def community-title quo2.components.community.community-view/community-title)
(def permission-tag-container quo2.components.community.community-view/permission-tag-container)
(def discover-card quo2.components.community.discover-card/discover-card)
;;;; DIVIDERS
@@ -82,6 +96,6 @@
(def preview-list quo2.components.list-items.preview-list/preview-list)
;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-logs/activity-log)
(def activity-log quo2.components.notifications.activity-log.view/view)
(def info-count quo2.components.notifications.info-count/info-count)
(def notification-dot quo2.components.notifications.notification-dot/notification-dot)
(def notification-dot quo2.components.notifications.notification-dot/notification-dot)
+7 -2
View File
@@ -1,7 +1,8 @@
(ns react-native.core
(:require [reagent.core :as reagent]
["react-native" :as react-native]
[react-native.flat-list :as flat-list]))
[react-native.flat-list :as flat-list]
[react-native.section-list :as section-list]))
(def app-state ^js (.-AppState ^js react-native))
@@ -9,7 +10,7 @@
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native)))
(def image (reagent/adapt-react-class (.-Image ^js react-native)))
(def text (reagent/adapt-react-class (.-Text ^js react-native)))
(def text-input (reagent/adapt-react-class (.-TextInput ^js react-native)))
(def text-input (reagent/adapt-react-class (.-TextInput ^js react-native)))
(def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity ^js react-native)))
(def touchable-highlight (reagent/adapt-react-class (.-TouchableHighlight ^js react-native)))
@@ -17,6 +18,8 @@
(def flat-list flat-list/flat-list)
(def section-list section-list/section-list)
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js react-native)))
(def modal (reagent/adapt-react-class (.-Modal ^js react-native)))
@@ -48,3 +51,5 @@
(defn get-window []
(js->clj (.get (.-Dimensions ^js react-native) "window") :keywordize-keys true))
(def status-bar (.-StatusBar ^js react-native))
+3
View File
@@ -27,6 +27,9 @@
(defn show-overlay [comp]
(.showOverlay Navigation (clj->js comp)))
(defn pop-to-root [tab]
(.popToRoot Navigation (clj->js tab)))
(defn dissmiss-overlay [comp]
(.catch (.dismissOverlay Navigation comp) #()))
+9 -1
View File
@@ -2,8 +2,9 @@
(:require ["react-native" :as rn]
[reagent.core :as reagent]
[clojure.string :as string]
["react-native-linear-gradient" :default LinearGradient]
["react-native-reanimated" :default reanimated
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring Easing Keyframe)]))
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring withRepeat Easing Keyframe)]))
;; Animated Components
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
@@ -12,6 +13,8 @@
(def image (reagent/adapt-react-class (.-Image reanimated)))
(def touchable-opacity (create-animated-component (.-TouchableOpacity ^js rn)))
(def linear-gradient (create-animated-component LinearGradient))
;; Hooks
(def use-shared-value useSharedValue)
(def use-animated-style useAnimatedStyle)
@@ -21,6 +24,7 @@
(def with-delay withDelay)
(def with-spring withSpring)
(def key-frame Keyframe)
(def with-repeat withRepeat)
;; Easings
(def bezier (.-bezier ^js Easing))
@@ -68,3 +72,7 @@
(defn animate-shared-value-with-delay [anim val duration easing delay]
(set-shared-value anim (with-delay delay (with-timing val (js-obj "duration" duration
"easing" (get easings easing))))))
(defn animate-shared-value-with-repeat [anim val duration easing number-of-repetitions reverse?]
(set-shared-value anim (with-repeat (with-timing val (js-obj "duration" duration
"easing" (get easings easing))) number-of-repetitions reverse?)))
+40
View File
@@ -0,0 +1,40 @@
(ns react-native.section-list
(:require [reagent.core :as reagent]
[react-native.flat-list :as flat-list]
["react-native" :as react-native]))
(def section-list-class (reagent/adapt-react-class (.-SectionList react-native)))
(def memo-wrap-render-fn
(memoize
(fn [f render-data]
(fn [^js data]
(reagent/as-element [f (.-item data) (.-index data) (.-separators data) render-data])))))
(defn- wrap-render-section-header-fn [f]
(fn [^js data]
(let [^js section (.-section data)]
(reagent/as-element [f {:title (.-title section)
:data (.-data section)}]))))
(defn- wrap-per-section-render-fn [props]
(update
(if-let [f (:render-fn props)]
(assoc (dissoc props :render-fn :render-data) :renderItem (memo-wrap-render-fn f (:render-data props)))
props)
:data to-array))
(defn section-list
"A wrapper for SectionList.
To render something on empty sections, use renderSectionFooter and conditionaly
render on empty data
See https://facebook.github.io/react-native/docs/sectionlist.html"
[{:keys [sections render-section-header-fn render-section-footer-fn style] :as props}]
[section-list-class
(merge (flat-list/base-list-props props)
props
(when render-section-footer-fn
{:renderSectionFooter (wrap-render-section-header-fn render-section-footer-fn)})
{:sections (clj->js (map wrap-per-section-render-fn sections))
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)
:style style})])
+80 -29
View File
@@ -6,6 +6,26 @@
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
;;;; Navigation
(fx/defn open-activity-center
{:events [:activity-center/open]}
[_]
(rf/dispatch [:show-popover {:view :activity-center
:style {:margin 0}
:disable-touchable-overlay? true
:blur-view? true
:blur-view-props {:blur-amount 20
:blur-type :dark}}]))
;;;; Misc
(fx/defn process-notification-failure
{:events [:activity-center/process-notification-failure]}
[_ notification-id action error]
(log/warn (str "Failed to " action)
{:notification-id notification-id :error error}))
;;;; Notification reconciliation
(defn- update-notifications
@@ -18,8 +38,7 @@
~excessively~ big, this implementation will probably need to be revisited."
[db-notifications new-notifications]
(reduce (fn [acc {:keys [id type read] :as notification}]
(let [filter-status (if read :read :unread)
remove-notification (fn [data]
(let [remove-notification (fn [data]
(remove #(= id (:id %)) data))
insert-and-sort (fn [data]
(->> notification
@@ -27,14 +46,17 @@
(sort-by (juxt :timestamp :id))
reverse))]
(as-> acc $
(update-in $ [type :read :data] remove-notification)
(update-in $ [type :all :data] remove-notification)
(update-in $ [types/no-type :all :data] remove-notification)
(update-in $ [type :unread :data] remove-notification)
(update-in $ [types/no-type :read :data] remove-notification)
(update-in $ [types/no-type :unread :data] remove-notification)
(if (or (:dismissed notification) (:accepted notification))
$
(-> $ (update-in [type filter-status :data] insert-and-sort)
(update-in [types/no-type filter-status :data] insert-and-sort))))))
(cond-> (-> $
(update-in [type :all :data] insert-and-sort)
(update-in [types/no-type :all :data] insert-and-sort))
(not read) (update-in [type :unread :data] insert-and-sort)
(not read) (update-in [types/no-type :unread :data] insert-and-sort))))))
db-notifications
new-notifications))
@@ -45,38 +67,69 @@
{:db (update-in db [:activity-center :notifications]
update-notifications new-notifications)}))
;;;; Contact verification
(fx/defn contact-verification-decline
{:events [:activity-center.contact-verification/decline]}
[_ contact-verification-id]
{::json-rpc/call [{:method "wakuext_declineContactVerificationRequest"
:params [contact-verification-id]
:on-success #(rf/dispatch [:activity-center.contact-verification/decline-success %])
:on-error #(rf/dispatch [:activity-center.contact-verification/decline-error contact-verification-id %])}]})
(fx/defn contact-verification-decline-success
{:events [:activity-center.contact-verification/decline-success]}
(fx/defn notifications-reconcile-from-response
{:events [:activity-center/reconcile-notifications-from-response]}
[cofx response]
(->> response
:activityCenterNotifications
(map data-store.activities/<-rpc)
(notifications-reconcile cofx)))
(fx/defn contact-verification-decline-error
{:events [:activity-center.contact-verification/decline-error]}
[_ contact-verification-id error]
(log/warn "Failed to decline contact verification"
{:contact-verification-id contact-verification-id
:error error})
nil)
;;;; Contact verification
(fx/defn contact-verification-decline
{:events [:activity-center.contact-verification/decline]}
[_ notification-id]
{::json-rpc/call [{:method "wakuext_declineContactVerificationRequest"
:params [notification-id]
:on-success #(rf/dispatch [:activity-center/reconcile-notifications-from-response %])
:on-error #(rf/dispatch [:activity-center/process-notification-failure
notification-id
:contact-verification/decline
%])}]})
(fx/defn contact-verification-reply
{:events [:activity-center.contact-verification/reply]}
[_ notification-id reply]
{::json-rpc/call [{:method "wakuext_acceptContactVerificationRequest"
:params [notification-id reply]
:on-success #(rf/dispatch [:activity-center/reconcile-notifications-from-response %])
:on-error #(rf/dispatch [:activity-center/process-notification-failure
notification-id
:contact-verification/reply
%])}]})
(fx/defn contact-verification-mark-as-trusted
{:events [:activity-center.contact-verification/mark-as-trusted]}
[_ notification-id]
{::json-rpc/call [{:method "wakuext_verifiedTrusted"
:params [{:id notification-id}]
:on-success #(rf/dispatch [:activity-center/reconcile-notifications-from-response %])
:on-error #(rf/dispatch [:activity-center/process-notification-failure
notification-id
:contact-verification/mark-as-trusted
%])}]})
(fx/defn contact-verification-mark-as-untrustworthy
{:events [:activity-center.contact-verification/mark-as-untrustworthy]}
[_ notification-id]
{::json-rpc/call [{:method "wakuext_verifiedUntrustworthy"
:params [{:id notification-id}]
:on-success #(rf/dispatch [:activity-center/reconcile-notifications-from-response %])
:on-error #(rf/dispatch [:activity-center/process-notification-failure
notification-id
:contact-verification/mark-as-untrustworthy
%])}]})
;;;; Notifications fetching and pagination
(def defaults
{:filter-status :unread
:filter-type types/no-type
:notifications-per-page 10})
;; Choose the maximum number of notifications that *usually/safely* fit on
;; most screens, so that the UI doesn't have to needlessly render
;; notifications.
:notifications-per-page 8})
(def start-or-end-cursor
"")
@@ -86,15 +139,13 @@
(and (some? cursor)
(not= cursor start-or-end-cursor)))
(def ^:const status-read 1)
(def ^:const status-unread 2)
(def ^:const status-all 3)
(defn status [filter-status]
(case filter-status
:read status-read
:unread status-unread
:all status-all
:all status-all
99))
(fx/defn notifications-fetch
+219 -269
View File
@@ -3,10 +3,11 @@
[day8.re-frame.test :as rf-test]
[re-frame.core :as rf]
[status-im.activity-center.notification-types :as types]
[status-im.constants :as constants]
[status-im.ethereum.json-rpc :as json-rpc]
status-im.events
[status-im.test-helpers :as h]
[status-im.utils.config :as config]))
[status-im2.setup.config :as config]))
(defn setup []
(h/register-helper-events)
@@ -14,87 +15,140 @@
;;;; Contact verification
(def notification-id 24)
(def contact-verification-rpc-response
{:activityCenterNotifications
[{:accepted false
:author "0x04d03f"
:chatId "0x04d03f"
:contactVerificationStatus constants/contact-verification-status-pending
:dismissed false
:id notification-id
:message {}
:name "0x04d03f"
:read true
:timestamp 1666647286000
:type types/contact-verification}]})
(def contact-verification-expected-notification
{:accepted false
:author "0x04d03f"
:chat-id "0x04d03f"
:contact-verification-status constants/contact-verification-status-pending
:dismissed false
:id notification-id
:last-message nil
:message {:command-parameters nil
:content {:chat-id nil
:ens-name nil
:image nil
:line-count nil
:links nil
:parsed-text nil
:response-to nil
:rtl? nil
:sticker nil
:text nil}
:outgoing false
:outgoing-status nil
:quoted-message nil}
:name "0x04d03f"
:read true
:reply-message nil
:timestamp 1666647286000
:type types/contact-verification})
(defn test-log-on-failure
[{:keys [notification-id event action]}]
(rf-test/run-test-sync
(setup)
(h/using-log-test-appender
(fn [logs]
(h/stub-fx-with-callbacks ::json-rpc/call :on-error (constantly :fake-error))
(rf/dispatch event)
(is (= {:args [(str "Failed to " action)
{:notification-id notification-id
:error :fake-error}]
:level :warn}
(last @logs)))))))
(defn test-contact-verification-event
[{:keys [event expected-rpc-call]}]
(rf-test/run-test-sync
(setup)
(let [spy-queue (atom [])]
(h/stub-fx-with-callbacks ::json-rpc/call :on-success (constantly contact-verification-rpc-response))
(h/spy-fx spy-queue ::json-rpc/call)
(rf/dispatch event)
(is (= {types/no-type
{:all {:data [contact-verification-expected-notification]}
:unread {:data []}}
types/contact-verification
{:all {:data [contact-verification-expected-notification]}
:unread {:data []}}}
(get-in (h/db) [:activity-center :notifications])))
(is (= expected-rpc-call
(-> @spy-queue
(get-in [0 :args 0])
(select-keys [:method :params])))))))
(deftest contact-verification-decline-test
(with-redefs [config/new-activity-center-enabled? true]
(testing "successfully declines and reconciles returned notification"
(rf-test/run-test-sync
(setup)
(let [spy-queue (atom [])
contact-verification-id 24
expected-notification {:accepted false
:author "0x04d03f"
:chat-id "0x04d03f"
:contact-verification-status 3
:dismissed false
:id 24
:last-message nil
:message {:command-parameters nil
:content {:chat-id nil
:ens-name nil
:image nil
:line-count nil
:links nil
:parsed-text nil
:response-to nil
:rtl? nil
:sticker nil
:text nil}
:outgoing false
:outgoing-status nil
:quoted-message nil}
:name "0x04d03f"
:read true
:reply-message nil
:timestamp 1666647286000
:type types/contact-verification}]
(h/stub-fx-with-callbacks
::json-rpc/call
:on-success (constantly {:activityCenterNotifications
[{:accepted false
:author "0x04d03f"
:chatId "0x04d03f"
:contactVerificationStatus 3
:dismissed false
:id contact-verification-id
:message {}
:name "0x04d03f"
:read true
:timestamp 1666647286000
:type types/contact-verification}]}))
(testing "declines notification and reconciles"
(test-contact-verification-event
{:event [:activity-center.contact-verification/decline notification-id]
:expected-rpc-call {:method "wakuext_declineContactVerificationRequest"
:params [notification-id]}}))
(testing "logs on failure"
(test-log-on-failure
{:notification-id notification-id
:event [:activity-center.contact-verification/decline notification-id]
:action :contact-verification/decline}))))
(h/spy-fx spy-queue ::json-rpc/call)
(deftest contact-verification-reply-test
(with-redefs [config/new-activity-center-enabled? true]
(testing "sends reply and reconciles"
(let [reply "any answer"]
(test-contact-verification-event
{:event [:activity-center.contact-verification/reply notification-id reply]
:expected-rpc-call {:method "wakuext_acceptContactVerificationRequest"
:params [notification-id reply]}})))
(testing "logs on failure"
(test-log-on-failure
{:notification-id notification-id
:event [:activity-center.contact-verification/reply notification-id "any answer"]
:action :contact-verification/reply}))))
(rf/dispatch [:activity-center.contact-verification/decline contact-verification-id])
(deftest contact-verification-mark-as-trusted-test
(with-redefs [config/new-activity-center-enabled? true]
(testing "marks notification as trusted and reconciles"
(test-contact-verification-event
{:event [:activity-center.contact-verification/mark-as-trusted notification-id]
:expected-rpc-call {:method "wakuext_verifiedTrusted"
:params [{:id notification-id}]}}))
(testing "logs on failure"
(test-log-on-failure
{:notification-id notification-id
:event [:activity-center.contact-verification/mark-as-trusted notification-id]
:action :contact-verification/mark-as-trusted}))))
(is (= {:method "wakuext_declineContactVerificationRequest"
:params [contact-verification-id]}
(-> @spy-queue
(get-in [0 :args 0])
(select-keys [:method :params]))))
(is (= {types/no-type
{:read {:data [expected-notification]}
:unread {:data []}}
types/contact-verification
{:read {:data [expected-notification]}
:unread {:data []}}}
(get-in (h/db) [:activity-center :notifications]))))))
(testing "logs failure"
(rf-test/run-test-sync
(setup)
(let [contact-verification-id 666]
(h/using-log-test-appender
(fn [logs]
(h/stub-fx-with-callbacks ::json-rpc/call :on-error (constantly :fake-error))
(rf/dispatch [:activity-center.contact-verification/decline contact-verification-id])
(is (= {:args ["Failed to decline contact verification"
{:contact-verification-id contact-verification-id
:error :fake-error}]
:level :warn}
(last @logs))))))))))
(deftest contact-verification-mark-as-untrustworthy-test
(with-redefs [config/new-activity-center-enabled? true]
(testing "marks notification as untrustworthy and reconciles"
(test-contact-verification-event
{:event [:activity-center.contact-verification/mark-as-untrustworthy notification-id]
:expected-rpc-call {:method "wakuext_verifiedUntrustworthy"
:params [{:id notification-id}]}}))
(testing "logs on failure"
(test-log-on-failure
{:notification-id notification-id
:event [:activity-center.contact-verification/mark-as-untrustworthy notification-id]
:action :contact-verification/mark-as-untrustworthy}))))
;;;; Notification reconciliation
@@ -104,12 +158,12 @@
(rf-test/run-test-sync
(setup)
(let [notifications {types/one-to-one-chat
{:read {:cursor ""
{:all {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}
{:id "0x2"
:read true
:read false
:type types/one-to-one-chat}]}
:unread {:cursor ""
:data [{:id "0x3"
@@ -129,216 +183,112 @@
(testing "removes dismissed or accepted notifications"
(rf-test/run-test-sync
(setup)
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1" :read true :type types/one-to-one-chat}
{:id "0x2" :read true :type types/one-to-one-chat}]}
:unread {:cursor ""
:data [{:id "0x3" :read false :type types/one-to-one-chat}]}}
types/private-group-chat
{:unread {:cursor ""
:data [{:id "0x4" :read false :type types/private-group-chat}
{:id "0x6" :read false :type types/private-group-chat}]}}}])
(let [notif-1 {:id "0x1" :read true :type types/one-to-one-chat}
notif-2 {:id "0x2" :read false :type types/one-to-one-chat}
notif-3 {:id "0x3" :read false :type types/one-to-one-chat}
notif-4 {:id "0x4" :read false :type types/private-group-chat}
notif-5 {:id "0x5" :read true :type types/private-group-chat}
notif-6 {:id "0x6" :read false :type types/private-group-chat}]
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:all {:cursor "" :data [notif-1 notif-2]}
:unread {:cursor "" :data [notif-3]}}
types/private-group-chat
{:unread {:cursor "" :data [notif-4 notif-6]}}}])
(rf/dispatch [:activity-center.notifications/reconcile
[{:id "0x1"
:read true
:type types/one-to-one-chat
:dismissed true}
{:id "0x3"
:read false
:type types/one-to-one-chat
:accepted true}
{:id "0x4"
:read false
:type types/private-group-chat
:dismissed true}
{:id "0x5"
:read false
:type types/private-group-chat
:accepted true}]])
(rf/dispatch [:activity-center.notifications/reconcile
[(assoc notif-1 :dismissed true)
(assoc notif-3 :accepted true)
(assoc notif-4 :dismissed true)
notif-5]])
(is (= {types/no-type
{:read {:data []}
:unread {:data []}}
types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x2"
:read true
:type types/one-to-one-chat}]}
:unread {:cursor ""
:data []}}
types/private-group-chat
{:read {:data []}
:unread {:cursor ""
:data [{:id "0x6"
:read false
:type types/private-group-chat}]}}}
(get-in (h/db) [:activity-center :notifications])))))
(is (= {types/no-type
{:all {:data [notif-5]}
:unread {:data []}}
types/one-to-one-chat
{:all {:cursor "" :data [notif-2]}
:unread {:cursor "" :data []}}
types/private-group-chat
{:all {:data [notif-5]}
:unread {:cursor "" :data [notif-6]}}}
(get-in (h/db) [:activity-center :notifications]))))))
(testing "replaces old notifications with newly arrived ones"
(rf-test/run-test-sync
(setup)
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/no-type
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}]}
:unread {:cursor ""
:data [{:id "0x4"
:read false
:type types/private-group-chat}
{:id "0x6"
:read false
:type types/private-group-chat}]}}
types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}]}}
types/private-group-chat
{:unread {:cursor ""
:data [{:id "0x4"
:read false
:type types/private-group-chat}
{:id "0x6"
:read false
:type types/private-group-chat}]}}}])
(let [notif-1 {:id "0x1" :read true :type types/one-to-one-chat}
notif-4 {:id "0x4" :read false :type types/private-group-chat}
notif-6 {:id "0x6" :read false :type types/private-group-chat}
new-notif-1 (assoc notif-1 :last-message {})
new-notif-4 (assoc notif-4 :author "0xabc")]
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/no-type
{:all {:cursor "" :data [notif-1]}
:unread {:cursor "" :data [notif-4 notif-6]}}
types/one-to-one-chat
{:all {:cursor "" :data [notif-1]}}
types/private-group-chat
{:unread {:cursor "" :data [notif-4 notif-6]}}}])
(rf/dispatch [:activity-center.notifications/reconcile
[{:id "0x1"
:read true
:type types/one-to-one-chat
:last-message {}}
{:id "0x4"
:read false
:type types/private-group-chat
:author "0xabc"}
{:id "0x6"
:read false
:type types/private-group-chat}]])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1 new-notif-4 notif-6]])
(is (= {types/no-type
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat
:last-message {}}]}
:unread {:cursor ""
:data [{:id "0x6"
:read false
:type types/private-group-chat}
{:id "0x4"
:read false
:type types/private-group-chat
:author "0xabc"}]}}
types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat
:last-message {}}]}
:unread {:data []}}
types/private-group-chat
{:read {:data []}
:unread {:cursor ""
:data [{:id "0x6"
:read false
:type types/private-group-chat}
{:id "0x4"
:read false
:type types/private-group-chat
:author "0xabc"}]}}}
(get-in (h/db) [:activity-center :notifications])))))
(is (= {types/no-type
{:all {:cursor "" :data [notif-6 new-notif-4 new-notif-1]}
:unread {:cursor "" :data [notif-6 new-notif-4]}}
types/one-to-one-chat
{:all {:cursor "" :data [new-notif-1]}
:unread {:data []}}
types/private-group-chat
{:all {:data [notif-6 new-notif-4]}
:unread {:cursor "" :data [notif-6 new-notif-4]}}}
(get-in (h/db) [:activity-center :notifications]))))))
(testing "reconciles notifications that switched their read/unread status"
(rf-test/run-test-sync
(setup)
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}]}}}])
(let [notif-1 {:id "0x1" :read true :type types/one-to-one-chat}
new-notif-1 (assoc notif-1 :read false)]
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:all {:cursor "" :data [notif-1]}}}])
(rf/dispatch [:activity-center.notifications/reconcile
[{:id "0x1"
:read false
:type types/one-to-one-chat}]])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1]])
(is (= {types/no-type
{:read {:data []}
:unread {:data [{:id "0x1"
:read false
:type types/one-to-one-chat}]}}
(is (= {types/no-type
{:all {:data [new-notif-1]}
:unread {:data [new-notif-1]}}
types/one-to-one-chat
{:read {:cursor ""
:data []}
:unread {:data [{:id "0x1"
:read false
:type types/one-to-one-chat}]}}}
(get-in (h/db) [:activity-center :notifications])))))
types/one-to-one-chat
{:all {:cursor "" :data [new-notif-1]}
:unread {:data [new-notif-1]}}}
(get-in (h/db) [:activity-center :notifications]))))))
;; Sorting by timestamp and ID is compatible with what the backend does when
;; returning paginated results.
(testing "sorts notifications by timestamp and id in descending order"
(rf-test/run-test-sync
(setup)
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1" :read true :type types/one-to-one-chat :timestamp 1}
{:id "0x2" :read true :type types/one-to-one-chat :timestamp 1}]}
:unread {:cursor ""
:data [{:id "0x3" :read false :type types/one-to-one-chat :timestamp 50}
{:id "0x4" :read false :type types/one-to-one-chat :timestamp 100}
{:id "0x5" :read false :type types/one-to-one-chat :timestamp 100}]}}}])
(let [notif-1 {:id "0x1" :read true :type types/one-to-one-chat :timestamp 1}
notif-2 {:id "0x2" :read true :type types/one-to-one-chat :timestamp 1}
notif-3 {:id "0x3" :read false :type types/one-to-one-chat :timestamp 50}
notif-4 {:id "0x4" :read false :type types/one-to-one-chat :timestamp 100}
notif-5 {:id "0x5" :read false :type types/one-to-one-chat :timestamp 100}
new-notif-1 (assoc notif-1 :last-message {})
new-notif-4 (assoc notif-4 :last-message {})]
(rf/dispatch [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:all {:cursor "" :data [notif-1 notif-2]}
:unread {:cursor "" :data [notif-3 notif-4 notif-5]}}}])
(rf/dispatch [:activity-center.notifications/reconcile
[{:id "0x1" :read true :type types/one-to-one-chat :timestamp 1 :last-message {}}
{:id "0x4" :read false :type types/one-to-one-chat :timestamp 100 :last-message {}}]])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1 new-notif-4]])
(is (= {types/no-type
{:read {:data [{:id "0x1"
:read true
:type types/one-to-one-chat
:timestamp 1
:last-message {}}]}
:unread {:data [{:id "0x4"
:read false
:type types/one-to-one-chat
:timestamp 100
:last-message {}}]}}
types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x2"
:read true
:type types/one-to-one-chat
:timestamp 1}
{:id "0x1"
:read true
:type types/one-to-one-chat
:timestamp 1
:last-message {}}]}
:unread {:cursor ""
:data [{:id "0x5"
:read false
:type types/one-to-one-chat
:timestamp 100}
{:id "0x4"
:read false
:type types/one-to-one-chat
:timestamp 100
:last-message {}}
{:id "0x3"
:read false
:type types/one-to-one-chat
:timestamp 50}]}}}
(get-in (h/db) [:activity-center :notifications])))))))
(is (= {types/no-type
{:all {:data [new-notif-4 new-notif-1]}
:unread {:data [new-notif-4]}}
types/one-to-one-chat
{:all {:cursor "" :data [new-notif-4 notif-2 new-notif-1]}
:unread {:cursor "" :data [notif-5 new-notif-4 notif-3]}}}
(get-in (h/db) [:activity-center :notifications]))))))))
;;;; Notifications fetching and pagination
@@ -456,12 +406,12 @@
(let [spy-queue (atom [])]
(h/spy-fx spy-queue ::json-rpc/call)
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
:read])
:all])
(rf/dispatch [:test/assoc-in [:activity-center :filter :type]
types/one-to-one-chat])
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :read :cursor]
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :all :cursor]
"10"])
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :read :loading?]
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :all :loading?]
true])
(rf/dispatch [:activity-center.notifications/fetch-next-page])
@@ -6,7 +6,7 @@
(def ^:const mention 3)
(def ^:const reply 4)
(def ^:const contact-request 5)
(def ^:const contact-verification 6)
(def ^:const contact-verification 10)
;; TODO: Remove this constant once the old Notification Center code is removed.
;; Its value clashes with the new constant `-contact-verification`
+5 -5
View File
@@ -134,7 +134,7 @@
(re-frame/dispatch [::failed-to-import %]))}]})
(fx/defn join
{:events [::join]}
{:events [:communities/join]}
[cofx community-id]
{::json-rpc/call [{:method "wakuext_joinCommunity"
:params [community-id]
@@ -156,8 +156,8 @@
(re-frame/dispatch [::failed-to-request-to-join %]))}]})
(fx/defn leave
{:events [::leave]}
[{:keys [db] :as cofx} community-id]
{:events [:communities/leave]}
[{:keys [db]} community-id]
(let [community-chat-ids (map #(str community-id %)
(keys (get-in db [:communities community-id :chats])))]
{:clear-message-notifications [community-chat-ids
@@ -325,7 +325,7 @@
{:db (assoc db :communities/create-channel {})})
(fx/defn invite-people-pressed
{:events [::invite-people-pressed]}
{:events [:communities/invite-people-pressed]}
[cofx id]
(fx/merge cofx
(reset-community-id-input id)
@@ -333,7 +333,7 @@
(navigation/open-modal :invite-people-community {:invite? true})))
(fx/defn share-community-pressed
{:events [::share-community-pressed]}
{:events [:communities/share-community-pressed]}
[cofx id]
(fx/merge cofx
(reset-community-id-input id)
+7 -6
View File
@@ -21,12 +21,13 @@
(def ^:const contact-request-state-received 3)
(def ^:const contact-request-state-dismissed 4)
(def ^:const contact-verification-state-unknown 0)
(def ^:const contact-verification-state-pending 1)
(def ^:const contact-verification-state-accepted 2)
(def ^:const contact-verification-state-declined 3)
(def ^:const contact-verification-state-cancelled 4)
(def ^:const contact-verification-state-trusted 5)
(def ^:const contact-verification-status-unknown 0)
(def ^:const contact-verification-status-pending 1)
(def ^:const contact-verification-status-accepted 2)
(def ^:const contact-verification-status-declined 3)
(def ^:const contact-verification-status-cancelled 4)
(def ^:const contact-verification-status-trusted 5)
(def ^:const contact-verification-status-untrustworthy 6)
(def ^:const emoji-reaction-love 1)
(def ^:const emoji-reaction-thumbs-up 2)
+1 -1
View File
@@ -4,7 +4,7 @@
[status-im.constants :as constants]
[status-im.activity-center.notification-types :as notification-types]
[status-im.data-store.messages :as messages]
[status-im.utils.config :as config]))
[status-im2.setup.config :as config]))
(defn- rpc->type [{:keys [type name] :as chat}]
(case type
@@ -3,7 +3,7 @@
[status-im.constants :as constants]
[status-im.activity-center.notification-types :as notification-types]
[status-im.data-store.activities :as store]
[status-im.utils.config :as config]))
[status-im2.setup.config :as config]))
(def chat-id
"0x04c66155")
@@ -13,7 +13,7 @@
(def raw-notification
{:chatId chat-id
:contactVerificationStatus constants/contact-verification-state-pending
:contactVerificationStatus constants/contact-verification-status-pending
:lastMessage {}
:name chat-name
:replyMessage {}})
@@ -23,7 +23,7 @@
(testing "renames keys"
(is (= {:name chat-name
:chat-id chat-id
:contact-verification-status constants/contact-verification-state-pending}
:contact-verification-status constants/contact-verification-status-pending}
(-> raw-notification
store/<-rpc
(dissoc :last-message :message :reply-message)))))
+1
View File
@@ -46,6 +46,7 @@
status-im.ui.screens.privacy-and-security-settings.events
[status-im.utils.dimensions :as dimensions]
[status-im.utils.fx :as fx]
status-im.utils.logging.core
[status-im.utils.universal-links.core :as universal-links]
[status-im.utils.utils :as utils]
status-im.visibility-status-updates.core
+1 -1
View File
@@ -22,7 +22,7 @@
::logout nil
::multiaccounts/webview-debug-changed false
:keychain/clear-user-password key-uid
::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])}
:setup/open-multiaccounts #(re-frame/dispatch [:setup/initialize-multiaccounts % {:logout? logout?}])}
(keychain/save-auth-method key-uid auth-method)
(wallet/clear-timeouts)
(init/initialize-app-db))))
+444
View File
@@ -0,0 +1,444 @@
(ns status-im.navigation.core
(:require
["react-native" :as rn]
["react-native-gesture-handler" :refer (gestureHandlerRootHOC)]
["react-native-navigation" :refer (Navigation)]
[clojure.set :as clojure.set]
[quo.components.text-input :as quo.text-input]
[quo.design-system.colors :as quo.colors]
[re-frame.core :as re-frame]
[status-im.multiaccounts.login.core :as login-core]
[status-im.navigation.roots :as roots]
[status-im.navigation.state :as state]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]
[status-im.ui.screens.views :as views]
[status-im.utils.fx :as fx]
[status-im.utils.platform :as platform]
[taoensso.encore :as enc]
[taoensso.timbre :as log]))
(def debug? ^boolean js/goog.DEBUG)
(def splash-screen (-> rn .-NativeModules .-SplashScreen))
(defonce set-navigation-default-options
(.setDefaultOptions Navigation (clj->js {:layout {:orientation "portrait"}})))
;; REGISTER COMPONENT (LAZY)
(defn reg-comp [key]
(log/debug "reg-comp" key)
(if-let [comp (get views/components (keyword key))]
(.registerComponent Navigation key (fn [] (views/component comp)))
(let [screen (views/screen key)]
(.registerComponent Navigation key (fn [] (gestureHandlerRootHOC screen)) (fn [] screen)))))
(defonce rset-lazy-reg
(.setLazyComponentRegistrator Navigation reg-comp))
(defn dismiss-all-modals []
(log/debug "dissmiss-all-modals")
(when @state/curr-modal
(reset! state/curr-modal false)
(reset! state/dissmissing true)
(doseq [modal @state/modals]
(.dismissModal Navigation (name modal)))
(reset! state/modals [])))
;; PUSH SCREEN
(defn navigate [comp]
(log/debug "NAVIGATE" comp)
(let [{:keys [options]} (get views/screens comp)]
(.push Navigation
(name @state/root-comp-id)
(clj->js {:component {:id comp
:name comp
:options (merge options
(roots/status-bar-options)
(roots/merge-top-bar (roots/topbar-options) options))}}))
;;if we push the screen from modal, we want to dismiss all modals
(dismiss-all-modals)))
;; OPEN MODAL
(defn update-modal-topbar-options [options]
(log/debug "update-modal-topbar-options" options)
(merge options
(roots/merge-top-bar {:elevation 0
:noBorder true
:title {:color quo.colors/black}
:background {:color quo.colors/white}
:leftButtonColor quo.colors/black
:leftButtons {:id "dismiss-modal"
:icon (icons/icon-source :main-icons/close)}}
options)))
(defn open-modal [comp]
(log/debug "open-modal" comp)
(let [{:keys [options]} (get views/screens comp)]
(if @state/dissmissing
(reset! state/dissmissing comp)
(do
(reset! state/curr-modal true)
(swap! state/modals conj comp)
(.showModal Navigation
(clj->js {:stack {:children
[{:component
{:name comp
:id comp
:options (update-modal-topbar-options
(merge (roots/status-bar-options)
(roots/default-root)
options))}}]}}))))))
(re-frame/reg-fx :open-modal-fx open-modal)
;; DISSMISS MODAL
(defn dissmissModal []
(log/debug "dissmissModal")
(reset! state/dissmissing true)
(.dismissModal Navigation (name (last @state/modals))))
(defonce register-nav-button-reg
(.registerNavigationButtonPressedListener
(.events Navigation)
(fn [^js evn]
(let [id (.-buttonId evn)]
(if (= "dismiss-modal" id)
(do
(when-let [event (get-in views/screens [(last @state/modals) :on-dissmiss])]
(re-frame/dispatch event))
(dissmissModal))
(when-let [handler (get-in views/screens [(keyword id) :right-handler])]
(handler)))))))
(defn set-view-id [view-id]
(log/debug "set-view-id" view-id)
(when-let [{:keys [on-focus]} (get views/screens view-id)]
(re-frame/dispatch [:set-view-id view-id])
(re-frame/dispatch [:screens/on-will-focus view-id])
(when on-focus
(re-frame/dispatch on-focus))))
(defonce register-modal-reg
(.registerModalDismissedListener
(.events Navigation)
(fn [_]
(if (> (count @state/modals) 1)
(let [new-modals (butlast @state/modals)]
(reset! state/modals (vec new-modals))
(set-view-id (last new-modals)))
(do
(reset! state/modals [])
(reset! state/curr-modal false)
(set-view-id @state/pushed-screen-id)))
(let [comp @state/dissmissing]
(reset! state/dissmissing false)
(when (keyword? comp)
(open-modal comp))))))
;; SCREEN DID APPEAR
(defonce screen-appear-reg
(.registerComponentDidAppearListener
(.events Navigation)
(fn [^js evn]
(let [view-id (keyword (.-componentName evn))]
(log/debug "screen-appear-reg" view-id)
(when (get views/screens view-id)
(when (and (not= view-id :bottom-sheet)
(not= view-id :popover)
(not= view-id :visibility-status-popover))
(set-view-id view-id)
(when-not @state/curr-modal
(reset! state/pushed-screen-id view-id))))))))
;; SCREEN DID DISAPPEAR
(defonce screen-disappear-reg
(.registerComponentDidDisappearListener
(.events Navigation)
(fn [^js evn]
(let [view-id (keyword (.-componentName evn))]
(when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover" "wallet-connect-sheet" "wallet-connect-success-sheet" "wallet-connect-app-management-sheet"}
(.-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
:init-root-fx
(fn [new-root-id]
(log/debug :init-root-fx new-root-id)
(reset! state/root-comp-id new-root-id)
(reset! state/root-id @state/root-comp-id)
(.setRoot Navigation (clj->js (get (roots/roots) new-root-id)))))
(re-frame/reg-fx
:init-root-with-component-fx
(fn [[new-root-id new-root-comp-id]]
(log/debug :init-root-with-component-fx new-root-id new-root-comp-id)
(reset! state/root-comp-id new-root-comp-id)
(reset! state/root-id @state/root-comp-id)
(.setRoot Navigation (clj->js (get (roots/roots) new-root-id)))))
(fx/defn set-multiaccount-root
{:events [::set-multiaccount-root]}
[{:keys [db]}]
(log/debug :set-multiaccounts-root)
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
keycard-account? (boolean (get-in db [:multiaccounts/multiaccounts
key-uid
:keycard-pairing]))]
{:init-root-fx (if keycard-account? :multiaccounts-keycard :multiaccounts)}))
(defonce rset-app-launched
(.registerAppLaunchedListener (.events Navigation)
(fn []
(reset! state/curr-modal false)
(reset! state/dissmissing false)
(if (or (= @state/root-id :multiaccounts)
(= @state/root-id :multiaccounts-keycard))
(re-frame/dispatch-sync [::set-multiaccount-root])
(when @state/root-id
(reset! state/root-comp-id @state/root-id)
(.setRoot Navigation (clj->js (get (roots/roots) @state/root-id)))
(re-frame/dispatch [::login-core/check-last-chat])))
(.hide ^js splash-screen))))
(defn get-screen-component [comp]
(log/debug :get-screen-component comp)
(let [{:keys [options]} (get views/screens comp)]
{:component {:id comp
:name comp
:options (merge options
(roots/status-bar-options)
(roots/merge-top-bar (roots/topbar-options) options))}}))
;; SET STACK ROOT
(re-frame/reg-fx
:set-stack-root-fx
(fn [[stack comp]]
(log/debug :set-stack-root-fx stack comp)
(.setStackRoot Navigation
(name stack)
(clj->js (if (vector? comp)
(mapv get-screen-component comp)
(get-screen-component comp))))))
;; BOTTOM TABS
(def tab-root-ids {0 :chat-stack
1 :browser-stack
2 :wallet-stack
3 :status-stack
4 :profile-stack})
(def tab-key-idx {:chat 0
:browser 1
:wallet 2
:status 3
:profile 4})
(re-frame/reg-fx
:change-tab-fx
(fn [tab]
(log/debug :change-tab-fx)
(reset! state/root-comp-id (get tab-root-ids (get tab-key-idx tab)))
(.mergeOptions Navigation "tabs-stack" (clj->js {:bottomTabs {:currentTabIndex (get tab-key-idx tab)}}))
;;when we change tab we want to dismiss all modals
(dismiss-all-modals)))
;issue on ios https://github.com/wix/react-native-navigation/issues/7146
(re-frame/reg-fx
:change-tab-count-fx
(fn [[tab cnt]]
(log/debug :change-tab-count-fx tab cnt)
(.mergeOptions Navigation
(name (get tab-root-ids (get tab-key-idx tab)))
(clj->js {:bottomTab (cond
(or (pos? cnt) (pos? (:other cnt)))
(if (and (= :chat tab) platform/ios?)
{:dotIndicator {:visible true}}
{:badge (str (or (:other cnt) cnt)) :dotIndicator {:visible false}})
(pos? (:public cnt))
(if platform/ios?
{:dotIndicator {:visible true}}
{:badge nil :dotIndicator {:visible true}})
:else
(if (and (= :chat tab) platform/ios?)
{:dotIndicator {:visible false}}
{:dotIndicator {:visible false} :badge ""}))}))))
(re-frame/reg-fx
:pop-to-root-tab-fx
(fn [comp]
(log/debug :pop-to-root-tab-fx comp)
(dismiss-all-modals)
(.popToRoot Navigation (name comp))))
(defonce register-bottom-tab-reg
(.registerBottomTabSelectedListener
(.events Navigation)
(fn [^js 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 (= @state/root-comp-id comp)
(when (= :chat tab-key)
(re-frame/dispatch [:close-chat]))
(when platform/android?
(.popToRoot Navigation (name comp))))
(reset! state/root-comp-id comp)))))
;; OVERLAY (Popover and bottom sheets)
(defn dissmiss-overlay [comp]
(.catch (.dismissOverlay Navigation comp) #()))
(defn show-overlay [comp]
(dissmiss-overlay comp)
(.showOverlay Navigation
(clj->js
{:component {:name comp
:id comp
:options (merge (cond-> (roots/status-bar-options)
(and platform/android? (not (quo.colors/dark?)))
(assoc-in [:statusBar :backgroundColor] "#99999A"))
{:layout {:componentBackgroundColor (if platform/android?
(:backdrop @quo.colors/theme)
"transparent")}
:overlay {:interceptTouchOutside true}})}})))
;; POPOVER
(defonce popover-reg
(.registerComponent Navigation
"popover"
(fn [] (gestureHandlerRootHOC views/popover-comp))
(fn [] views/popover-comp)))
(re-frame/reg-fx :show-popover (fn [] (show-overlay "popover")))
(re-frame/reg-fx :hide-popover (fn [] (dissmiss-overlay "popover")))
;; VISIBILITY STATUS POPOVER
(defonce visibility-status-popover-reg
(.registerComponent Navigation
"visibility-status-popover"
(fn [] (gestureHandlerRootHOC views/visibility-status-popover-comp))
(fn [] views/visibility-status-popover-comp)))
(re-frame/reg-fx :show-visibility-status-popover
(fn [] (show-overlay "visibility-status-popover")))
(re-frame/reg-fx :hide-visibility-status-popover
(fn [] (dissmiss-overlay "visibility-status-popover")))
;; BOTTOM SHEETS
(defonce bottom-sheet-reg
(.registerComponent Navigation
"bottom-sheet"
(fn [] (gestureHandlerRootHOC views/sheet-comp))
(fn [] views/sheet-comp)))
(re-frame/reg-fx :show-bottom-sheet (fn [] (show-overlay "bottom-sheet")))
(re-frame/reg-fx :hide-bottom-sheet (fn [] (dissmiss-overlay "bottom-sheet")))
;; WALLET CONNECT
(defonce wallet-connect-sheet-reg
(.registerComponent Navigation
"wallet-connect-sheet"
(fn [] (gestureHandlerRootHOC views/wallet-connect-comp))
(fn [] views/wallet-connect-comp)))
(defonce wallet-connect-success-sheet-reg
(.registerComponent Navigation
"wallet-connect-success-sheet"
(fn [] (gestureHandlerRootHOC views/wallet-connect-success-comp))
(fn [] views/wallet-connect-success-comp)))
(defonce wallet-connect-app-management-sheet-reg
(.registerComponent Navigation
"wallet-connect-app-management-sheet"
(fn [] (gestureHandlerRootHOC views/wallet-connect-app-management-comp))
(fn [] views/wallet-connect-app-management-comp)))
(re-frame/reg-fx :show-wallet-connect-sheet (fn [] (show-overlay "wallet-connect-sheet")))
(re-frame/reg-fx :hide-wallet-connect-sheet (fn [] (dissmiss-overlay "wallet-connect-sheet")))
(re-frame/reg-fx :show-wallet-connect-success-sheet (fn [] (show-overlay "wallet-connect-success-sheet")))
(re-frame/reg-fx :hide-wallet-connect-success-sheet (fn [] (dissmiss-overlay "wallet-connect-success-sheet")))
(re-frame/reg-fx :show-wallet-connect-app-management-sheet (fn [] (show-overlay "wallet-connect-app-management-sheet")))
(re-frame/reg-fx :hide-wallet-connect-app-management-sheet (fn [] (dissmiss-overlay "wallet-connect-app-management-sheet")))
;; SIGNING
(defonce signing-sheet-reg
(.registerComponent Navigation
"signing-sheet"
(fn [] (gestureHandlerRootHOC views/signing-comp))
(fn [] views/signing-comp)))
(re-frame/reg-fx :show-signing-sheet (fn [] (show-overlay "signing-sheet")))
(re-frame/reg-fx :hide-signing-sheet (fn [] (dissmiss-overlay "signing-sheet")))
;; Select account
;; TODO why is this not a regular bottom sheet ?
(defonce select-acc-sheet-reg
(.registerComponent Navigation
"select-acc-sheet"
(fn [] (gestureHandlerRootHOC views/select-acc-comp))
(fn [] views/select-acc-comp)))
(re-frame/reg-fx :show-select-acc-sheet (fn [] (show-overlay "select-acc-sheet")))
(re-frame/reg-fx :hide-select-acc-sheet (fn [] (dissmiss-overlay "select-acc-sheet")))
;; NAVIGATION
(re-frame/reg-fx
:navigate-to-fx
(fn [key]
(log/debug :navigate-to-fx key)
(navigate key)))
(re-frame/reg-fx
:navigate-back-fx
(fn []
(log/debug :navigate-back-fx)
(if @state/curr-modal
(dissmissModal)
(.pop Navigation (name @state/root-comp-id)))))
(re-frame/reg-fx
:navigate-replace-fx
(fn [view-id]
(log/debug :navigate-replace-fx view-id)
(.pop Navigation (name @state/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
:community-edit
:community-reorder-categories))
;; 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))
:dispatch-n (enc/conj-when []
(and (= view-id :chat) [:chat.ui/sync-all-deleted-for-me-messages]))}))
+19 -20
View File
@@ -43,7 +43,7 @@
"returns discovery v5 topic derived from genesis of the provided network"
[network]
(let [les-discovery-identifier "LES2@"
hash-prefix (get-network-genesis-hash-prefix network)]
hash-prefix (get-network-genesis-hash-prefix network)]
(when hash-prefix
(str les-discovery-identifier hash-prefix))))
@@ -92,13 +92,13 @@
(defn- get-multiaccount-node-config
[{:keys [multiaccount :networks/networks :networks/current-network]
:as db}]
(let [wakuv2-config (get multiaccount :wakuv2-config {})
current-fleet-key (current-fleet-key db)
current-fleet (get-current-fleet db)
wakuv2-enabled (boolean (:waku current-fleet))
wakuv2-nodes (into (vals (:waku current-fleet)) (vals (get wakuv2-config :CustomNodes)))
rendezvous-nodes (pick-nodes 3 (vals (:rendezvous current-fleet)))
:as db}]
(let [wakuv2-config (get multiaccount :wakuv2-config {})
current-fleet-key (current-fleet-key db)
current-fleet (get-current-fleet db)
wakuv2-enabled (boolean (:waku current-fleet))
waku-nodes (:waku-nodes current-fleet)
rendezvous-nodes (pick-nodes 3 (vals (:rendezvous current-fleet)))
{:keys [installation-id log-level
waku-bloom-filter-mode
custom-bootnodes custom-bootnodes-enabled?]} multiaccount
@@ -111,10 +111,10 @@
(get-login-node-config)
current-fleet
(assoc :NoDiscovery wakuv2-enabled
:Rendezvous (if wakuv2-enabled false (boolean (seq rendezvous-nodes)))
:ClusterConfig {:Enabled true
:Fleet (name current-fleet-key)
(assoc :NoDiscovery wakuv2-enabled
:Rendezvous (if wakuv2-enabled false (boolean (seq rendezvous-nodes)))
:ClusterConfig {:Enabled true
:Fleet (name current-fleet-key)
:BootNodes
(if wakuv2-enabled [] (pick-nodes 4 (vals (:boot current-fleet))))
:TrustedMailServers
@@ -124,9 +124,8 @@
(into (pick-nodes 2
(vals (:whisper current-fleet)))
(vals (:static current-fleet))))
:RelayNodes wakuv2-nodes
:StoreNodes wakuv2-nodes
:RendezvousNodes (if wakuv2-enabled [] rendezvous-nodes)})
:RendezvousNodes (if wakuv2-enabled [] rendezvous-nodes)
:WakuNodes (or waku-nodes [])})
:always
(assoc :LocalNotificationsConfig {:Enabled true}
@@ -135,10 +134,10 @@
:MailserversConfig {:Enabled true}
:EnableNTPSync true
:WakuConfig
{:Enabled true
{:Enabled true
:BloomFilterMode waku-bloom-filter-mode
:LightClient true
:MinimumPoW 0.000001}
:LightClient true
:MinimumPoW 0.000001}
:WakuV2Config (assoc wakuv2-config :Enabled wakuv2-enabled :Host "0.0.0.0")
:ShhextConfig
{:BackupDisabledDataDir (utils.platform/no-backup-directory)
@@ -174,8 +173,8 @@
app-db"
{:events [::save-new-config]}
[{:keys [db]} config {:keys [on-success]}]
{::json-rpc/call [{:method "settings_saveSetting"
:params [:node-config config]
{::json-rpc/call [{:method "settings_saveSetting"
:params [:node-config config]
:on-success on-success}]})
(fx/defn prepare-new-config
-54
View File
@@ -1,54 +0,0 @@
(ns status-im.switcher.shell
(:require [quo.react-native :as rn]
[status-im.i18n.i18n :as i18n]
[quo2.foundations.colors :as colors]
[quo2.components.markdown.text :as text]
[quo.components.safe-area :as safe-area]
[quo2.components.navigation.top-nav :as top-nav]))
(defn placeholder []
[rn/view {:style {:position :absolute
:top 0
:left 0
:right 0
:bottom -1
:justify-content :center
:align-items :center
:accessibility-label :shell-placeholder-view}}
[rn/view {:style {:margin-top 12
:width 80
:height 80
:border-radius 16
:background-color colors/neutral-90}}]
[text/text {:size :heading-2
:weight :semi-bold
:style {:margin-top 20
:color colors/white}}
(i18n/label :t/shell-placeholder-title)]
[text/text {:size :paragraph-1
:weight :regular
:align :center
:style {:margin-top 8
:color colors/white}}
(i18n/label :t/shell-placeholder-subtitle)]])
(defn shell []
[safe-area/consumer
(fn [insets]
[rn/view {:style {:top 0
:left 0
:right 0
:bottom -1
:position :absolute
:background-color colors/neutral-100}}
[top-nav/top-nav {:type :shell
:style {:margin-top (:top insets)}}]
[placeholder]
[rn/scroll-view {:style {:padding-horizontal 20
:flex-direction :row}}
[text/text {:size :heading-1
:weight :semi-bold
:style {:color colors/white
:margin-top 12}}
(i18n/label :t/jump-to)]]])])
-24
View File
@@ -1,24 +0,0 @@
(ns status-im.switcher.shell-stack
(:require [status-im.i18n.i18n :as i18n]
[status-im.switcher.shell :as shell]
[status-im.switcher.constants :as constants]
[status-im.switcher.animation :as animation]
[status-im.switcher.home-stack :as home-stack]
[status-im.switcher.bottom-tabs :as bottom-tabs]
[quo2.components.navigation.floating-shell-button :as floating-shell-button]))
(defn shell-stack []
[:f>
(fn []
(let [shared-values (animation/get-shared-values)]
[:<>
[shell/shell]
[bottom-tabs/bottom-tabs shared-values]
[home-stack/home-stack shared-values]
[floating-shell-button/floating-shell-button
{:jump-to {:on-press #(animation/close-home-stack shared-values)
:label (i18n/label :t/jump-to)}}
{:position :absolute
:bottom (+ (constants/bottom-tabs-container-height) 7)} ;; bottom offset is 12 = 7 + 5(padding on button)
(:home-stack-opacity shared-values)
(:home-stack-pointer shared-values)]]))])
+1 -1
View File
@@ -5,7 +5,7 @@
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.chat.models :as models.chat]
[status-im.chat.models.reactions :as models.reactions]
[status-im.utils.config :as config]
[status-im2.setup.config :as config]
[status-im.contact.core :as models.contact]
[status-im.communities.core :as models.communities]
[status-im.pairing.core :as models.pairing]
+1 -29
View File
@@ -2,22 +2,7 @@
(:require [quo.design-system.colors :as colors]
[quo.core :as quo]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.icons :as icons]
[quo2.components.buttons.button :as quo2.button]))
(def action-button-container
{:align-items :center
:justify-content :center
:height 32
:border-radius 16
:overflow :hidden})
(defn action-button []
{:width 32
:height 32
:border-radius 18
:align-items :center
:justify-content :center})
[status-im.ui.components.icons.icons :as icons]))
(def action-button-container-old
{:position :absolute
@@ -44,19 +29,6 @@
"rgba(0, 12, 63, 0.2)")
:elevation 2})
(defn plus-button [{:keys [on-press loading accessibility-label]}]
[react/view action-button-container
[quo2.button/button {:type :primary
:size 32
:width 32
:accessibility-label (or accessibility-label :plus-button)
:on-press on-press}
[react/view (action-button)
(if loading
[react/activity-indicator {:color colors/white-persist
:animating true}]
[icons/icon :main-icons/add {:color colors/white-persist}])]]])
(defn plus-button-old [{:keys [on-press loading accessibility-label]}]
[react/view action-button-container-old
[quo/button {:type :scale
@@ -0,0 +1,11 @@
(ns status-im.ui.screens.activity-center.notification.contact-request.style
(:require [quo2.foundations.colors :as colors]))
(def context-tag-text
{:color colors/white})
(def user-avatar-tag-text
{:color colors/white})
(def user-avatar-tag
{:background-color colors/white-opa-10})
@@ -0,0 +1,59 @@
(ns status-im.ui.screens.activity-center.notification.contact-request.view
(:require [quo.components.animated.pressable :as animation]
[quo2.core :as quo2]
[status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.activity-center.notification.contact-request.style :as style]
[status-im.ui.screens.activity-center.utils :as activity-center.utils]
[status-im.utils.datetime :as datetime]
[utils.re-frame :as rf]))
(defn view
[{:keys [id author message last-message] :as notification}]
(let [message (or message last-message)
contact (rf/sub [:contacts/contact-by-identity author])
pressable (case (:contact-request-state message)
constants/contact-request-message-state-accepted
;; NOTE(2022-09-21): We need to dispatch to
;; `:contact.ui/send-message-pressed` instead of
;; `:chat.ui/navigate-to-chat`, otherwise the chat screen
;; looks completely broken if it has never been opened
;; before for the accepted contact.
[animation/pressable {:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:contact.ui/send-message-pressed {:public-key author}]))}]
[:<>])]
(conj pressable
[quo2/activity-log
(merge {:title (i18n/label :t/contact-request)
:icon :main-icons2/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:context [[quo2/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style style/user-avatar-tag
:text-style style/user-avatar-tag-text}
(activity-center.utils/contact-name contact)
(multiaccounts/displayed-photo contact)]
(i18n/label :t/contact-request-sent)]
:message {:body (get-in message [:content :text])}
:status (case (:contact-request-state message)
constants/contact-request-message-state-accepted
{:type :positive :label (i18n/label :t/accepted)}
constants/contact-request-message-state-declined
{:type :negative :label (i18n/label :t/declined)}
nil)}
(case (:contact-request-state message)
constants/contact-request-state-mutual
{:button-1 {:label (i18n/label :t/decline)
:accessibility-label :decline-contact-request
:type :danger
:on-press #(rf/dispatch [:contact-requests.ui/decline-request id])}
:button-2 {:label (i18n/label :t/accept)
:accessibility-label :accept-contact-request
:type :positive
:on-press #(rf/dispatch [:contact-requests.ui/accept-request id])}}
nil))])))
@@ -0,0 +1,11 @@
(ns status-im.ui.screens.activity-center.notification.contact-verification.style
(:require [quo2.foundations.colors :as colors]))
(def context-tag-text
{:color colors/white})
(def user-avatar-tag-text
{:color colors/white})
(def user-avatar-tag
{:background-color colors/white-opa-10})
@@ -0,0 +1,109 @@
(ns status-im.ui.screens.activity-center.notification.contact-verification.view
(:require [clojure.string :as str]
[quo2.core :as quo2]
[status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.activity-center.notification.contact-verification.style :as style]
[status-im.ui.screens.activity-center.utils :as activity-center.utils]
[status-im.utils.datetime :as datetime]
[utils.re-frame :as rf]))
(defn- hide-bottom-sheet-and-dispatch
[event]
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch event))
(defn- context-tags
[challenger? {:keys [author contact-verification-status]}]
(let [contact (rf/sub [:contacts/contact-by-identity author])]
[[quo2/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style style/user-avatar-tag
:text-style style/user-avatar-tag-text}
(activity-center.utils/contact-name contact)
(multiaccounts/displayed-photo contact)]
(if challenger?
(when (or (= contact-verification-status constants/contact-verification-status-accepted)
(= contact-verification-status constants/contact-verification-status-trusted)
(= contact-verification-status constants/contact-verification-status-untrustworthy))
(str (str/lower-case (i18n/label :t/replied)) ":"))
(when (or (= contact-verification-status constants/contact-verification-status-accepted)
(= contact-verification-status constants/contact-verification-status-pending)
(= contact-verification-status constants/contact-verification-status-declined))
(str (i18n/label :t/identity-verification-request-sent) ":")))]))
(defn- activity-message
[challenger? {:keys [contact-verification-status message reply-message]}]
(if challenger?
(when (or (= contact-verification-status constants/contact-verification-status-accepted)
(= contact-verification-status constants/contact-verification-status-trusted)
(= contact-verification-status constants/contact-verification-status-untrustworthy))
{:title (get-in message [:content :text])
:body (get-in reply-message [:content :text])})
(when (or (= contact-verification-status constants/contact-verification-status-accepted)
(= contact-verification-status constants/contact-verification-status-pending)
(= contact-verification-status constants/contact-verification-status-declined))
{:body (get-in message [:content :text])})))
(defn- activity-status
[challenger? contact-verification-status]
(if challenger?
(cond (= contact-verification-status constants/contact-verification-status-trusted)
{:type :positive :label (i18n/label :t/status-confirmed)}
(= contact-verification-status constants/contact-verification-status-untrustworthy)
{:type :negative :label (i18n/label :t/untrustworthy)})
(cond (= contact-verification-status constants/contact-verification-status-accepted)
{:type :positive :label (i18n/label :t/replied)}
(= contact-verification-status constants/contact-verification-status-declined)
{:type :negative :label (i18n/label :t/declined)})))
(defn view
[_ _]
(let [reply (atom "")]
(fn [{:keys [id message contact-verification-status] :as notification} {:keys [replying?]}]
(let [challenger? (:outgoing message)]
;; TODO(@ilmotta): Declined challenges should only be displayed for the
;; challengee, not the challenger.
;; https://github.com/status-im/status-mobile/issues/14354
(when-not (and challenger? (= contact-verification-status constants/contact-verification-status-declined))
[quo2/activity-log
(merge {:title (i18n/label :t/identity-verification-request)
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:on-update-reply #(reset! reply %)
:replying? replying?
:context (context-tags challenger? notification)
:message (activity-message challenger? notification)
:status (activity-status challenger? contact-verification-status)}
(if challenger?
(when (= contact-verification-status constants/contact-verification-status-accepted)
{:button-1 {:label (i18n/label :t/untrustworthy)
:accessibility-label :mark-contact-verification-as-untrustworthy
:type :danger
:on-press #(rf/dispatch [:activity-center.contact-verification/mark-as-untrustworthy id])}
:button-2 {:label (i18n/label :t/accept)
:accessibility-label :mark-contact-verification-as-trusted
:type :positive
:on-press #(rf/dispatch [:activity-center.contact-verification/mark-as-trusted id])}})
(when (= contact-verification-status constants/contact-verification-status-pending)
{:button-1 {:label (i18n/label :t/decline)
:accessibility-label :decline-contact-verification
:type :danger
:on-press #(hide-bottom-sheet-and-dispatch [:activity-center.contact-verification/decline id])}
:button-2 (if replying?
{:label (i18n/label :t/send-reply)
:accessibility-label :reply-to-contact-verification
:type :primary
:on-press #(hide-bottom-sheet-and-dispatch [:activity-center.contact-verification/reply id @reply])}
{:label (i18n/label :t/message-reply)
:accessibility-label :send-reply-to-contact-verification
:type :primary
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
:activity-center.contact-verification/reply
{:notification notification
:replying? true}])})})))])))))
@@ -0,0 +1,9 @@
(ns status-im.ui.screens.activity-center.sheet.contact-verification
(:require [status-im.ui.screens.activity-center.notification.contact-verification.view :as contact-verification]))
(defn- reply-view
[{:keys [notification replying?]}]
[contact-verification/view notification {:replying? replying?}])
(def reply
{:content reply-view})
@@ -0,0 +1,28 @@
(ns status-im.ui.screens.activity-center.style
(:require [quo2.foundations.colors :as colors]))
(def screen-padding 20)
(def header-button
{:margin-bottom 12
:margin-left screen-padding})
(def header-heading
{:padding-horizontal screen-padding
:padding-vertical 12
:color colors/white})
(defn screen-container
[window-width top bottom]
{:flex 1
:width window-width
:padding-top (if (pos? top) (+ top 12) 12)
:padding-bottom bottom})
(defn notification-container
[index]
{:margin-top (if (zero? index) 0 4)
:padding-horizontal 8})
(def tabs
{:padding-left screen-padding})
@@ -0,0 +1,6 @@
(ns status-im.ui.screens.activity-center.utils)
(defn contact-name
[contact]
(or (get-in contact [:names :nickname])
(get-in contact [:names :three-words-name])))
@@ -1,154 +1,32 @@
(ns status-im.ui.screens.activity-center.views
(:require [quo.components.animated.pressable :as animation]
(:require [quo.components.safe-area :as safe-area]
[quo.react :as react]
[quo.react-native :as rn]
[quo2.components.buttons.button :as button]
[quo2.components.markdown.text :as text]
[quo2.components.notifications.activity-logs :as activity-logs]
[quo2.components.tabs.tabs :as tabs]
[quo2.components.tags.context-tags :as context-tags]
[quo2.core :as quo2]
[quo2.foundations.colors :as colors]
[status-im.constants :as constants]
[status-im.activity-center.notification-types :as types]
[status-im.i18n.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.datetime :as datetime]
[goog.string :as gstring]
[status-im.utils.handlers :refer [<sub >evt]]
[quo.components.safe-area :as safe-area]))
;;;; Misc
(defn sender-name
[contact]
(or (get-in contact [:names :nickname])
(get-in contact [:names :three-words-name])))
(defmulti notification-component :type)
;; TODO(rasom): should be removed as soon as all notifications types covered
(defmethod notification-component :default
[{:keys [type]}]
[rn/view {:style {:width 300, :height 100}}
[rn/text
(gstring/format
"I exist just to avoid crashing for no reason. I'm sorry. Type %d" type)]])
;;;; Contact request notifications
(defmethod notification-component types/contact-request
[{:keys [id] :as notification}]
(let [message (or (:message notification) (:last-message notification))
contact (<sub [:contacts/contact-by-identity (:author notification)])
pressable (case (:contact-request-state message)
constants/contact-request-message-state-accepted
;; NOTE [2022-09-21]: We need to dispatch to
;; `:contact.ui/send-message-pressed` instead of
;; `:chat.ui/navigate-to-chat`, otherwise the chat screen looks completely
;; broken if it has never been opened before for the accepted contact.
[animation/pressable {:on-press (fn []
(>evt [:hide-popover])
(>evt [:contact.ui/send-message-pressed {:public-key (:author notification)}]))}]
[:<>])]
(conj pressable
[activity-logs/activity-log
(merge {:title (i18n/label :t/contact-request)
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:context [[context-tags/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style {:background-color colors/white-opa-10}
:text-style {:color colors/white}}
(sender-name contact)
(multiaccounts/displayed-photo contact)]
[rn/text {:style {:color colors/white}}
(i18n/label :t/contact-request-sent)]]
:message {:body (get-in message [:content :text])}
:status (case (:contact-request-state message)
constants/contact-request-message-state-accepted
{:type :positive :label (i18n/label :t/accepted)}
constants/contact-request-message-state-declined
{:type :negative :label (i18n/label :t/declined)}
nil)}
(case (:contact-request-state message)
constants/contact-request-state-mutual
{:button-1 {:label (i18n/label :t/decline)
:type :danger
:on-press #(>evt [:contact-requests.ui/decline-request id])}
:button-2 {:label (i18n/label :t/message-reply)
:type :success
:override-background-color colors/success-60
:on-press #(>evt [:contact-requests.ui/accept-request id])}}
nil))])))
;;;; Contact verification notifications
(defmethod notification-component types/contact-verification
[{:keys [id contact-verification-status] :as notification}]
(let [message (or (:message notification) (:last-notification notification))
contact (<sub [:contacts/contact-by-identity (:author notification)])]
[activity-logs/activity-log
(merge {:title (i18n/label :t/identity-verification-request)
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:context [[context-tags/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style {:background-color colors/white-opa-10}
:text-style {:color colors/white}}
(sender-name contact)
(multiaccounts/displayed-photo contact)]
[rn/text {:style {:color colors/white}}
(str (i18n/label :t/identity-verification-request-sent)
":")]]
:message (case contact-verification-status
(constants/contact-verification-state-pending
constants/contact-verification-state-declined)
{:body (get-in message [:content :text])}
nil)
:status (case contact-verification-status
constants/contact-verification-state-declined
{:type :negative :label (i18n/label :t/declined)}
nil)}
(case contact-verification-status
constants/contact-verification-state-pending
{:button-1 {:label (i18n/label :t/decline)
:type :danger
:on-press #(>evt [:activity-center.contact-verification/decline id])}
:button-2 {:label (i18n/label :t/accept)
:type :primary
;; TODO: The acceptance flow will be implemented in follow-up PRs.
:on-press identity}}
nil))]))
;;;; Type-independent components
(defn render-notification
[notification index]
[rn/view {:margin-top (if (= 0 index) 0 4)
:padding-horizontal 20}
[notification-component notification]])
[status-im.ui.screens.activity-center.notification.contact-request.view :as contact-request]
[status-im.ui.screens.activity-center.notification.contact-verification.view :as contact-verification]
[status-im.ui.screens.activity-center.style :as style]
[utils.re-frame :as rf]))
(defn filter-selector-read-toggle
[]
(let [unread-filter-enabled? (<sub [:activity-center/filter-status-unread-enabled?])]
;; TODO: Replace the button by a Filter Selector component once available for use.
[button/button {:icon true
:type (if unread-filter-enabled? :primary :blur-bg-outline)
:size 32
:override-theme :dark
:on-press #(>evt [:activity-center.notifications/fetch-first-page
{:filter-status (if unread-filter-enabled?
:all
:unread)}])}
(let [unread-filter-enabled? (rf/sub [:activity-center/filter-status-unread-enabled?])]
;; TODO(@ilmotta): Replace the button by a Filter Selector.
;; https://github.com/status-im/status-mobile/issues/14355
[quo2/button {:icon true
:type (if unread-filter-enabled? :primary :blur-bg-outline)
:size 32
:override-theme :dark
:on-press #(rf/dispatch [:activity-center.notifications/fetch-first-page
{:filter-status (if unread-filter-enabled?
:all
:unread)}])}
:i/unread]))
;; TODO(2022-10-07): The empty state is still under design analysis, so we
;; TODO(@ilmotta,2022-10-07): The empty state is still under design analysis, so we
;; shouldn't even care about translations at this point. A placeholder box is
;; used instead of an image.
(defn empty-tab
@@ -161,24 +39,24 @@
:height 120
:margin-bottom 20
:width 120}}]
[text/text {:size :paragraph-1
[quo2/text {:size :paragraph-1
:style {:padding-bottom 2}
:weight :semi-bold}
"No notifications"]
[text/text {:size :paragraph-2}
[quo2/text {:size :paragraph-2}
"Your notifications will be here"]])
(defn tabs
[]
(let [filter-type (<sub [:activity-center/filter-type])]
[tabs/scrollable-tabs {:size 32
(let [filter-type (rf/sub [:activity-center/filter-type])]
[quo2/scrollable-tabs {:size 32
:blur? true
:override-theme :dark
:style {:padding-left 20}
:style style/tabs
:fade-end-percentage 0.79
:scroll-on-press? true
:fade-end? true
:on-change #(>evt [:activity-center.notifications/fetch-first-page {:filter-type %}])
:on-change #(rf/dispatch [:activity-center.notifications/fetch-first-page {:filter-type %}])
:default-active filter-type
:data [{:id types/no-type
:label (i18n/label :t/all)}
@@ -203,19 +81,16 @@
[]
(let [screen-padding 20]
[rn/view
[button/button {:icon true
:type :blur-bg
:size 32
:override-theme :dark
:style {:margin-bottom 12
:margin-left screen-padding}
:on-press #(>evt [:hide-popover])}
[quo2/button {:icon true
:type :blur-bg
:size 32
:override-theme :dark
:style style/header-button
:on-press #(rf/dispatch [:hide-popover])}
:i/close]
[text/text {:size :heading-1
[quo2/text {:size :heading-1
:weight :semi-bold
:style {:padding-horizontal screen-padding
:padding-vertical 12
:color colors/white}}
:style style/header-heading}
(i18n/label :t/notifications)]
[rn/view {:flex-direction :row
:padding-vertical 12}
@@ -227,22 +102,30 @@
:padding-right screen-padding}
[filter-selector-read-toggle]]]]))
(defn render-notification
[notification index]
[rn/view {:style (style/notification-container index)}
(case (:type notification)
types/contact-verification
[contact-verification/view notification {}]
types/contact-request
[contact-request/view notification]
nil)])
(defn activity-center
[]
[:f>
(fn []
(let [notifications (<sub [:activity-center/filtered-notifications])
window-width (<sub [:dimensions/window-width])
{:keys [top bottom]} (safe-area/use-safe-area)]
(react/effect! #(>evt [:activity-center.notifications/fetch-first-page]))
[rn/view {:style {:flex 1
:width window-width
:padding-top (if (pos? top) (+ top 12) 12)
:padding-bottom bottom}}
(let [notifications (rf/sub [:activity-center/filtered-notifications])
window-width (rf/sub [:dimensions/window-width])
{:keys [top bottom]} (safe-area/use-safe-area)]
(react/effect! #(rf/dispatch [:activity-center.notifications/fetch-first-page]))
[rn/view {:style (style/screen-container window-width top bottom)}
[header]
[rn/flat-list {:content-container-style {:flex-grow 1}
:data notifications
:empty-component [empty-tab]
:key-fn :id
:on-end-reached #(>evt [:activity-center.notifications/fetch-next-page])
:render-fn render-notification}]]))])
[rn/flat-list {:data notifications
:empty-component [empty-tab]
:key-fn :id
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
:render-fn render-notification}]]))])
@@ -1,12 +1,13 @@
(ns status-im.ui.screens.bottom-sheets.views
(:require [status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
(:require [quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.activity-center.sheet.contact-verification :as contact-verification.sheet]
[status-im.ui.screens.home.sheet.views :as home.sheet]
[status-im.ui.screens.keycard.views :as keycard]
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[quo.core :as quo]))
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]))
(defn bottom-sheet []
(let [{:keys [show? view options]} @(re-frame/subscribe [:bottom-sheet])
@@ -27,6 +28,9 @@
(= view :add-new)
(merge home.sheet/add-new)
(= view :activity-center.contact-verification/reply)
(merge contact-verification.sheet/reply)
(= view :keycard.login/more)
(merge keycard/more-sheet)
@@ -40,4 +44,4 @@
(merge key-storage/migrate-account-password))]
[quo/bottom-sheet opts
(when content
[content (when options options)])]))
[content (when options options)])]))
@@ -0,0 +1,77 @@
(ns status-im.ui.screens.chat.components.messages-skeleton
(:require [status-im.ui.components.react :as react]
[react-native.core :as rn]
[reagent.core :as reagent]
[react-native.reanimated :as reanimated]
[quo2.foundations.colors :as colors]))
(def message-skeleton-height 54)
(def avatar-skeleton-size 32)
(def message-content-width [{:author 80
:message 249}
{:author 124
:message 156}
{:author 96
:message 212}
{:author 112
:message 144}])
;; Standlone message skeleton
(defn message-skeleton []
[:f>
(fn []
(let [color (colors/theme-colors colors/neutral-5 colors/neutral-70)
loading-color (colors/theme-colors colors/neutral-10 colors/neutral-60)
content-width (rand-nth message-content-width)
author-width (content-width :author)
message-width (content-width :message)
{window-width :width} (rn/use-window-dimensions)
translate-x (reanimated/use-shared-value (- window-width))
animated-gradient-style (reanimated/apply-animations-to-style
{:transform [{:translateX translate-x}]}
{:width window-width
:height "100%"})]
(reanimated/animate-shared-value-with-repeat translate-x window-width 1000 :linear (- 1) false)
[react/masked-view
{:style {:height message-skeleton-height}
:maskElement (reagent/as-element
[rn/view {:style {:height message-skeleton-height
:flex-direction :row
:padding-vertical 11
:background-color :transparent
:padding-left 21}}
[rn/view {:style {:height avatar-skeleton-size
:width avatar-skeleton-size
:border-radius (/ avatar-skeleton-size 2)
:background-color color
:overflow :hidden}}]
[rn/view {:style {:padding-left 8
:background-color :transparent}}
[rn/view {:style {:height 8
:width author-width
:border-radius 6
:background-color color
:margin-bottom 8
:overflow :hidden}}]
[rn/view {:style {:height 16
:width message-width
:border-radius 6
:overflow :hidden
:background-color color}}]]])}
[rn/view {:style {:flex 1
:background-color color}}
[reanimated/linear-gradient {:colors [color color loading-color color color]
:start {:x 0 :y 0}
:end {:x 1 :y 0}
:style animated-gradient-style}]]]))])
(defn messages-skeleton [parent-height]
(let [number-of-skeletons (int (Math/floor (/ parent-height message-skeleton-height)))]
[rn/view {:style {:background-color (colors/theme-colors
colors/white
colors/neutral-90)
:flex 1}}
(for [n (range number-of-skeletons)]
[message-skeleton {:key n}])]))
@@ -4,6 +4,7 @@
[re-frame.core :as re-frame]
[status-im.i18n.i18n :as i18n]
[status-im.utils.datetime :as datetime]
[status-im.ui.screens.chat.components.messages-skeleton :as messages-skeleton]
[status-im.ui.screens.chat.styles.input.gap :as style]))
(defn on-press
@@ -18,16 +19,17 @@
chat-id]
connected? [:mailserver/connected?]
use-status-nodes? [:mailserver/use-status-nodes?]
first-gap? (= gap-ids #{:first-gap})]
first-gap? (= gap-ids #{:first-gap})
window-height [:dimensions/window-height]]
(when (or (not first-gap?) public? community?)
[react/view {:style (style/gap-container)}
[react/view {:style (when-not in-progress? style/gap-container)}
[react/touchable-highlight
{:on-press (when (and (not in-progress?) use-status-nodes? connected?)
(on-press chat-id gap-ids))
:style style/touchable}
:style {:height (if in-progress? window-height 48)}}
[react/view {:style style/label-container}
(if in-progress?
[react/activity-indicator]
[messages-skeleton/messages-skeleton window-height]
[react/nested-text
{:style (style/gap-text (and connected? use-status-nodes?))}
(i18n/label (if first-gap? :t/load-more-messages :t/fetch-messages))
@@ -1,28 +1,29 @@
(ns status-im.ui.screens.communities.community
(:require [status-im.ui.components.topbar :as topbar]
[quo.react-native :as rn]
(:require [i18n.i18n :as i18n]
[utils.re-frame :as rf]
[react-native.core :as rn]
[quo2.components.community.style :as styles]
;; TODO reimplement with quo2 library and new designs
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.toolbar :as toolbar]
[quo.core :as quo]
[status-im.constants :as constants]
[status-im.chat.models.link-preview :as link-preview]
[status-im.utils.handlers :refer [>evt <sub]]
[status-im.i18n.i18n :as i18n]
[status-im.utils.datetime :as datetime]
[status-im.communities.core :as communities]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as components.react]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.screens.chat.photos :as photos]
[status-im.react-native.resources :as resources]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[quo.design-system.colors :as colors]
[status-im.ui.components.icons.icons :as icons]
[status-im.utils.core :as utils]
[status-im.ui.components.plus-button :as components.plus-button]
[re-frame.core :as re-frame]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.components.accordion :as accordion]
[quo2.components.community.style :as styles]))
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[quo.core :as quo]
[quo.design-system.colors :as colors]))
(def request-cooldown-ms (* 24 60 60 1000))
@@ -61,8 +62,8 @@
(i18n/label :t/open-membership))]]]))
(defn hide-sheet-and-dispatch [event]
(>evt [:bottom-sheet/hide])
(>evt event))
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(defn community-plus-actions [{:keys [id permissions can-manage-users?]}]
(let [can-invite? (and can-manage-users? (not= (:access permissions) constants/community-no-membership-access))
@@ -87,14 +88,14 @@
:title (i18n/label :t/invite-people)
:icon :main-icons/share
:accessibility-label :community-invite-people
:on-press #(>evt [::communities/invite-people-pressed id])}])
:on-press #(rf/dispatch [:communities/invite-people-pressed id])}])
(when (and can-share? (not can-invite?))
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-people)
:icon :main-icons/share
:accessibility-label :community-share
:on-press #(>evt [::communities/share-community-pressed id])}])]))
:on-press #(rf/dispatch [:communities/share-community-pressed id])}])]))
(defn community-actions [{:keys [id name images color can-manage-users?]}]
(let [thumbnail-image (get-in images [:thumbnail :uri])]
@@ -153,13 +154,13 @@
;; unread indicator
(assoc home-item :public? true)
{:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil])
(re-frame/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[sheets/actions home-item])}])}])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:chat.ui/navigate-to-chat chat-id])
(rf/dispatch [:search/home-filter-changed nil])
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[sheets/actions home-item])}])}])
(defn categories-accordion [community-id chats categories data]
[:<>
@@ -167,8 +168,8 @@
^{: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])
{:on-open #(rf/dispatch [::communities/store-category-state community-id id true])
:on-close #(rf/dispatch [::communities/store-category-state community-id id false])
:default state
:title [rn/view styles/category-item
[icons/icon :main-icons/channel-category {:color colors/gray}]
@@ -180,7 +181,7 @@
[quo/separator]])])
(defn community-chat-list [community-id categories from-chat]
(let [chats (<sub [:chats/sorted-categories-by-community-id community-id])]
(let [chats (rf/sub [:chats/sorted-categories-by-community-id community-id])]
(if (and (empty? categories) (empty? chats))
[blank-page (i18n/label :t/welcome-community-blank-message)]
[list/flat-list
@@ -230,25 +231,25 @@
:render-fn channel-preview-item}]))
(defn unknown-community [community-id]
(let [fetching (<sub [:communities/fetching-community community-id])]
(let [fetching (rf/sub [:communities/fetching-community community-id])]
[:<> {:style {:flex 1}}
[topbar/topbar {:title (if fetching (i18n/label :t/fetching-community) (i18n/label :t/not-found))}]
[rn/view {:style {:padding 16 :flex 1 :flex-direction :row :align-items :center :justify-content :center}}
[quo/button {:on-press (when-not fetching #(>evt [::link-preview/resolve-community-info community-id]))
[quo/button {:on-press (when-not fetching #(rf/dispatch [::link-preview/resolve-community-info community-id]))
:disabled fetching
:color :secondary}
:color :secondary}
(if fetching
[components.react/small-loading-indicator]
[react/small-loading-indicator]
(i18n/label :t/fetch-community))]]]))
(defn community []
(let [{:keys [community-id from-chat]} (<sub [:get-screen-params])]
(let [{:keys [community-id from-chat]} (rf/sub [:get-screen-params])]
(fn []
(let [{:keys [id chats name images members permissions color joined
can-request-access? can-join? requested-to-join-at admin]
:as community} (<sub [:communities/community community-id])
categories (<sub [:communities/sorted-categories community-id])]
:as community} (rf/sub [:communities/community community-id])
categories (rf/sub [:communities/sorted-categories community-id])]
(if community
[rn/view {:style {:flex 1}}
[topbar/topbar
@@ -264,24 +265,24 @@
(when (or admin joined)
[{:icon :main-icons/more
:accessibility-label :community-menu-button
:on-press #(>evt [:bottom-sheet/show-sheet
{:content (fn []
[community-actions community])}])}])}]
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[community-actions community])}])}])}]
(if joined
[community-chat-list id categories false from-chat]
[community-channel-preview-list id chats])
(when admin
[components.plus-button/plus-button-old
{:on-press #(>evt [:bottom-sheet/show-sheet
{:content (fn []
[community-plus-actions community])}])
{:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[community-plus-actions community])}])
:accessibility-label :new-chat-button}])
(when-not joined
(cond
can-join?
[toolbar/toolbar
{:show-border? true
:center [quo/button {:on-press #(>evt [::communities/join id])
:center [quo/button {:on-press #(rf/dispatch [:communities/join id])
:type :secondary}
(i18n/label :t/join)]}]
can-request-access?
@@ -292,13 +293,13 @@
:left [quo/text {:color :secondary} (i18n/label :t/membership-request-pending)]}]
[toolbar/toolbar
{:show-border? true
:center [quo/button {:on-press #(>evt [::communities/request-to-join id])
:center [quo/button {:on-press #(rf/dispatch [::communities/request-to-join id])
:type :secondary}
(i18n/label :t/request-access)]}])
:else
[toolbar/toolbar
{:show-border? true
:center [quo/button {:on-press #(>evt [::communities/join id])
:center [quo/button {:on-press #(rf/dispatch [:communities/join id])
:type :secondary}
(i18n/label :t/follow)]}]))]
[unknown-community community-id])))))
@@ -1,89 +0,0 @@
(ns status-im.ui.screens.communities.community-options-bottom-sheet
(:require [status-im.i18n.i18n :as i18n]
[quo.react-native :as rn] [quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[quo2.components.drawers.action-drawers :as action-drawers]
[quo2.components.tags.context-tags :as context-tags]
[status-im.react-native.resources :as resources]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.communities.core :as communities]))
(def not-joined-options [{:icon :i/members
:label (i18n/label :t/view-members)}
{:icon :i/bullet-list
:right-icon :i/chevron-right
:label (i18n/label :t/view-community-rules)}
{:icon :i/add-user
:label (i18n/label :t/invite-contacts)}
{:icon :i/qr-code
:label (i18n/label :t/show-qr)}
{:icon :i/share
:label (i18n/label :t/share-community)}])
(def joined-options [{:icon :i/members
:label (i18n/label :t/view-members)}
{:icon :i/bullet-list
:right-icon :i/chevron-right
:label (i18n/label :t/view-community-rules)}
{:icon :i/up-to-date
:label (i18n/label :t/mark-as-read)}
{:icon :i/muted
:label (i18n/label :t/mute-community)
:right-icon :i/chevron-right}
{:icon :i/notifications
:label (i18n/label :t/community-notification-settings)
:right-icon :i/chevron-right}
{:icon :i/add-user
:label (i18n/label :t/invite-contacts)}
{:icon :i/qr-code
:label (i18n/label :t/show-qr)}
{:icon :i/share
:label (i18n/label :t/share-community)}])
(defn leave-sheet [community]
[rn/view {:style {:flex 1 :margin-left 20 :margin-right 20 :margin-bottom 20}}
[rn/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :space-between}}
[text/text {:accessibility-label :communities-join-community
:weight :semi-bold
:size :heading-1}
(i18n/label :t/leave-community?)]]
;; TODO get tag image from community data
[context-tags/context-tag
{:style
{:margin-right :auto
:margin-top 8}}
(resources/get-image :status-logo) (:name community)]
[text/text {:accessibility-label :communities-join-community
:size :paragraph-1
:style {:margin-top 16}}
(i18n/label :t/leave-community-message)]
[rn/view {:style {:width "100%"
:margin-top 16 :margin-bottom 16
:flex 1
:flex-direction :row
:align-items :center
:justify-content :space-evenly}}
[button/button {:on-press #(>evt [:bottom-sheet/hide])
:type :grey :style {:flex 1 :margin-right 12}} (i18n/label :t/cancel)]
[button/button
{:on-press (fn []
(>evt [::communities/leave (:id community)])
(>evt [:bottom-sheet/hide]))
:style {:flex 1}} (i18n/label :t/leave-community)]]])
(defn options-menu []
(let [community-mock (<sub [:get-screen-params :community-overview]) ;;TODO stop using mock data and only pass community id
community (<sub [:communities/community (:id community-mock)])]
[action-drawers/action-drawer {:actions (if (:joined community)
joined-options
not-joined-options)
:actions-with-consequence
(when (:joined community)
[{:icon :i/log-out
:label (i18n/label :t/leave-community)
:on-press #(>evt [:bottom-sheet/show-sheet
{:content (constantly [leave-sheet community])
:content-height 300}])}])}]))
@@ -1,171 +0,0 @@
(ns status-im.ui.screens.communities.community-overview-redesign
(:require [status-im.i18n.i18n :as i18n]
[quo.react-native :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[quo2.components.list-items.preview-list :as preview-list]
[quo2.components.list-items.channel :as channel]
[quo2.components.dividers.divider-label :as divider-label]
[quo2.components.community.community-view :as community-view]
[quo2.components.tags.status-tags :as status-tags]
[quo2.components.community.style :as styles]
[quo2.foundations.colors :as colors]
[quo2.components.navigation.page-nav :as page-nav]
[status-im.ui.screens.communities.request-to-join-bottom-sheet-redesign :as request-to-join]
[status-im.ui.screens.communities.community-options-bottom-sheet :as options-menu]
[status-im.ui.components.list.views :as list]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.ui.screens.communities.icon :as communities.icon]))
;; Mocked list items
(def user-list
[{:full-name "Alicia K"}
{:full-name "Marcus C"}
{:full-name "MNO PQR"}
{:full-name "STU VWX"}])
(defn preview-user-list []
[rn/view {:style {:flex-direction :row
:align-items :center
:margin-top 20}}
[preview-list/preview-list {:type :user
:more-than-99-label (i18n/label :counter-99-plus)
:user user-list :list-size 4 :size 24}]
[text/text {:accessibility-label :communities-screen-title
:style {:margin-left 8}
:size :label}
"Join Alicia, Marcus and 2 more"]]) ;; TODO remove mocked data and use from contacts list/communities members
(def list-of-channels {:Welcome [{:name "welcome"
:emoji "🤝"}
{:name "onboarding"
:emoji "🍑"}
{:name "intro"
:emoji "🦄"}]
:General [{:name "general"
:emoji "🐷"}
{:name "people-ops"
:emoji "🌏"}
{:name "announcements"
:emoji "🎺"}]
:Mobile [{:name "mobile"
:emoji "👽"}]})
(defn channel-list-component []
[rn/scroll-view {:style {:margin-top 20}}
[:<> {:style {:flex 1}}
(map (fn [category]
^{:key (get category 0)}
[rn/view {:flex 1}
[divider-label/divider-label
{:label (first category)
:chevron-position :left}]
[rn/view
{:margin-left 8
:margin-top 10
:margin-bottom 8}
[list/flat-list
{:shows-horizontal-scroll-indicator false
:separator [rn/view {:margin-top 4}]
:data ((first category) list-of-channels)
:render-fn channel/list-item}]]])
list-of-channels)]])
(defn icon-color []
(colors/theme-colors
colors/white-opa-40
colors/neutral-80-opa-40))
(defn community-card-page-view [{:keys [name description locked joined
status tokens cover tags community-color] :as community}]
[rn/view
{:style
{:flex 1
:border-radius 20}}
[rn/view (styles/community-cover-container 148)
[rn/image
{:source cover
:style {:position :absolute
:flex 1}}]
[rn/view {:style {:margin-top 26}}
[page-nav/page-nav
{:horizontal-description? true
:one-icon-align-left? true
:align-mid? false
:page-nav-color :transparent
:page-nav-background-uri ""
:mid-section {:type :text-with-description}
:right-section-buttons [{:icon :i/search
:background-color (icon-color)}
{:icon :i/options
:background-color (icon-color)
:on-press #(>evt [:bottom-sheet/show-sheet
{:content (constantly [options-menu/options-menu community])
:content-height 400}])}]
:left-section {:icon :i/close
:icon-background-color (icon-color)
:on-press #(>evt [:navigate-back])}}]]]
[rn/view {:flex 1
:height 20
:border-radius 16
:background-color (colors/theme-colors
colors/white
colors/neutral-90)}
[rn/view {:padding-horizontal 20}
[rn/view {:border-radius 40
:border-width 1
:border-color colors/white
:position :absolute
:top (- (/ 80 2))
:left (/ 70 4)
:padding 2
:background-color (colors/theme-colors
colors/white
colors/neutral-90)}
[communities.icon/community-icon-redesign community 80]]
(when (and (not joined)
(= status :gated))
[rn/view (styles/permission-tag-styles)
[community-view/permission-tag-container
{:locked locked
:status status
:tokens tokens}]])
(when joined
[rn/view {:position :absolute
:top 12
:right 12}
[status-tags/status-tag {:status {:type :positive} :label (i18n/label :joined)}]])
[community-view/community-title
{:title name
:size :large
:description description}]
[rn/view {:margin-top 12}
[community-view/community-stats-column :card-view]]
[rn/view {:margin-top 16}
[community-view/community-tags tags]]
[preview-user-list]
(when (not joined)
[button/button
{:on-press #(>evt [:bottom-sheet/show-sheet
{:content (constantly [request-to-join/request-to-join community])
:content-height 300}])
:override-background-color community-color
:style
{:width "100%"
:margin-top 20
:margin-left :auto
:margin-right :auto}
:before :i/communities}
(i18n/label :join-open-community)])]
[channel-list-component]]])
(defn overview []
(let [community-mock (<sub [:get-screen-params :community-overview]) ;;TODO stop using mock data and only pass community id
community (<sub [:communities/community (:id community-mock)])]
[rn/view {:style
{:height "100%"}}
[community-card-page-view
(merge community-mock {:joined (:joined community)})]]))
@@ -21,6 +21,7 @@
[chat-icon.screen/chat-icon-view-chat-list
id true name color false false])))
;; TODO (flexsurfer) reimplement with new design, its still old design, photos and chat-icon components from old design
(defn community-icon-redesign [{:keys [id name images color]} size]
(let [color (or color (rand-nth colors/chat-colors))
thumbnail-image (get-in images [:thumbnail :uri])]
@@ -73,6 +73,7 @@
:center
[quo/button {:disabled (and (str/blank? @user-pk)
(zero? (count selected)))
:accessibility-label :share-community-link
:type :secondary
:on-press #(>evt-once
[(if can-invite?
@@ -70,7 +70,7 @@
:title (i18n/label :t/invite-people)
:accessibility-label :community-invite-people
:theme :accent
:on-press #(>evt [::communities/invite-people-pressed community-id])}]
:on-press #(>evt [:communities/invite-people-pressed community-id])}]
[quo/separator {:style {:margin-vertical 8}}]])
(defn requests-to-join [community-id]
@@ -31,7 +31,7 @@
:on-press #(>evt [:navigate-back])}]
:right-accessories [{:icon :main-icons/share
:accessibility-label :invite-button
:on-press #(>evt [::communities/share-community-pressed community-id])}]
:on-press #(>evt [:communities/share-community-pressed community-id])}]
:extended-header (profile-header/extended-header
{:title name
:color (or color (rand-nth colors/chat-colors))
@@ -95,7 +95,7 @@
[quo/list-item {:theme :accent
:icon :main-icons/arrow-left
:title (i18n/label :t/leave-community)
:on-press #(>evt [::communities/leave community-id])}]
:on-press #(>evt [:communities/leave community-id])}]
;; Disable as not implemented yet
(when false
[quo/list-item {:theme :negative
@@ -1,132 +0,0 @@
(ns status-im.ui.screens.communities.request-to-join-bottom-sheet-redesign
(:require [status-im.i18n.i18n :as i18n]
[reagent.core :as reagent]
[status-im.react-native.resources :as resources]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[quo2.components.selectors.disclaimer :as disclaimer]
[quo2.components.icon :as icon]
[status-im.utils.handlers :refer [>evt]]
[quo2.components.tags.context-tags :as context-tags]
[status-im.communities.core :as communities]
[quo2.foundations.colors :as colors]))
;; TODO: update with real data
(def community-rules [{:index 1
:title "Be respectful"
:content "You must respect all users, regardless of your liking towards them. Treat others the way you want to be treated."}
{:index 2
:title "No Inappropriate Language"
:content "The use of profanity should be kept to a minimum. However, any derogatory language towards any user is prohibited."}
{:index 3
:title "No spamming"
:content "Don't send a lot of small messages right after each other. Do not disrupt chat by spamming."}
{:index 4
:title "No pornographic, adult or NSFW material"
:content "This is a community server and not meant to share this kind of material."}
{:index 5
:title "No advertisements"
:content "We do not tolerate any kind of advertisements, whether it be for other communities or streams."}
{:index 6
:title "No offensive names and profile pictures"
:content "You will be asked to change your name or picture if the staff deems them inappropriate."}])
(defn community-rule-item [{:keys [title content index]}]
[react/view
{:style {:flex 1 :margin-top 16}}
[react/view
{:style
{:flex 1
:flex-direction :row
:align-items :center}}
[react/view
{:style
{:height 18
:width 18
:margin-left 1
:margin-right 9
:background-color colors/white
:border-color colors/neutral-20
:border-width 1
:border-radius 6}}
[text/text {:style
{:margin-left :auto
:margin-right :auto
:margin-top :auto
:margin-bottom :auto}
:accessibility-label :communities-rule-index
:weight :medium
:size :label}
(str index)]]
[text/text
{:accessibility-label :communities-rule-title
:weight :semi-bold
:size :paragraph-2}
title]]
[text/text
{:style {:margin-left 28 :margin-top 1}
:accessibility-label :communities-rule-content
:size :paragraph-2}
content]])
(defn community-rules-list [rules]
[list/flat-list
{:shows-horizontal-scroll-indicator false
:data rules
:separator [react/view {:margin-top 1}]
:render-fn community-rule-item}])
(defn request-to-join [community]
(let [agreed-to-rules? (reagent/atom false)]
(fn []
[react/view {:style {:flex 1 :margin-left 20 :margin-right 20 :margin-bottom 20}}
[react/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :space-between}}
[text/text {:accessibility-label :communities-join-community
:weight :semi-bold
:size :heading-1}
(i18n/label :t/join-open-community)]
[react/view {:style {:height 32
:width 32
:align-items :center
:background-color colors/white
:border-color colors/neutral-20
:border-width 1
:border-radius 8
:display :flex
:justify-content :center}}
[icon/icon :i/info]]]
;; TODO get tag image from community data
[context-tags/context-tag
{:style
{:margin-right :auto
:margin-top 8}}
(resources/get-image :status-logo) (:name community)]
[text/text {:style {:margin-top 24}
:accessibility-label :communities-rules-title
:weight :semi-bold
:size :paragraph-1}
(i18n/label :t/community-rules)]
[community-rules-list community-rules]
[disclaimer/disclaimer
{:container-style {:margin-top 20}
:on-change #(swap! agreed-to-rules? not)}
(i18n/label :t/accept-community-rules)]
[react/view {:style {:width "100%"
:margin-top 32 :margin-bottom 16
:flex 1
:flex-direction :row
:align-items :center
:justify-content :space-evenly}}
[button/button {:on-press #(>evt [:bottom-sheet/hide])
:type :grey :style {:flex 1 :margin-right 12}} (i18n/label :t/cancel)]
[button/button
{:on-press (fn []
(>evt [::communities/join (:id community)])
(>evt [:bottom-sheet/hide]))
:disabled (not @agreed-to-rules?) :style {:flex 1}} (i18n/label :t/join-open-community)]]])))
@@ -159,15 +159,3 @@
:accessibility-label :chat-key
:monospace true}
community-key]]]))
(defn render-featured-community [{:keys [name id]}]
[react/touchable-highlight {:on-press #(>evt [:navigate-to :community {:community-id id}])
:accessibility-label :chat-item}
[react/view {:padding-right 8
:padding-vertical 8}
[react/view {:border-color quo.colors/gray-lighter
:border-radius 36
:border-width 1
:padding-horizontal 8
:padding-vertical 5}
[quo/text {:color :link} name]]]])
+3 -8
View File
@@ -22,7 +22,7 @@
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.components.invite.views :as invite]
[status-im.utils.config :as config]
[status-im2.setup.config :as config]
[quo2.components.markdown.text :as quo2.text]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
@@ -234,7 +234,7 @@
(views/defview plus-button []
(views/letsubs [logging-in? [:multiaccounts/login]]
[components.plus-button/plus-button
[components.plus-button/plus-button-old
{:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
:loading logging-in?
@@ -259,12 +259,7 @@
:on-press #(do
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
(if config/new-activity-center-enabled?
(re-frame/dispatch [:show-popover {:view :activity-center
:style {:margin 0}
:disable-touchable-overlay? true
:blur-view? true
:blur-view-props {:blur-amount 20
:blur-type :dark}}])
(re-frame/dispatch [:activity-center/open])
(re-frame/dispatch [:navigate-to :notifications-center])))}
[icons/icon :main-icons/notification2 {:color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)}]]
(when (pos? notif-count)
@@ -234,7 +234,8 @@
:height 110}}])]]]
[react/view {:margin-bottom 50}
[quo/button
{:on-press #(re-frame/dispatch [:keycard.recovery.no-key.ui/generate-key-pressed])}
{:test-id :generate-new-key
:on-press #(re-frame/dispatch [:keycard.recovery.no-key.ui/generate-key-pressed])}
(i18n/label :t/generate-new-key)]
[quo/button
{:type :secondary
@@ -157,7 +157,7 @@
:margin-bottom 24}
[quo/checkbox {:value @tos-accepted
:on-change #(swap! tos-accepted not)}]
[rn/touchable-opacity {:on-press #(swap! tos-accepted not)}
[rn/touchable-opacity {:test-ID :terms-of-service :on-press #(swap! tos-accepted not)}
[react/nested-text {:style {:margin-left 12}}
(i18n/label :t/accept-status-tos-prefix)
[{:style (merge {:color colors/blue}
@@ -167,7 +167,8 @@
" "
(i18n/label :t/terms-of-service)]]]]
[react/view {:style {:margin-bottom 24}}
[quo/button {:disabled (not @tos-accepted)
[quo/button {:test-ID :get-started
:disabled (not @tos-accepted)
:on-press #(do (re-frame/dispatch [:init-root :onboarding])
;; clear atom state for next use
(reset! tos-accepted false)
@@ -83,7 +83,8 @@
[react/view {:style {:align-items :center}}
[react/view {:style (assoc styles/bottom-button :margin-bottom 16)}
[quo/button
{;:disabled existing-account?
{:test-ID :generate-keys
;:disabled existing-account?
:on-press #(re-frame/dispatch [:generate-and-derive-addresses])
:accessibility-label :onboarding-next-button}
(i18n/label :t/generate-a-key)]]
@@ -44,7 +44,8 @@
(i18n/label :intro-wizard-title-alt4)]
[rn/view
[rn/view {:style {:padding 16}}
[quo/text-input {:secure-text-entry true
[quo/text-input {:test-ID :password-placeholder
:secure-text-entry true
:auto-capitalize :none
:auto-focus true
:show-cancel false
@@ -56,7 +57,8 @@
(some-> ^js @confirm-ref .focus))}]]
[rn/view {:style {:padding 16
:opacity (if-not valid-password 0.33 1)}}
[quo/text-input {:secure-text-entry true
[quo/text-input {:test-ID :confirm-password-placeholder
:secure-text-entry true
:get-ref #(reset! confirm-ref %)
:auto-capitalize :none
:show-cancel false
+4 -7
View File
@@ -18,7 +18,6 @@
[status-im.ui.screens.browser.views :as browser]
[status-im.ui.screens.bug-report :as bug-report]
[status-im.ui.screens.chat.pinned-messages :as pin-messages]
[status-im.ui.screens.communities.community-overview-redesign :as community-overview]
[status-im.ui.screens.communities.channel-details :as communities.channel-details]
[status-im.ui.screens.communities.community :as community]
[status-im.ui.screens.communities.community-emoji-thumbnail-picker :as community-emoji-thumbnail-picker]
@@ -115,7 +114,8 @@
[status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
[status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send]
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]))
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]
[status-im.ui2.screens.chat.group-details.view :as group-details]))
(defn right-button-options [id icon]
{:id id
@@ -212,10 +212,9 @@
:component pin-messages/pinned-messages}
{:name :group-chat-profile
:insets {:top false}
;;TODO animated-header
:options {:topBar {:visible false}}
:component profile.group-chat/group-chat-profile}
:component group-details/group-details}
{:name :group-chat-invite
;;TODO parameter in the event
:options {:topBar {:visible false}}
@@ -307,9 +306,7 @@
{:name :community-membership
:options {:topBar {:title {:text (i18n/label :t/membership-title)}}}
:component membership/membership}
{:name :community-overview
:options {:topBar {:visible false}}
:component community-overview/overview}
;;BROWSER
{:name :empty-tab
+86 -54
View File
@@ -3,22 +3,24 @@
[status-im.chat.models :as chat.models]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.i18n.i18n :as i18n]
[utils.re-frame :as rf]
[status-im.ui2.screens.common.core :as common]
[status-im.constants :as constants]
[status-im.utils.re-frame :as rf]
[quo2.components.drawers.action-drawers :as drawer]))
(defn- entry [{:keys [icon label on-press danger? sub-label chevron?]}]
(defn- entry [{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
{:pre [(keyword? icon)
(string? label)
(fn? on-press)
(boolean? danger?)
(boolean? chevron?)]}
{:icon icon
:label label
:on-press on-press
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)})
{:icon icon
:label label
:on-press on-press
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)
:add-divider? add-divider?})
(defn hide-sheet-and-dispatch [event]
(rf/dispatch [:bottom-sheet/hide])
@@ -40,14 +42,40 @@
(defn unmute-chat-action [chat-id]
(hide-sheet-and-dispatch [::chat.models/mute-chat-toggled chat-id false]))
(defn clear-history-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/clear-history-pressed chat-id]))
(defn clear-history-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(common/alert {:title (i18n/label :t/clear-history?)
:description (i18n/label :t/clear-history-confirmation-content)
:context item
:button-text (i18n/label :t/clear-history)
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
(defn delete-chat-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id]))
(defn delete-chat-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(common/alert {:title (i18n/label :t/delete-chat?)
:description (i18n/label :t/delete-chat-confirmation)
:context item
:button-text (i18n/label :t/delete-chat)
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
(defn leave-group-action [chat-id]
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-pressed chat-id]))
(defn leave-group-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(common/alert {:title (i18n/label :t/leave-group?)
:description (i18n/label :t/leave-chat-confirmation)
:context item
:button-text (i18n/label :t/leave-group)
:on-press #(hide-sheet-and-dispatch [:chat.ui/leave-chat chat-id])}))}]))
(defn block-user-action [{:keys [public-key] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn [] (common/alert {:title (i18n/label :t/block-user?)
:description (i18n/label :t/block-contact-details)
:context item
:button-text (i18n/label :t/block-user)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}]))
(defn mute-chat-entry [chat-id]
(let [muted? (rf/sub [:chats/muted chat-id])]
@@ -64,33 +92,35 @@
:chevron? true})))
(defn mark-as-read-entry [chat-id]
(entry {:icon :i/correct
:label (i18n/label :t/mark-as-read)
:on-press #(mark-all-read-action chat-id)
:danger? false
:sub-label nil
:chevron? false}))
(entry {:icon :i/correct
:label (i18n/label :t/mark-as-read)
:on-press #(mark-all-read-action chat-id)
:danger? false
:sub-label nil
:chevron? false
:add-divider? true}))
(defn clear-history-entry [chat-id]
(entry {:icon :i/delete
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
:danger? true
:sub-label nil
:chevron? false}))
(entry {:icon :i/delete
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
:danger? true
:sub-label nil
:chevron? false
:add-divider? true}))
(defn delete-chat-entry [chat-id]
(defn delete-chat-entry [item]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action chat-id)
:on-press #(delete-chat-action item)
:danger? true
:sub-label nil
:chevron? false}))
(defn leave-group-entry [chat-id]
(defn leave-group-entry [item]
(entry {:icon :i/log-out
:label (i18n/label :t/leave-group)
:on-press #(leave-group-action chat-id)
:on-press #(leave-group-action item)
:danger? true
:sub-label nil
:chevron? false}))
@@ -176,17 +206,18 @@
:chevron? false}))
(defn mark-untrustworthy-entry []
(entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy)
:on-press #(js/alert "TODO: to be implemented, probably requires status-go impl. and design input")
:danger? true
:sub-label nil
:chevron? false}))
(entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy)
:on-press #(js/alert "TODO: to be implemented, requires status-go impl.")
:danger? true
:sub-label nil
:chevron? false
:add-divider? true}))
(defn block-user-entry []
(defn block-user-entry [item]
(entry {:icon :i/block
:label (i18n/label :t/block-user)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:on-press #(block-user-action item)
:danger? true
:sub-label nil
:chevron? false}))
@@ -231,11 +262,11 @@
:sub-label nil
:chevron? false}))
(defn destructive-actions [chat-id group-chat]
[(clear-history-entry chat-id)
(defn destructive-actions [{:keys [group-chat] :as item}]
[(clear-history-entry item)
(if group-chat
(leave-group-entry chat-id)
(delete-chat-entry chat-id))])
(leave-group-entry item)
(delete-chat-entry item))])
(defn notification-actions [{:keys [chat-id group-chat public?]} inside-chat?]
[(mark-as-read-entry chat-id)
@@ -262,32 +293,33 @@
(when (and admin? inside-chat?) (edit-group-entry))
(when (and admin? inside-chat?) (group-privacy-entry))]))
(defn one-to-one-actions [{:keys [chat-id group-chat] :as item} inside-chat?]
(defn one-to-one-actions [{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer [[(view-profile-entry chat-id)
(edit-nickname-entry chat-id)]
(notification-actions item inside-chat?)
(destructive-actions chat-id group-chat)]])
(destructive-actions item)]])
(defn public-chat-actions [{:keys [chat-id group-chat] :as item} inside-chat?]
(defn public-chat-actions [{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer [[(group-details-entry chat-id)
(when inside-chat?
(add-members-entry))]
(notification-actions item inside-chat?)
(destructive-actions chat-id group-chat)]])
(destructive-actions item)]])
(defn private-group-chat-actions [{:keys [chat-id group-chat] :as item} inside-chat?]
(defn private-group-chat-actions [item inside-chat?]
[drawer/action-drawer [(group-actions item inside-chat?)
(notification-actions item inside-chat?)
(destructive-actions chat-id group-chat)]])
(destructive-actions item)]])
(defn contact-actions [{:keys [public-key] :as contact}]
(defn contact-actions [{:keys [public-key added] :as contact}]
[drawer/action-drawer [[(view-profile-entry public-key)
(remove-from-contacts-entry contact)
(rename-entry)
(show-qr-entry)
(share-profile-entry)]
(when added
(remove-from-contacts-entry contact)
(rename-entry)
(show-qr-entry)
(share-profile-entry))]
[(mark-untrustworthy-entry)
(block-user-entry)]]])
(block-user-entry contact)]]])
(defn actions [{:keys [chat-type] :as item} inside-chat?]
(case chat-type
@@ -8,7 +8,7 @@
[quo.platform :as platform]
[quo2.components.markdown.text :as text]
[status-im.ui2.screens.chat.components.message-home-item.style :as style]
[status-im.utils.re-frame :as rf]
[utils.re-frame :as rf]
[status-im.ui2.screens.chat.actions :as actions]))
(defn open-chat [chat-id]
@@ -22,11 +22,13 @@
(defn contact-item [item]
(let [{:keys [public-key ens-verified added? images]} item
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))]
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))
current-pk (rf/sub [:multiaccount/public-key])]
[rn/touchable-opacity (merge {:style (style/container)
:on-press #(open-chat public-key)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}])})
:on-long-press #(when-not (= current-pk public-key)
(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}]))})
[user-avatar/user-avatar {:full-name display-name
:profile-picture photo-path
:status-indicator? true
@@ -44,11 +46,14 @@
(when added?
[rn/view {:style {:margin-left 5 :margin-top 4}}
[icons/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
[text/text {:size :paragraph-1
[text/text {:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(utils/get-shortened-address public-key)]]
[rn/touchable-opacity {:style {:position :absolute
:right 20}
:active-opacity 1} ; TODO: on-long-press to be added when contact bottom sheet is implemented
[icons/icon :i/options {:size 20 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]]))
(when-not (= current-pk public-key)
[rn/touchable-opacity {:style {:position :absolute
:right 20}
:active-opacity 1
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}])}
[icons/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]])]))
@@ -1,11 +1,10 @@
(ns status-im.ui2.screens.chat.components.message-home-item.view
(:require [clojure.string :as string]
[status-im.utils.re-frame :as rf]
[utils.re-frame :as rf]
[status-im.utils.datetime :as time]
[quo2.foundations.typography :as typography]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo.react-native :as rn]
[quo.platform :as platform]
[quo2.core :as quo2]
@@ -90,14 +89,11 @@
(defn display-pic-view [group-chat color display-name photo-path]
(if group-chat
[rn/view {:style (style/group-chat-icon color)}
[icons/icon :i/group {:size 16 :color colors/white-opa-70}]]
[user-avatar/user-avatar {:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? true
:size :small
:ring? false}]))
[quo2/group-avatar {:color color
:size :medium}]
[quo2/user-avatar {:full-name display-name
:profile-picture photo-path
:size :small}]))
(defn messages-home-item [item]
(let [{:keys [chat-id
@@ -68,11 +68,11 @@
:size :label
:weight :regular
:accessibility-label :quoted-message
:ellipsize-mode :tail
:style (merge
{:ellipsize-mode :tail
:text-transform :none
:margin-left 4
:margin-top 2}
{:text-transform :none
:margin-left 4
:margin-top 2}
(when (or (= constants/content-type-image content-type)
(= constants/content-type-sticker content-type)
(= constants/content-type-audio content-type))
@@ -0,0 +1,20 @@
(ns status-im.ui2.screens.chat.group-details.style
(:require [quo2.foundations.colors :as colors]))
(defn actions-view []
{:flex-direction :row
:justify-content :space-between
:margin-vertical 20
:padding-horizontal 20})
(defn action-container [color]
{:background-color (colors/theme-alpha color 0.1 0.1)
:flex 0.29
:border-radius 16
:padding 12})
(defn count-container []
{:width 16
:height 16
:border-radius 6
:background-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5)})
@@ -0,0 +1,90 @@
(ns status-im.ui2.screens.chat.group-details.view
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[status-im.ui2.screens.chat.group-details.style :as style]
[quo2.core :as quo2]
[utils.re-frame :as rf]
[i18n.i18n :as i18n]
[status-im.ui2.screens.chat.components.contact-item.view :as contact-item]))
(defn back-button []
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-left 20}
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn options-button []
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-right 20}
:accessibility-label :options-button}
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn count-container [count]
[rn/view {:style (style/count-container)}
[quo2/text {:size :label
:weight :medium
:style {:text-align :center}} count]])
(defn prepare-members [members]
(let [admins (filter :admin? members)
online (filter #(and (not (:admin? %)) (:online? %)) members)
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
(vals (cond-> {}
(seq admins) (assoc :owner {:title "Owner" :data admins})
(seq online) (assoc :online {:title "Online" :data online})
(seq offline) (assoc :offline {:title "Offline" :data offline})))))
(defn contacts-section-header [{:keys [title]}]
[rn/view {:style {:padding-horizontal 20 :border-top-width 1 :border-top-color colors/neutral-20 :padding-vertical 8 :margin-top 8}}
[quo2/text {:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]])
(defn group-details []
(let [{:keys [admins chat-id chat-name color public?]} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/current-chat-contacts])
sectioned-members (prepare-members members)
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view {:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header {:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view {:style {:flex-direction :row
:margin-top 12
:padding-horizontal 20}}
[quo2/group-avatar {:color color
:size :medium}]
[quo2/text {:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo2/icon (if public? :i/world :i/privacy) {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity {:style (style/action-container color)}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/pinned-messages-2)]]
[rn/touchable-opacity {:style (style/action-container color)}
[quo2/icon :i/activity-center {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/mute-group)]]
[rn/touchable-opacity {:style (style/action-container color)}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count members)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list {:key-fn :title
:sticky-section-headers-enabled false
:sections sectioned-members
:render-section-header-fn contacts-section-header
:render-fn contact-item/contact-item}]]))
+11 -11
View File
@@ -16,14 +16,13 @@
[status-im.utils.debounce :as debounce]
[status-im.utils.utils :as utils]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.invite.views :as invite]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.utils.config :as config]
[quo2.components.markdown.text :as quo2.text]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]
[quo.react-native :as rn]
[react-native.core :as rn]
[quo.react-native :as quo.rn]
[quo.react]
[quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]
@@ -37,7 +36,9 @@
[status-im.ui2.screens.chat.components.received-cr-item :as received-cr-item]
[status-im.ui2.screens.chat.components.message-home-item.view :refer [messages-home-item]]
[status-im.ui2.screens.chat.components.contact-item.view :refer [contact-item]]
[clojure.string :as str])
[clojure.string :as str]
[status-im2.common.plus-button.view :as components.plus-button]
[status-im2.setup.config :as config])
(:require-macros [status-im.utils.views :as views]))
(defn home-tooltip-view []
@@ -195,7 +196,7 @@
{:id :sent
:label (i18n/label :t/sent)}]}]
[list/flat-list
{:key-fn :first
{:key-fn :chat-id
:data (if (= @selected-requests-tab :received) received-requests sent-requests)
:render-fn received-cr-item/received-cr-item}]]))])
@@ -279,7 +280,7 @@
:render-fn messages-home-item}]
[rn/view {:style {:flex 1}} (when (> (count requests) 0)
[contact-requests requests])
[list/section-list
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections contacts
@@ -314,7 +315,7 @@
:on-press #(do
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
(if config/new-activity-center-enabled?
(re-frame/dispatch [:navigate-to :activity-center])
(re-frame/dispatch [:activity-center/open])
(re-frame/dispatch [:navigate-to :notifications-center])))}
[icons/icon :main-icons/notification2 {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
(when (pos? notif-count)
@@ -355,9 +356,9 @@
[:f>
(fn []
(quo.react/effect! #(re-frame/dispatch [:get-activity-center-notifications]))
[rn/keyboard-avoiding-view {:style {:flex 1
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
:ignore-offset true}
[quo.rn/keyboard-avoiding-view {:style {:flex 1
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
:ignore-offset true}
[topbar/topbar {:navigation :none
:use-insets true
:background (colors/theme-colors colors/neutral-5 colors/neutral-95)
@@ -377,4 +378,3 @@
[quo2.text/text {:size :heading-1 :weight :semi-bold} (i18n/label :t/messages)]
[plus-button]]
[chats-list]])])
@@ -34,7 +34,7 @@
[status-im.ui.screens.communities.icon :as communities.icon]
[status-im.ui2.screens.chat.components.reply :as components.reply]
[status-im.utils.config :as config]
[status-im.utils.re-frame :as rf]
[utils.re-frame :as rf]
[status-im.utils.security :as security]
[quo2.components.icon :as icons]
[status-im.utils.datetime :as time]
@@ -288,11 +288,18 @@
display-name]
[message-home-item/verified-or-contact-icon contact]
(when show-key?
[text/text {:size :label
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:margin-left 8
:margin-top 2}}
(str (utils/get-shortened-address (:public-key contact)) " • " (time/to-short-str timestamp))])])
(let [props {:size :label
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}]
[rn/view {:style {:margin-left 8
:margin-top 2
:flex-direction :row}}
[text/text
(assoc props :accessibility-label :message-chat-key)
(utils/get-shortened-address (:public-key contact))]
[text/text props " • "]
[text/text
(assoc props :accessibility-label :message-timestamp)
(time/to-short-str timestamp)]]))])
(defn message-content-wrapper
"Author, userpic and delivery wrapper"
@@ -505,17 +512,17 @@
[{:type :main
:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
:id :reply
:icon :i/reply-context20
:icon :i/reply
:label (i18n/label :t/message-reply)}
{:type :main
:on-press #(react/copy-to-clipboard (get content :text))
:id :copy
:icon :i/copy-context20
:icon :i/copy
:label (i18n/label :t/copy-text)}]
(when message-pin-enabled [{:type :main
:on-press #(pin-message message)
:id :pin
:icon :i/pin-context20
:icon :i/pin
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))}]))))]
(reset! ref on-long-press)
[message-content-wrapper message
@@ -546,7 +553,7 @@
(on-long-press
(when-not outgoing
[{:type :main
:icon :i/stickers-context20
:icon :i/stickers
:on-press #(when pack
(re-frame/dispatch [:chat.ui/show-profile from]))
:label (i18n/label :t/see-sticker-set)}])))]
@@ -574,31 +581,31 @@
(concat [{:type :main
:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
:id :reply
:icon :i/reply-context20
:icon :i/reply
:label (i18n/label :t/message-reply)}
{:type :main
:on-press #(re-frame/dispatch [:chat.ui/save-image-to-gallery (:image content)])
:id :save
:icon :i/save-context20
:icon :i/save
:label (i18n/label :t/save-image-library)}
{:type :main
:on-press #(images/download-image-http
(get-in message [:content :image]) preview/share)
:id :share
:icon :i/share-context20
:icon :i/share
:label (i18n/label :t/share-image)}]
[{:type :danger
:on-press #(re-frame/dispatch
[:chat.ui/delete-message-for-me message
constants/delete-message-for-me-undo-time-limit-ms])
:label (i18n/label :t/delete-for-me)
:icon :i/delete-context20
:icon :i/delete
:id :delete-for-me}]
(when (and outgoing config/delete-message-enabled?)
[{:type :danger
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
:label (i18n/label :t/delete-for-everyone)
:icon :i/delete-context20
:icon :i/delete
:id :delete}]))))]
(reset! ref on-long-press)
[message-content-wrapper message
@@ -622,20 +629,20 @@
{:type :main
:on-press #(pin-message message)
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
:icon :i/pin-context20
:icon :i/pin
:id (if pinned :unpin :pin)}
{:type :danger
:on-press #(re-frame/dispatch
[:chat.ui/delete-message-for-me message
constants/delete-message-for-me-undo-time-limit-ms])
:label (i18n/label :t/delete-for-me)
:icon :i/delete-context20
:icon :i/delete
:id :delete-for-me}
(when (and outgoing config/delete-message-enabled?)
{:type :danger
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
:label (i18n/label :t/delete-for-everyone)
:icon :i/delete-context20
:icon :i/delete
:id :delete})]))]
(reset! ref on-long-press)
[message-content-wrapper message
@@ -5,7 +5,6 @@
[quo.react-native :as rn]
[quo2.foundations.typography :as typography]
[quo2.foundations.colors :as colors]
[status-im.switcher.constants :as constants]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.ui2.screens.chat.messages.style :as style]
@@ -14,7 +13,7 @@
(defn pin-limit-popover [chat-id pinned-messages-list]
[:f>
(fn []
(let [{:keys [width]} (constants/dimensions)
(let [width (<sub [:dimensions/window-width])
show-pin-limit-modal? (<sub [:chats/pin-modal chat-id])
opacity-animation (reanimated/use-shared-value 0)
z-index-animation (reanimated/use-shared-value -1)]
@@ -9,6 +9,7 @@
[status-im.ui.screens.chat.group :as chat.group]
[status-im.ui.screens.chat.message.datemark :as message-datemark]
[status-im.ui.screens.chat.message.gap :as gap]
[status-im.ui.screens.chat.components.messages-skeleton :as messages-skeleton]
[status-im.utils.utils :as utils]
[status-im.utils.platform :as platform]
[status-im.ui.screens.chat.state :as state]
@@ -19,6 +20,11 @@
(defonce show-floating-scroll-down-button (reagent/atom false))
(defonce messages-list-ref (atom nil))
(def messages-view-height (reagent/atom 0))
(defn on-messages-view-layout [^js ev]
(reset! messages-view-height (-> ev .-nativeEvent .-layout .-height)))
(def list-key-fn #(or (:message-id %) (:value %)))
(def list-ref #(reset! messages-list-ref %))
@@ -63,8 +69,7 @@
all-loaded? (<sub [:chats/all-loaded? chat-id])]
[rn/view {:style (when platform/android? {:scaleY -1})}
(if (or loading-messages? (not chat-id) (not all-loaded?))
[rn/view {:height 324 :align-items :center :justify-content :center}
[rn/activity-indicator {:animating true}]]
[messages-skeleton/messages-skeleton @messages-view-height]
[chat-intro-header-container chat no-messages?])]))
(defn list-header [{:keys [chat-id chat-type invitation-admin]}]
@@ -186,6 +191,7 @@
:on-scroll on-scroll
;;TODO https://github.com/facebook/react-native/issues/30034
:inverted (when platform/ios? true)
:style (when platform/android? {:scaleY -1})})]
:style (when platform/android? {:scaleY -1})
:on-layout on-messages-view-layout})]
(when @show-floating-scroll-down-button
[floating-scroll-down-button show-input?])]))
@@ -0,0 +1,18 @@
(ns status-im.ui2.screens.common.alert.style
(:require [quo2.foundations.colors :as colors]))
(defn context-container []
{:flex-direction :row
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:border-radius 20
:align-items :center
:align-self :flex-start
:padding 4
:margin-top 8
:margin-left -4
:margin-bottom 16})
(defn buttons-container []
{:flex-direction :row
:justify-content :space-between
:margin-top 20})
@@ -0,0 +1,56 @@
(ns status-im.ui2.screens.common.alert.view
(:require
[reagent.core :as reagent]
[status-im.i18n.i18n :as i18n]
[utils.re-frame :as rf]
[quo2.components.markdown.text :as quo2.text]
[react-native.core :as rn]
[quo2.core :as quo2]
[quo2.components.buttons.button :as quo2.button]
[status-im.ui2.screens.common.alert.style :as style]
[quo2.components.selectors.selectors :as selectors]))
(defn avatar [group-chat color display-name photo-path]
(if group-chat
[quo2/group-avatar {:color color
:size :small}]
[quo2/user-avatar {:full-name display-name
:profile-picture photo-path
:size :xxs
:status-indicator false}]))
(defn extra-action-view [extra-action extra-text extra-action-selected?]
(when extra-action
[rn/view {:style {:margin-top 16 :flex-direction :row}}
[selectors/checkbox {:on-change (fn [selected?] (reset! extra-action-selected? selected?))}]
[quo2.text/text {:style {:margin-left 10}} extra-text]]))
(defn alert [{:keys [title description context button-text on-press extra-action extra-text]}]
(let [extra-action-selected? (reagent/atom false)]
(fn []
(let [{:keys [group-chat chat-id public-key color name]} context
id (or chat-id public-key)
display-name (if-not group-chat (first (rf/sub [:contacts/contact-two-names-by-identity id])) name)
contact (when-not group-chat (rf/sub [:contacts/contact-by-address id]))
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path id]))]
[rn/view {:style {:margin-horizontal 20}}
[quo2.text/text {:weight :semi-bold
:size :heading-1} title]
[rn/view {:style (style/context-container)}
[avatar group-chat color display-name photo-path]
[quo2.text/text {:weight :medium
:size :paragraph-2
:style {:margin-left 4}} display-name]]
[quo2.text/text description]
[extra-action-view extra-action extra-text extra-action-selected?]
[rn/view {:style (style/buttons-container)}
[quo2.button/button {:type :grey
:style {:flex 0.48}
:on-press #(rf/dispatch [:bottom-sheet/hide])}
(i18n/label :t/close)]
[quo2.button/button {:type :danger
:style {:flex 0.48}
:on-press #(do
(when @extra-action-selected? (extra-action))
(on-press))}
button-text]]]))))
@@ -0,0 +1,4 @@
(ns status-im.ui2.screens.common.core
(:require status-im.ui2.screens.common.alert.view))
(def alert status-im.ui2.screens.common.alert.view/alert)
@@ -1,123 +0,0 @@
(ns status-im.ui2.screens.communities.communities-home
(:require [re-frame.core :as re-frame]
[reagent.core :as reagent]
[quo2.components.community.community-list-view :as community-list-view]
[quo.components.safe-area :as safe-area]
[quo2.components.markdown.text :as text]
[quo2.components.tabs.tabs :as tabs]
[quo2.foundations.colors :as colors]
[quo2.components.community.discover-card :as discover-card]
[quo2.components.navigation.top-nav :as topnav]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.i18n.i18n :as i18n]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as rn]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.screens.communities.community :as community]))
(def selected-tab (reagent/atom :joined))
(defn plus-button []
(let [logging-in? (<sub [:multiaccounts/login])]
[components.plus-button/plus-button
{:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
:loading logging-in?
:accessibility-label :new-chat-button}]))
(defn render-fn [community-item]
[community-list-view/communities-membership-list-item
{:on-press (fn []
(>evt [:communities/load-category-states (:id community-item)])
(>evt [:dismiss-keyboard])
(>evt [:navigate-to :community {:community-id (:id community-item)}]))
:on-long-press #(>evt [:bottom-sheet/show-sheet
{:content (fn []
[community/community-actions community-item])}])}
community-item])
(defn community-list-key-fn [item]
(:id item))
(defn get-item-layout-js [_ index]
#js {:length 64 :offset (* 64 index) :index index})
(defn home-community-segments []
[rn/view {:style {:padding-bottom 12
:padding-top 16
:margin-top 8
:height 60
:padding-horizontal 20}}
[tabs/tabs {:size 32
:on-change #(reset! selected-tab %)
:default-active :joined
:data [{:id :joined :label (i18n/label :chats/joined) :accessibility-label :joined-tab}
{:id :pending :label (i18n/label :t/pending) :accessibility-label :pending-tab}
{:id :opened :label (i18n/label :t/opened) :accessibility-label :opened-tab}]}]])
(defn communities-list [communities]
[list/flat-list
{:key-fn community-list-key-fn
:getItemLayout get-item-layout-js
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:data communities
:render-fn render-fn}])
(defn segments-community-lists [communities]
(let [tab @selected-tab]
[rn/view {:style {:padding-left 20
:padding-vertical 12}}
(case tab
:joined
[communities-list communities]
:pending
[communities-list communities]
:opened
[communities-list communities])]))
(defn title-column []
[rn/view
{:style {:flex-direction :row
:align-items :center
:height 56
:padding-vertical 12
:margin-bottom 8
:padding-horizontal 20}}
[rn/view
{:flex 1}
[text/text {:accessibility-label :communities-screen-title
:margin-right 6
:weight :semi-bold
:size :heading-1}
(i18n/label :t/communities)]]
[plus-button]])
(defn discover-card []
[discover-card/discover-card {:on-press #(>evt [:navigate-to :discover-communities])
:title (i18n/label :t/discover)
:description (i18n/label :t/whats-trending)
:accessibility-label :communities-home-discover-card}])
(defn communities-home []
(let [communities (<sub [:communities/communities])]
[rn/view {:flex 1}
[topnav/top-nav {:type :default}]
[title-column]
[discover-card]
[home-community-segments]
[segments-community-lists communities]]))
(defn views []
[safe-area/consumer
(fn [insets]
[rn/view {:style {:flex 1
:padding-top (:top insets)
:background-color (colors/theme-colors
colors/neutral-5
colors/neutral-95)}}
[communities-home]])])
@@ -1,142 +0,0 @@
(ns status-im.ui2.screens.communities.discover-communities
(:require [reagent.core :as reagent]
[status-im.i18n.i18n :as i18n]
[status-im.ui.components.list.views :as list]
[quo.react-native :as rn]
[quo2.components.markdown.text :as quo2.text]
[quo2.components.counter.counter :as quo2.counter]
[quo.components.safe-area :as safe-area]
[status-im.react-native.resources :as resources]
[status-im.utils.handlers :refer [<sub >evt]]
[quo2.components.buttons.button :as quo2.button]
[quo2.components.community.community-card-view :as community-card]
[quo2.components.community.community-list-view :as community-list]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[status-im.ui.screens.communities.community :as community]))
(def view-type (reagent/atom :card-view))
(def mock-community-item-data ;; TODO: remove once communities are loaded with this data.
{:data {:community-color "#0052FF"
:status :gated
:locked? true
:cover (resources/get-image :community-cover)
:tokens [{:id 1
:group [{:id 1
:token-icon (resources/get-image :status-logo)}]}]
:tags [{:id 1
:tag-label (i18n/label :t/music)
:resource (resources/get-image :music)}
{:id 2
:tag-label (i18n/label :t/lifestyle)
:resource (resources/get-image :lifestyle)}
{:id 3
:tag-label (i18n/label :t/podcasts)
:resource (resources/get-image :podcasts)}]}})
(defn render-other-fn [community-item]
(let [item (merge community-item
(get mock-community-item-data :data)
{:featured false})]
(if (= @view-type :card-view)
[community-card/community-card-view-item item #(>evt [:navigate-to :community-overview item])]
[community-list/communities-list-view-item
{:on-press (fn []
(>evt [:communities/load-category-states (:id item)])
(>evt [:dismiss-keyboard])
(>evt [:navigate-to :community {:community-id (:id item)}]))
:on-long-press #(>evt [:bottom-sheet/show-sheet
{:content (fn []
[community/community-actions item])}])}
item])))
(defn render-featured-fn [community-item]
(let [item (merge community-item
(get mock-community-item-data :data)
{:featured true})]
[community-card/community-card-view-item item #(>evt [:navigate-to :community-overview item])]))
(defn get-item-layout-js [_ index]
#js {:length 64 :offset (* 64 index) :index index})
(defn screen-title []
[rn/view
{:height 56
:padding-vertical 12
:padding-horizontal 20}
[quo2.text/text {:accessibility-label :communities-screen-title
:weight :semi-bold
:size :heading-1}
(i18n/label :t/discover-communities)]])
(defn featured-communities [communities]
[list/flat-list
{:key-fn :id
:horizontal true
:getItemLayout get-item-layout-js
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:data communities
:render-fn render-featured-fn}])
(defn featured-communities-section [communities]
(let [count (reagent/atom {:value (count communities) :type :grey})]
[rn/view {:flex 1}
[rn/view {:flex-direction :row
:height 30
:padding-top 8
:justify-content :space-between
:padding-horizontal 20}
[rn/view {:flex-direction :row
:align-items :center}
[quo2.text/text {:accessibility-label :featured-communities-title
:weight :semi-bold
:size :paragraph-1
:style {:margin-right 6}}
(i18n/label :t/featured)]
[quo2.counter/counter @count (:value @count)]]
[icons/icon :i/info {:container-style {:align-items :center
:justify-content :center}
:resize-mode :center
:size 20
:color (colors/theme-colors
colors/neutral-50
colors/neutral-40)}]]
[rn/view {:margin-top 8
:padding-left 20}
[featured-communities communities]]]))
(defn other-communities [communities sort-list-by]
(let [sorted-communities (sort-by sort-list-by communities)]
[list/flat-list
{:key-fn :id
:getItemLayout get-item-layout-js
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:header (featured-communities-section communities)
:data sorted-communities
:render-fn render-other-fn}]))
(defn discover-communities []
(let [communities (<sub [:communities/communities])]
[rn/view {:flex 1}
[quo2.button/button {:icon true
:type :grey
:size 32
:style {:margin-vertical 12
:margin-left 20}
:on-press #(>evt [:navigate-back])}
:close]
[screen-title]
[other-communities communities :name]]))
(defn communities []
(fn []
[safe-area/consumer
(fn []
[rn/view {:style {:flex 1
:background-color (colors/theme-colors
colors/white
colors/neutral-90)}}
[discover-communities]])]))
-4
View File
@@ -145,7 +145,3 @@
;;TODO for development only should be removed in status 2.0
(def new-ui-enabled? true)
;; TODO: Remove this (highly) temporary flag once the new Activity Center is
;; usable enough to replace the old one **in the new UI**.
(def new-activity-center-enabled? false)
-28
View File
@@ -4,34 +4,6 @@
[taoensso.timbre :as log]
[status-im.utils.debounce :as debounce]))
(defn- parse-json
;; NOTE(dmitryn) Expects JSON response like:
;; {"error": "msg"} or {"result": true}
[s]
(try
(let [res (-> s
js/JSON.parse
(js->clj :keywordize-keys true))]
;; NOTE(dmitryn): AddPeer() may return {"error": ""}
;; assuming empty error is a success response
;; by transforming {"error": ""} to {:result true}
(if (and (:error res)
(= (:error res) ""))
{:result true}
res))
(catch :default ^js e
{:error (.-message e)})))
(defn response-handler [success-fn error-fn]
(fn handle-response
([response]
(let [{:keys [error result]} (parse-json response)]
(handle-response error result)))
([error result]
(if error
(error-fn error)
(success-fn result)))))
(defn- pretty-print-event [ctx]
(let [[first _] (get-coeffect ctx :event)]
first))
-7
View File
@@ -1,7 +0,0 @@
(ns status-im.utils.re-frame
(:require [re-frame.core :as re-frame]))
(def sub (comp deref re-frame/subscribe))
(def dispatch re-frame/dispatch)
@@ -0,0 +1,10 @@
(ns status-im2.common.plus-button.view
(:require [quo2.components.buttons.button :as quo2.button]))
(defn plus-button [{:keys [on-press accessibility-label]}]
[quo2.button/button {:type :primary
:size 32
:icon true
:accessibility-label (or accessibility-label :plus-button)
:on-press on-press}
:i/add])
@@ -0,0 +1 @@
(ns status-im2.contexts.communities.actions.view)
@@ -0,0 +1,138 @@
(ns status-im2.contexts.communities.discover.view
(:require [reagent.core :as reagent]
[i18n.i18n :as i18n]
[react-native.safe-area :as safe-area]
[react-native.core :as rn]
[quo2.core :as quo]
[quo2.components.community.community-card-view :as community-card]
[quo2.components.community.community-list-view :as community-list]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[utils.re-frame :as rf]
;; TODO move to status-im2
[status-im.react-native.resources :as resources]
[status-im.ui.screens.communities.community :as community]))
(def view-type (reagent/atom :card-view))
(def mock-community-item-data ;; TODO: remove once communities are loaded with this data.
{:data {:community-color "#0052FF"
:status :gated
:locked? true
:cover (resources/get-image :community-cover)
:tokens [{:id 1
:group [{:id 1
:token-icon (resources/get-image :status-logo)}]}]
:tags [{:id 1
:tag-label (i18n/label :t/music)
:resource (resources/get-image :music)}
{:id 2
:tag-label (i18n/label :t/lifestyle)
:resource (resources/get-image :lifestyle)}
{:id 3
:tag-label (i18n/label :t/podcasts)
:resource (resources/get-image :podcasts)}]}})
(defn render-other-fn [community-item]
(let [item (merge community-item
(get mock-community-item-data :data)
{:featured false})]
(if (= @view-type :card-view)
[community-card/community-card-view-item item #(rf/dispatch [:navigate-to :community-overview item])]
[community-list/communities-list-view-item
{:on-press (fn []
(rf/dispatch [:communities/load-category-states (:id item)])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community {:community-id (:id item)}]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
;; TODO implement with quo2
[community/community-actions item])}])}
item])))
(defn render-featured-fn [community-item]
(let [item (merge community-item
(get mock-community-item-data :data)
{:featured true})]
[community-card/community-card-view-item item #(rf/dispatch [:navigate-to :community-overview item])]))
(defn get-item-layout-js [_ index]
#js {:length 64 :offset (* 64 index) :index index})
(defn screen-title []
[rn/view
{:height 56
:padding-vertical 12
:padding-horizontal 20}
[quo/text {:accessibility-label :communities-screen-title
:weight :semi-bold
:size :heading-1}
(i18n/label :t/discover-communities)]])
(defn featured-communities [communities]
[rn/flat-list
{:key-fn :id
:horizontal true
:getItemLayout get-item-layout-js
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:data communities
:render-fn render-featured-fn}])
(defn featured-communities-section [communities]
(let [count (reagent/atom {:value (count communities) :type :grey})]
[rn/view {:flex 1}
[rn/view {:flex-direction :row
:height 30
:padding-top 8
:justify-content :space-between
:padding-horizontal 20}
[rn/view {:flex-direction :row
:align-items :center}
[quo/text {:accessibility-label :featured-communities-title
:weight :semi-bold
:size :paragraph-1
:style {:margin-right 6}}
(i18n/label :t/featured)]
[quo/counter @count (:value @count)]]
[icons/icon :i/info {:container-style {:align-items :center
:justify-content :center}
:resize-mode :center
:size 20
:color (colors/theme-colors
colors/neutral-50
colors/neutral-40)}]]
[rn/view {:margin-top 8
:padding-left 20}
[featured-communities communities]]]))
(defn other-communities []
(let [communities (rf/sub [:communities/communities])
;;TODO move sorting to subscription
sorted-communities (sort-by :name communities)]
[rn/flat-list
{:key-fn :id
:getItemLayout get-item-layout-js
:keyboard-should-persist-taps :always
:shows-horizontal-scroll-indicator false
:header (featured-communities-section communities)
:data sorted-communities
:render-fn render-other-fn}]))
(defn discover []
[safe-area/consumer
(fn []
[rn/view {:style {:flex 1
:background-color (colors/theme-colors
colors/white
colors/neutral-90)}}
[quo/button {:icon true
:type :grey
:size 32
:style {:margin-vertical 12
:margin-left 20}
:on-press #(rf/dispatch [:navigate-back])}
:i/close]
[screen-title]
[other-communities]])])
@@ -0,0 +1,101 @@
(ns status-im2.contexts.communities.home.actions.view
(:require [i18n.i18n :as i18n]
[utils.re-frame :as rf]
[react-native.core :as rn]
[quo2.core :as quo]))
(defn hide-sheet-and-dispatch [event]
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(def not-joined-options
{:actions [{:icon :i/members
:label (i18n/label :t/view-members)}
{:icon :i/bullet-list
:right-icon :i/chevron-right
:label (i18n/label :t/view-community-rules)}
{:icon :i/add-user
:label (i18n/label :t/invite-contacts)}
{:icon :i/qr-code
:label (i18n/label :t/show-qr)}
{:icon :i/share
:label (i18n/label :t/share-community)}]})
(defn joined-options [id]
{:actions [{:icon :i/members
:accessibility-label :i/view-members
:label (i18n/label :t/view-members)
:on-press #(hide-sheet-and-dispatch [:navigate-to :community-members {:community-id id}])}
{:icon :i/bullet-list
:right-icon :i/chevron-right
:accessibility-label :view-community-rules
:label (i18n/label :t/view-community-rules)}
{:icon :i/up-to-date
:accessibility-label :mark-as-read
:label (i18n/label :t/mark-as-read)
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-in-community-pressed id])}
{:icon :i/muted
:accessibility-label :mute-community
:label (i18n/label :t/mute-community)
:right-icon :i/chevron-right}
{:icon :i/notifications
:accessibility-label :community-notification-settings
:label (i18n/label :t/community-notification-settings)
:right-icon :i/chevron-right}
{:icon :i/add-user
:accessibility-label :invite-people-from-contacts
:label (i18n/label :t/invite-people-from-contacts)
:on-press #(hide-sheet-and-dispatch [:communities/invite-people-pressed id])}
{:icon :i/qr-code
:accessibility-label :show-qr
:label (i18n/label :t/show-qr)}
{:icon :i/share
:accessibility-label :share-community
:label (i18n/label :t/share-community)
:on-press #(hide-sheet-and-dispatch [:communities/share-community-pressed id])}]})
(defn leave-sheet [community]
[rn/view {:style {:flex 1 :margin-left 20 :margin-right 20 :margin-bottom 20}}
[rn/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :space-between}}
[quo/text {:accessibility-label :communities-join-community
:weight :semi-bold
:size :heading-1}
(i18n/label :t/leave-community?)]]
;; TODO get tag image from community data
#_[quo/context-tag
{:style
{:margin-right :auto
:margin-top 8}}
(resources/get-image :status-logo) (:name community)]
[quo/text {:accessibility-label :communities-join-community
:size :paragraph-1
:style {:margin-top 16}}
(i18n/label :t/leave-community-message)]
[rn/view {:style {:margin-top 16
:margin-bottom 16
:flex 1
:flex-direction :row
:align-items :center
:justify-content :space-evenly}}
[quo/button {:on-press #(rf/dispatch [:bottom-sheet/hide])
:type :grey
:style {:flex 1
:margin-right 12}}
(i18n/label :t/cancel)]
[quo/button {:on-press #(hide-sheet-and-dispatch [:communities/leave (:id community)])
:style {:flex 1}}
(i18n/label :t/leave-community)]]])
(defn actions []
(let [community-mock (rf/sub [:get-screen-params :community-overview]) ;;TODO stop using mock data and only pass community id
community (rf/sub [:communities/community (:id community-mock)])]
[quo/action-drawer [(get (if (:joined community)
(joined-options (:id community))
not-joined-options) :actions)
(when (:joined community)
[{:icon :i/log-out
:label (i18n/label :t/leave-community)
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (constantly [leave-sheet community])
:content-height 300}])}])]]))
@@ -0,0 +1,15 @@
(ns status-im2.contexts.communities.home.style)
(def title-column
{:flex-direction :row
:align-items :center
:height 56
:padding-vertical 12
:margin-bottom 8
:padding-horizontal 20})
(def title-column-text
{:accessibility-label :communities-screen-title
:margin-right 6
:weight :semi-bold
:size :heading-1})

Some files were not shown because too many files have changed in this diff Show More