Compare commits

..
16 Commits
Author SHA1 Message Date
Vitaliy Vlasov cdbfc1ed1f overlay fix 2023-02-10 13:00:12 +02:00
Vitaliy Vlasov 63ead3d588 gomobile_src_override 2023-02-09 10:56:39 +02:00
Vitaliy Vlasov 5d2b0c026e use static lib 2023-01-23 16:21:29 +02:00
Vitaliy Vlasov 1083547561 Add tag to status-go builds
https://github.com/status-im/status-go/compare/7662cd61...5aad6fa0
2023-01-20 11:56:15 +02:00
Vitaliy Vlasov bf7d71d716 liblcproxy->libverifproxy 2023-01-09 17:58:35 +02:00
Vitaliy Vlasov 922c4d6128 Integrate status-go with nimbus-light-client
https://github.com/status-im/status-go/compare/7662cd61...756511d9
2022-12-23 20:20:46 +02:00
Vitaliy Vlasov 9ff1e054c9 Remove commented lines 2022-12-16 21:00:43 +02:00
Vitaliy Vlasov 6c79f158b3 Fix ios builds for x86 2022-12-16 20:41:47 +02:00
Vitaliy Vlasov ff0d042e60 Fix ios build for arm64 2022-12-16 16:42:09 +02:00
Vitaliy Vlasov 178d65795b Remove unneeded include flags, add --debuginfo:off to nim compiler
invocation
2022-12-14 20:13:40 +02:00
Vitaliy Vlasov 8e1e0a77c9 Use compiler flags directly instead of config.nims changes 2022-12-09 13:37:57 +02:00
Vitaliy Vlasov 7659c43372 Simplify build, fix clang fork issue 2022-12-08 21:47:32 +02:00
Vitaliy Vlasov 92b2f50630 Compilation fixes 2022-11-30 21:29:54 +02:00
Vitaliy Vlasov f84f0312af Fix libbacktrace build with seds, make -e 2022-11-28 12:49:19 +02:00
Vitaliy Vlasov 6a8035967f Separate Nim compiler derivation, miniupnpc fixes for Android 2022-11-22 13:17:00 +02:00
Vitaliy Vlasov 56a5570c20 Nix changes (initial) 2022-11-18 17:45:39 +02:00
207 changed files with 4306 additions and 6074 deletions
+1 -2
View File
@@ -2,13 +2,12 @@
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 utils.re-frame/defn]}
:linters {:invalid-arity {:skip-args [status-im.utils.fx/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
@@ -1,37 +0,0 @@
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,6 +175,3 @@ test/appium/tests/users.py
##node bindings
/bin/
/lib/
## visual tests
/artifacts
+1 -11
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 Android release builds
# Useful for Andoird 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,16 +313,6 @@ 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 or new_ui_medium\" \
-m \"new_ui_critical\" \
-k \"${params.KEYWORD_EXPRESSION}\" \
--apk=${params.APK_NAME}
"""
+1 -1
View File
@@ -640,7 +640,7 @@ SPEC CHECKSUMS:
FBLazyVector: 352a8ca9bbc8e2f097d680747a8c97ecef12d469
FBReactNativeSpec: 7dfb84f624136a45727c813ed21d130cd3e61beb
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
glog: 997518ea2aa2d8cd5df9797b641b758d52ecf2bc
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
+1
View File
@@ -14,6 +14,7 @@
status-go = {
src-override = null;
gomobile-src-override = null;
ipfs-gateway-url = "https://ipfs.status.im/";
};
};
+47 -11
View File
@@ -9,17 +9,47 @@ self: super:
let
inherit (super) stdenv stdenvNoCC callPackage;
in {
# Fix for MacOS
mkShell = super.mkShell.override { stdenv = stdenvNoCC; };
# Various utilities
utils = callPackage ./tools/utils.nix { };
lib = (super.lib or { }) // (import ./lib {
inherit (super) lib;
inherit (self) config;
});
gomobileSrcOverride = "/Users/vvlasov/c/mobile";
# Warning message about using local sources
localSrcWarn = (path: "Using local gomobile sources from ${path}");
localGomobileSrc = rec {
owner = "status-im";
repo = "mobile";
rev = "unknown";
shortRev = rev;
rawVersion = "develop";
cleanVersion = rawVersion;
goPackagePath = "github.com/${owner}/${repo}";
# We use builtins.path so that we can name the resulting derivation,
# Normally the name would not be deterministic, taken from the checkout directory.
src = builtins.path rec {
path = lib.traceValFn localSrcWarn gomobileSrcOverride;
name = "${repo}-source-${shortRev}";
# Keep this filter as restrictive as possible in order
# to avoid unnecessary rebuilds and limit closure size
filter = lib.mkFilter {
root = path;
include = [ ".*" ];
exclude = [
".*/[.]git.*" ".*[.]md" ".*[.]yml" ".*/.*_test.go$"
"VERSION" "_assets/.*" "build/.*"
".*/.*LICENSE.*" ".*/CONTRIB.*" ".*/AUTHOR.*"
];
};
};
};
in {
inherit lib;
# Fix for MacOS
mkShell = super.mkShell.override { stdenv = stdenvNoCC; };
# Various utilities
utils = callPackage ./tools/utils.nix { };
# Project dependencies
deps = {
clojure = callPackage ./deps/clojure { };
@@ -45,11 +75,17 @@ in {
buildGoPackage = super.buildGo118Package;
buildGoModule = super.buildGo118Module;
gomobile = (super.gomobile.overrideAttrs (old: {
patches = self.fetchurl { # https://github.com/golang/mobile/pull/84
url = "https://github.com/golang/mobile/commit/f20e966e05b8f7e06bed500fa0da81cf6ebca307.patch";
sha256 = "sha256-TZ/Yhe8gMRQUZFAs9G5/cf2b9QGtTHRSObBFD5Pbh7Y=";
};
})).override {
src = "/Users/vvlasov/c/mobile";
vendorSha256 = "sha256-TZ/Yhe8gMRQUZFAs9G5/cf2b9QGtTHRSObBFD5Pbh7Y=";
# patches = self.fetchurl { # https://github.com/golang/mobile/pull/84
# url = "https://github.com/golang/mobile/commit/f20e966e05b8f7e06bed500fa0da81cf6ebca307.patch";
# sha256 = "sha256-TZ/Yhe8gMRQUZFAs9G5/cf2b9QGtTHRSObBFD5Pbh7Y=";
# };
})).override rec {
buildGoModule = args: super.buildGoModule ( args // {
src = "/Users/vvlasov/c/mobile";
vendorSha256 = "sha256-C6GD3NMolRIve1siG8wpcQav7ZWTugjce8K22EQDD7M=";
});
# FIXME: No Android SDK packages for aarch64-darwin.
withAndroidPkgs = stdenv.system != "aarch64-darwin";
androidPkgs = self.androidEnvCustom.compose;
+3
View File
@@ -46,6 +46,9 @@ config=''
if [[ -n "${STATUS_GO_SRC_OVERRIDE}" ]]; then
config+="status-im.status-go.src-override=\"${STATUS_GO_SRC_OVERRIDE}\";"
fi
if [[ -n "${GOMOBILE_SRC_OVERRIDE}" ]]; then
config+="status-im.status-go.gomobile-src-override=\"${GOMOBILE_SRC_OVERRIDE}\";"
fi
config+="status-im.build-type=\"${BUILD_TYPE}\";"
if [[ -n "$config" ]]; then
+43 -1
View File
@@ -12,6 +12,7 @@ let
# Source can be changed with a local override from config
source = callPackage ./source.nix { };
nimbusSource = callPackage ./nimbus_source.nix { };
# Params to be set at build time, important for About section and metrics
goBuildParams = {
@@ -31,14 +32,55 @@ let
"-w" # -w disables DWARF debugging information
];
in rec {
inherit nimbusSource;
mobile = callPackage ./mobile {
inherit meta source goBuildLdFlags;
inherit meta source nimbusSource nimCompiler goBuildLdFlags;
};
library = callPackage ./library {
inherit meta source;
};
nimCompiler = callPackage ./mobile/buildNim.nix {
srcRaw = nimbusSource;
};
liblcproxy-android-arm = callPackage ./mobile/buildNimbus.nix {
srcRaw = nimbusSource;
nimCompiler = nimCompiler;
platform = "android";
arch = "arm";
};
liblcproxy-android-arm64 = callPackage ./mobile/buildNimbus.nix {
srcRaw = nimbusSource;
nimCompiler = nimCompiler;
platform = "android";
arch = "arm64";
};
liblcproxy-android-x86 = callPackage ./mobile/buildNimbus.nix {
srcRaw = nimbusSource;
nimCompiler = nimCompiler;
platform = "android";
arch = "x86";
};
liblcproxy-ios-x86 = callPackage ./mobile/buildNimbus.nix {
srcRaw = nimbusSource;
nimCompiler = nimCompiler;
platform = "ios";
arch = "x86";
};
liblcproxy-ios-arm64 = callPackage ./mobile/buildNimbus.nix {
srcRaw = nimbusSource;
nimCompiler = nimCompiler;
platform = "ios";
arch = "arm64";
};
shell = mkShell {
inputsFrom = [ mobile.android mobile.ios ];
};
+12 -4
View File
@@ -2,6 +2,7 @@
, androidPkgs, openjdk, gomobile, xcodeWrapper, removeReferencesTo
, meta
, source
, buildNimbusLc
, platform ? "android"
, platformVersion ? "23"
, targets ? [ "android/arm64" "android/arm" ]
@@ -13,7 +14,14 @@ let
inherit (lib) concatStringsSep optionalString optional;
isIOS = platform == "ios";
isAndroid = platform == "android";
lc = buildNimbusLc {inherit platform targets;};
cgoCflags = "-I" + (builtins.elemAt lc 0);
lcDirs = (builtins.concatStringsSep " " (builtins.map (s: "-L" + s) lc));
goBuildLdFlagsModified =
goBuildLdFlags ++ [("-extldflags \"-lverifproxy " + lcDirs + "\"")];
ldflags = concatStringsSep " " goBuildLdFlagsModified;
in buildGoPackage {
pname = source.repo;
version = "${source.cleanVersion}-${source.shortRev}-${platform}";
@@ -30,8 +38,6 @@ in buildGoPackage {
++ optional isAndroid openjdk
++ optional isIOS xcodeWrapper;
ldflags = concatStringsSep " " goBuildLdFlags;
ANDROID_HOME = optionalString isAndroid androidPkgs.sdk;
# Ensure XCode is present for iOS, instead of failing at the end of the build.
@@ -40,11 +46,13 @@ in buildGoPackage {
buildPhase = ''
runHook preBuild
echo -e "\nBuilding $pname for: ${concatStringsSep "," targets}"
echo -e "\n LC dirs: ${lcDirs}"
echo -e "\n ldflags: ${ldflags}"
set -x
export CGO_CFLAGS=\"${cgoCflags}\"
gomobile bind \
${concatStringsSep " " goBuildFlags} \
-ldflags="$ldflags" \
-ldflags ''\'${ldflags}''\' \
-target=${concatStringsSep "," targets} \
${optionalString isAndroid "-androidapi=${platformVersion}" } \
${optionalString isIOS "-iosversion=${platformVersion}" } \
+67
View File
@@ -0,0 +1,67 @@
{ pkgs, stdenv, lib, fetchFromGitHub
# Dependencies
, xcodeWrapper
, srcRaw
, writeScript
, writeTextFile
, androidPkgs
, git
, platform ? "android"
, arch ? "386"
, api ? "29" }:
let
osId = builtins.elemAt (builtins.split "\-" stdenv.hostPlatform.system) 2;
osArch = builtins.elemAt (builtins.split "\-" stdenv.hostPlatform.system) 0;
nimHostOs = if osId == "darwin" then "Darwin"
else if osId == "linux" then "Linux"
else "Windows_NT";
createNimbleLink = writeTextFile {
name = "createNimbleLink.sh";
text = ''
mkdir -p vendor/.nimble/pkgs
curdir=`pwd`
for dir in vendor/*/;
do
baseDirName=`basename ''${dir}`
dirName=vendor/.nimble/pkgs/$baseDirName-\#head
echo $dirName
mkdir -p $dirName
packageDir="''${curdir}/vendor/''${baseDirName}"
if [ -d "''${packageDir}/src" ]; then
packageDir="''${packageDir}/src"
fi
echo "''${packageDir}" > ''${dirName}/''${baseDirName}.nimble-link
echo "''${packageDir}" >> ''${dirName}/''${baseDirName}.nimble-link
done
'';
executable = true;
};
in stdenv.mkDerivation rec {
pname = "nimCompiler";
name = "nimCompiler";
src = srcRaw.src;
#version = lib.strings.substring 0 7 src.rev;
buildInputs = with pkgs; [ wget git clang which tcl curl];
phases = [ "unpackPhase" "buildPhase" "installPhase" ];
buildPhase = ''
${createNimbleLink}
export HOME=$PWD
unset SSL_CERT_FILE
make V=3 CC=clang build-nim
'';
installPhase = ''
mkdir -p $out
cp -r vendor/nimbus-build-system/vendor/Nim/* $out/
'';
}
+231
View File
@@ -0,0 +1,231 @@
{ pkgs, stdenv, lib, fetchFromGitHub
# Dependencies
, xcodeWrapper
, srcRaw
, writeScript
, writeTextFile
, androidPkgs
, git
, nimCompiler
, platform ? "android"
, arch ? "386"
, api ? "29" }:
let
osId = builtins.elemAt (builtins.split "\-" stdenv.hostPlatform.system) 2;
osArch = builtins.elemAt (builtins.split "\-" stdenv.hostPlatform.system) 0;
# Arg arch -> Nim arch
nimCpuMap = {
"x86" = "i386";
"x86-64" = "amd64";
"arm" = "arm";
"arm64" = "arm64";
};
iosArchMap = {
"x86" = "x86_64";
"x86-64" = "x86_64";
"arm" = "armv7";
"arm64" = "arm64";
};
nimCpu = if platform == "ios" && arch == "x86"
then "amd64" else "${lib.getAttr arch nimCpuMap}";
nimPlatform = "${(if platform == "ios" then "ios" else "android")}";
iosSdk = if arch == "x86" then "iphonesimulator" else "iphoneos";
iosArch = lib.getAttr arch iosArchMap;
isAndroid = lib.hasPrefix "android" platform;
isIOS = platform == "ios";
buildType = lib.getConfig "build-type" "";
routeHeader = builtins.readFile ./route.h;
PROJECT_ROOT = srcRaw.src;
iosIncludes = stdenv.mkDerivation {
name = "nim-status-ios-includes";
buildInputs = [ pkgs.coreutils ];
builder = writeScript "nim-ios-includes.sh"
''
export PATH=${pkgs.coreutils}/bin
mkdir $out
cd $out
mkdir net
echo "${routeHeader}" > net/route.h
'';
};
ANDROID_NDK_HOME = "${androidPkgs.sdk}/ndk-bundle";
androidToolchain = "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/${osId}-${osArch}";
androidTargetArchMap = {
"x86" = "i686-linux-android";
"x86-64" = "x86_64-linux-android";
"arm" = "armv7a-linux-androideabi";
"arm64" = "aarch64-linux-android";
};
androidTargetArch = lib.getAttr arch androidTargetArchMap;
iosVersion = "9.0";
sysroot = if isAndroid then "${androidToolchain}/sysroot" else "$(xcrun --sdk ${iosSdk} --show-sdk-path)";
compilerFlags = if isAndroid then
"--sysroot ${sysroot} -fPIC -target ${androidTargetArch}${api}"
else if isIOS then
# TODO The conditional for -miphoneos-version-min=8.0 is required,
# otherwise Nim will complain that thread-local storage is not supported for the current target
# when expanding 'NIM_THREADVAR' macro
"-isysroot ${sysroot} -fembed-bitcode -target ${iosArch}-apple-ios${iosVersion} ${if arch == "arm" then "" else "-miphoneos-version-min=${iosVersion}"} -I${iosIncludes}"
else throw "Unsupported platform!";
linkerFlags = if isAndroid then
"--sysroot ${sysroot} -target ${androidTargetArch}${api}"
else if isIOS then
"--sysroot ${sysroot} -fembed-bitcode -target ${iosArch}-apple-ios${iosVersion} ${if arch == "arm" then "" else "-miphoneos-version-min=${iosVersion}"} -v"
else throw "Unsupported platform!";
ldDirMap = {
"x86" = "i686";
"x86-64" = "x86_64";
"arm" = "armeabi-v7a";
"arm64" = "arm64-v8a";
};
cmakeArgs = if isAndroid then
"-DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=${api} -DCMAKE_ANDROID_ARCH_ABI=${lib.getAttr arch ldDirMap} -DCMAKE_ANDROID_NDK=${ANDROID_NDK_HOME}"
else if isIOS then "-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=\"$(CMAKE_SYSROOT)\" -DCMAKE_OSX_ARCHITECTURES=${iosArch} -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO -DCMAKE_IOS_INSTALL_COMBINED=YES"
else throw "Unsupported platform!";
#clangPath = if isAndroid then "${androidToolchain}/bin" else "";
#clangName = if isAndroid then "${androidTargetArch}${api}-clang" else "";
compilerVars = if isAndroid then
''
export PATH=${androidToolchain}/bin:$PATH
export CC=clang
export CXX=clang++
export AR=${androidToolchain}/bin/llvm-ar
export NM=${androidToolchain}/bin/llvm-nm
export RANLIB=${androidToolchain}/bin/llvm-ranlib
export LD=${androidToolchain}/bin/ld
export AS=$CC
export CFLAGS="${compilerFlags}"
export LDFLAGS="${linkerFlags}"
mkdir bin
touch bin/git
chmod +x bin/git
export PATH=./bin:$PATH
''
else if isIOS then
''
export PATH=${xcodeWrapper}/bin:$PATH
export CC=clang #$(xcrun --sdk ${iosSdk} --find clang)
export CXX=clang++ #$(xcrun --sdk ${iosSdk} --find clang++)
export LD=clang
export CFLAGS="${compilerFlags}"
export LDFLAGS="${linkerFlags}"
mkdir bin
touch bin/git
chmod +x bin/git
export PATH=./bin:$PATH
export CMAKE_SYSROOT=${sysroot}
''
else throw "Unsupported platform!";
src = srcRaw;
nimHostOs = if osId == "darwin" then "Darwin"
else if osId == "linux" then "Linux"
else "Windows_NT";
createNimbleLink = writeTextFile {
name = "createNimbleLink.sh";
text = ''
mkdir -p vendor/.nimble/pkgs
curdir=`pwd`
for dir in vendor/*/;
do
baseDirName=`basename ''${dir}`
dirName=vendor/.nimble/pkgs/$baseDirName-\#head
echo $dirName
mkdir -p $dirName
packageDir="''${curdir}/vendor/''${baseDirName}"
if [ -d "''${packageDir}/src" ]; then
packageDir="''${packageDir}/src"
fi
echo "''${packageDir}" > ''${dirName}/''${baseDirName}.nimble-link
echo "''${packageDir}" >> ''${dirName}/''${baseDirName}.nimble-link
done
'';
executable = true;
};
in stdenv.mkDerivation rec {
pname = "libverifproxy";
name = "libverifproxy";
src = srcRaw.src;
#version = lib.strings.substring 0 7 src.rev;
buildInputs = with pkgs; [ wget git which tcl cmake libtool binutils];
phases = [ "unpackPhase" "preBuildPhase" "buildPhase" "installPhase" ];
preBuildPhase = ''
sed -E -i 's|^(LIBBACKTRACE_SED := true.*)|\1\nCMAKE_ARGS := ${cmakeArgs}|g' vendor/nim-libbacktrace/Makefile
sed -E -i 's|^(.*)(useNews\* = )(.*)|\1\2 false|g' vendor/nim-json-rpc/json_rpc/clients/config.nim
sed -E -i 's|(.*XOPEN_SOURCE.*)|#\1|g' vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc/Makefile
export HOME=$PWD
${createNimbleLink}
${compilerVars}
export PATH=${nimCompiler}/bin:$PATH
#export PATH=${pkgs.binutils}/bin:$PATH
ln -sf ${pkgs.binutils}/bin/ar bin/ar
'';
buildPhase = ''
which ar
make V=3 OS=${nimHostOs} \
CC=clang CXX=clang USE_SYSTEM_NIM=1 \
NIMFLAGS="\
--passC:\"${compilerFlags}\" \
--passL:\"${linkerFlags}\" \
--debuginfo:off \
--cc:clang \
--listcmd \
--cpu:${nimCpu} \
--os:${nimPlatform} \
-d:disableMarchNative" \
libverifproxy
echo "### ls build/libverifproxy"
ls -l build/libverifproxy/*
'';
installPhase = ''
set -x
mkdir -p $out
cp libverifproxy* $out/
cp build/libverifproxy/verifproxy.h $out/
cp build/libverifproxy/nimbase.h $out/
'';
}
+31 -6
View File
@@ -1,19 +1,44 @@
{ callPackage, meta, source, goBuildLdFlags }:
{ stdenv, callPackage, meta, source, nimbusSource, nimCompiler, goBuildLdFlags }:
let
buildNimbusLc = { platform, targets }: builtins.map
(target:
let
arch =
if platform == "ios" then
(if target == "iossimulator" && stdenv.hostPlatform.isx86
then "x86" else "arm64")
else builtins.elemAt (builtins.split "\/" target) 2 ;
in
callPackage ./buildNimbus.nix {
inherit nimCompiler platform arch;
srcRaw = nimbusSource;
}
)
targets;
in {
#ios-x86 = buildNimbusLc {platform = "ios"; targets = ["ios" "iossimulator"];};
ios-x86 = buildNimbusLc {platform = "ios"; targets = ["iossimulator"];};
ios-arm = buildNimbusLc {platform = "ios"; targets = ["ios"];};
android-arm64 = buildNimbusLc {platform = "android"; targets = ["android/arm64"];};
android-arm = buildNimbusLc {platform = "android"; targets = ["android/arm"];};
{
android = callPackage ./build.nix {
platform = "android";
platformVersion = "23";
targets = [ "android/arm" "android/arm64" "android/386" ];
#targets = [ "android/arm" "android/arm64" "android/386" ];
targets = [ "android/arm64" ];
outputFileName = "status-go-${source.shortRev}.aar";
inherit meta source goBuildLdFlags;
inherit meta source buildNimbusLc goBuildLdFlags;
};
ios = callPackage ./build.nix {
platform = "ios";
platformVersion = "8.0";
targets = [ "ios" "iossimulator" ];
targets = [ "iossimulator" ];
outputFileName = "Statusgo.xcframework";
inherit meta source goBuildLdFlags;
inherit meta source buildNimbusLc goBuildLdFlags;
};
}
+259
View File
@@ -0,0 +1,259 @@
/*
* Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)route.h 8.3 (Berkeley) 4/19/94
* $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
*/
#ifndef _NET_ROUTE_H_
#define _NET_ROUTE_H_
#include <sys/appleapiopts.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
/*
* These numbers are used by reliable protocols for determining
* retransmission behavior and are included in the routing structure.
*/
struct rt_metrics {
u_int32_t rmx_locks; /* Kernel leaves these values alone */
u_int32_t rmx_mtu; /* MTU for this path */
u_int32_t rmx_hopcount; /* max hops expected */
int32_t rmx_expire; /* lifetime for route, e.g. redirect */
u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
u_int32_t rmx_rtt; /* estimated round trip time */
u_int32_t rmx_rttvar; /* estimated rtt variance */
u_int32_t rmx_pksent; /* packets sent using this route */
u_int32_t rmx_state; /* route state */
u_int32_t rmx_filler[3]; /* will be used for T/TCP later */
};
/*
* rmx_rtt and rmx_rttvar are stored as microseconds;
*/
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
#define RTF_UP 0x1 /* route usable */
#define RTF_GATEWAY 0x2 /* destination is a gateway */
#define RTF_HOST 0x4 /* host entry (net otherwise) */
#define RTF_REJECT 0x8 /* host or net unreachable */
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
#define RTF_DELCLONE 0x80 /* delete cloned route */
#define RTF_CLONING 0x100 /* generate new routes on use */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
#define RTF_LLINFO 0x400 /* DEPRECATED - exists ONLY for backward
* compatibility */
#define RTF_LLDATA 0x400 /* used by apps to add/del L2 entries */
#define RTF_STATIC 0x800 /* manually added */
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
#define RTF_WASCLONED 0x20000 /* route generated through cloning */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
/* 0x80000 unused */
#define RTF_PINNED 0x100000 /* future use */
#define RTF_LOCAL 0x200000 /* route represents a local address */
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
#define RTF_IFREF 0x4000000 /* route holds a ref to interface */
#define RTF_PROXY 0x8000000 /* proxying, no interface scope */
#define RTF_ROUTER 0x10000000 /* host is a router */
#define RTF_DEAD 0x20000000 /* Route entry is being freed */
/* 0x40000000 and up unassigned */
#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
#define RTF_BITS \
"\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \
"\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \
"\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \
"\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \
"\33IFREF\34PROXY\35ROUTER"
#define IS_DIRECT_HOSTROUTE(rt) \
(((rt)->rt_flags & (RTF_HOST | RTF_GATEWAY)) == RTF_HOST)
/*
* Routing statistics.
*/
struct rtstat {
short rts_badredirect; /* bogus redirect calls */
short rts_dynamic; /* routes created by redirects */
short rts_newgateway; /* routes modified by redirects */
short rts_unreach; /* lookups which failed */
short rts_wildcard; /* lookups satisfied by a wildcard */
short rts_badrtgwroute; /* route to gateway is not direct */
};
/*
* Structures for routing messages.
*/
struct rt_msghdr {
u_short rtm_msglen; /* to skip over non-understood messages */
u_char rtm_version; /* future binary compatibility */
u_char rtm_type; /* message type */
u_short rtm_index; /* index for associated ifp */
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
pid_t rtm_pid; /* identify sender */
int rtm_seq; /* for sender to identify action */
int rtm_errno; /* why failed */
int rtm_use; /* from rtentry */
u_int32_t rtm_inits; /* which metrics we are initializing */
struct rt_metrics rtm_rmx; /* metrics themselves */
};
struct rt_msghdr2 {
u_short rtm_msglen; /* to skip over non-understood messages */
u_char rtm_version; /* future binary compatibility */
u_char rtm_type; /* message type */
u_short rtm_index; /* index for associated ifp */
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
int32_t rtm_refcnt; /* reference count */
int rtm_parentflags; /* flags of the parent route */
int rtm_reserved; /* reserved field set to 0 */
int rtm_use; /* from rtentry */
u_int32_t rtm_inits; /* which metrics we are initializing */
struct rt_metrics rtm_rmx; /* metrics themselves */
};
#define RTM_VERSION 5 /* Up the ante and ignore older versions */
/*
* Message types.
*/
#define RTM_ADD 0x1 /* Add Route */
#define RTM_DELETE 0x2 /* Delete Route */
#define RTM_CHANGE 0x3 /* Change Metrics or flags */
#define RTM_GET 0x4 /* Report Metrics */
#define RTM_LOSING 0x5 /* RTM_LOSING is no longer generated by xnu
* and is deprecated */
#define RTM_REDIRECT 0x6 /* Told to use different route */
#define RTM_MISS 0x7 /* Lookup failed on this address */
#define RTM_LOCK 0x8 /* fix specified metrics */
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
#define RTM_NEWADDR 0xc /* address being added to iface */
#define RTM_DELADDR 0xd /* address being removed from iface */
#define RTM_IFINFO 0xe /* iface going up/down etc. */
#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
#define RTM_IFINFO2 0x12 /* */
#define RTM_NEWMADDR2 0x13 /* */
#define RTM_GET2 0x14 /* */
/*
* Bitmask values for rtm_inits and rmx_locks.
*/
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
#define RTV_EXPIRE 0x4 /* init or lock _expire */
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
#define RTV_RTT 0x40 /* init or lock _rtt */
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
/*
* Bitmask values for rtm_addrs.
*/
#define RTA_DST 0x1 /* destination sockaddr present */
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
#define RTA_IFP 0x10 /* interface name sockaddr present */
#define RTA_IFA 0x20 /* interface addr sockaddr present */
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
/*
* Index offsets for sockaddr array for alternate internal encoding.
*/
#define RTAX_DST 0 /* destination sockaddr present */
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
#define RTAX_NETMASK 2 /* netmask sockaddr present */
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
#define RTAX_IFP 4 /* interface name sockaddr present */
#define RTAX_IFA 5 /* interface addr sockaddr present */
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
#define RTAX_MAX 8 /* size of array to allocate */
struct rt_addrinfo {
int rti_addrs;
struct sockaddr *rti_info[RTAX_MAX];
};
#endif /* _NET_ROUTE_H_ */
+64
View File
@@ -0,0 +1,64 @@
{ utils, lib, fetchFromGitHub }:
let
inherit (lib) strings traceValFn importJSON getConfig;
srcOverride = getConfig "nimbus-eth1.src-override" null;
# Warning message about using local sources
localSrcWarn = (path: "Using local nimbus-eth1 sources from ${path}");
localSrc = rec {
owner = "status-im";
repo = "nimbus-eth1";
rev = "unknown";
shortRev = rev;
rawVersion = "develop";
cleanVersion = rawVersion;
goPackagePath = "github.com/${owner}/${repo}";
# We use builtins.path so that we can name the resulting derivation,
# Normally the name would not be deterministic, taken from the checkout directory.
src = builtins.path rec {
path = traceValFn localSrcWarn srcOverride;
name = "${repo}-source-${shortRev}";
# Keep this filter as restrictive as possible in order
# to avoid unnecessary rebuilds and limit closure size
filter = lib.mkFilter {
root = path;
include = [ ".*" ];
exclude = [
".*/[.]git.*" ".*[.]md" ".*[.]yml" ".*/.*_test.go$"
"VERSION" "_assets/.*" "build/.*"
".*/.*LICENSE.*" ".*/CONTRIB.*" ".*/AUTHOR.*"
];
};
};
};
githubSrc = let
owner = "status-im";
repo = "nimbus-eth1";
# Static lib
# rev = "211a0ed1e89bc836a79759e35db4a45f23a79b14";
# sha256 = "sha256-Z+PoQMoYJK9ort2ZiXE1oLeoNu2H44HHNnL4pbp+uI8=";
# Dynamic lib
rev = "1199e476397e271b889e54680dc632e47bc01dd6";
sha256 = "sha256-egx+I4h/V/56QRBtlaZffc3hrq7IaZCqL2Lm5XNqH1c=";
version = "0.1";
in rec {
inherit owner repo rev sha256 version;
shortRev = strings.substring 0 7 rev;
rawVersion = version;
cleanVersion = utils.sanitizeVersion version;
src = fetchFromGitHub {
inherit rev owner repo sha256;
name = "${repo}-${shortRev}-source-with-submodules";
fetchSubmodules = true;
};
};
in
if srcOverride != null
# If config.status-im.status-go.src-override is defined,
# instruct Nix to use that path to build status-go
then localSrc
# Otherwise grab it from the location defined by status-go-version.json
else githubSrc
+1 -4
View File
@@ -84,10 +84,7 @@
"@babel/preset-env": "7.1.0",
"@babel/register": "7.0.0",
"@mapbox/node-pre-gyp": "^1.0.9",
"@types/jest": "^28.1.6",
"detox": "^19.9.1",
"jest-image-snapshot": "^5.1.0",
"jest": "^28.1.3",
"jest": "^25.1.0",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
"process": "0.11.10",
+127 -161
View File
@@ -1,165 +1,131 @@
{
"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"
}
"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"
}
}
},
"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"
}
},
"meta": {
"hostname": "node-01.do-ams3.proxy.misc",
"timestamp": "2021-06-07T00:00:09.836740"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

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|status-im)')
INVALID_CHANGES=$(echo "$CHANGES" | grep -E '(re-frame/dispatch|rf/dispatch|re-frame/subscribe|rf/subscribe|rf/sub|<sub|>evt)')
if test -n "$INVALID_CHANGES"; then
echo "re-frame dispatch/subscribe and status-im are not allowed in quo/quo2 components"
echo "re-frame dispatch/subscribe is 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 test-ID]
accessibility-label loading border-radius style]
:or {theme :main
type :primary
haptic-feedback true
@@ -92,7 +92,7 @@
{:on-press-start (fn []
(optional-haptic)
(on-press-start))}))
[rn/view {:test-ID test-ID :style (merge (style-container type) style)}
[rn/view {:style (merge (style-container type) style)}
(when before
[rn/view
[icons/icon before {:color icon-color}]])
-44
View File
@@ -1,44 +0,0 @@
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();
})
});
+13 -11
View File
@@ -4,23 +4,25 @@
[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]}]
(let [container-size (get-in sizes [:container size])
(fn [{:keys [color size override-theme]}]
(let [theme (or override-theme (if (colors/dark?) :dark :light))
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 (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}]])))
: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}]])))
+7 -7
View File
@@ -122,20 +122,20 @@
first-initial-letter
initials)
"")]
[rn/view {:accessibility-label :user-avatar
:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
[rn/view {:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
(when (and ring? identicon?)
[icons/icon :i/identicon-ring {:size outer-dimensions
:no-color true}])
[icons/icon :main-icons/identicon-ring {:width outer-dimensions
:height outer-dimensions
: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}}
+2 -3
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 test-ID]
on-long-press accessibility-label icon icon-no-color style]
:or {type :primary
size 40}}
children]
@@ -197,8 +197,7 @@
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 {:test-ID test-ID
:disabled disabled
[rn/touchable-without-feedback (merge {:disabled disabled
:accessibility-label accessibility-label}
(when on-press
{:on-press (fn []
@@ -6,49 +6,10 @@
[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 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]}]
(defn communities-list-view-item [props {:keys [name locked? status notifications
tokens background-color]}]
[rn/view {:style (merge (style/community-card 16)
{:margin-bottom 12
:margin-horizontal 20})}
@@ -63,8 +24,8 @@
:padding-vertical 8
:background-color background-color}
[rn/view]
(when community-icon
[community-icon-view community-icon])
;;TODO new pure component based on quo2 should be implemented without status-im usage
;[communities.icon/community-icon-redesign community 32]]
[rn/view {:flex 1
:margin-horizontal 12}
[text/text {:weight :semi-bold
@@ -72,7 +33,7 @@
:accessibility-label :community-name-text
:number-of-lines 1
:ellipsize-mode :tail
:style {:color (when muted?
:style {:color (when (= notifications :muted)
(colors/theme-colors
colors/neutral-40
colors/neutral-60))}}
@@ -81,18 +42,28 @@
(if (= status :gated)
[community-view/permission-tag-container {:locked? locked?
:tokens tokens}]
[notification-view {:muted? muted?
:unread-mentions-count unread-mentions-count
:unread-messages? unread-messages?}])]]]])
(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)}}]
(defn communities-membership-list-item [props {:keys [name
muted?
unread-messages?
unread-mentions-count
status
community-icon
tokens
locked?]}]
(= 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?]}]
[rn/view {:margin-bottom 20}
[rn/touchable-highlight (merge {:underlay-color colors/primary-50-opa-5
:style {:border-radius 12}}
@@ -101,9 +72,8 @@
[rn/view {:flex-direction :row
:border-radius 16
:align-items :center}
(when community-icon
[community-icon-view community-icon])
;;TODO new pure component based on quo2 should be implemented without status-im usage
;[communities.icon/community-icon-redesign community 32]
[rn/view {:flex 1
:margin-left 12
:justify-content :center}
@@ -114,12 +84,8 @@
:weight :semi-bold
:size :paragraph-1}
name]]
[rn/view {:justify-content :center
:margin-right 16}
(if (= status :gated)
(when (= status :gated)
[rn/view {:justify-content :center
:margin-right 12}
[community-view/permission-tag-container {:locked? locked?
:tokens tokens}]
[notification-view {:muted? muted?
:unread-mentions-count unread-mentions-count
:unread-messages? unread-messages?}])]]]]])
:tokens tokens}]])]]]])
+53 -55
View File
@@ -9,6 +9,54 @@
(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)
@@ -17,60 +65,10 @@
: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]
[:<>
(doall
[:<> {:style
{:flex 1}}
(interpose
[divider]
(for [actions sections]
(doall
(map action actions))))])
(map action actions)))])
+1 -2
View File
@@ -30,5 +30,4 @@
(get-icons 12)
(get-icons 16)
(get-icons 20)
(get-icons 24)
(get-icons 32)))
(get-icons 24)))
@@ -1,40 +0,0 @@
(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)})
@@ -1,67 +0,0 @@
(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])])
@@ -1,39 +0,0 @@
(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)})
@@ -1,66 +0,0 @@
(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.string :as utils]))
[utils :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 test-ID]}]
on-press pass-through? icon-color-anim accessibility-label]}]
[:f>
(fn []
(let [icon-animated-style (reanimated/apply-animations-to-style
@@ -40,8 +40,7 @@
:height 40
:border-radius 10})]
[rn/touchable-without-feedback
{:test-ID test-ID
:on-press on-press
{: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,7 +63,6 @@
: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]
@@ -1,76 +0,0 @@
(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})
@@ -1,178 +0,0 @@
(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]]])
@@ -0,0 +1,157 @@
(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])]])
+3 -4
View File
@@ -3,8 +3,7 @@
[react-native.core :as rn]
[quo2.components.tabs.tab :as tab]
[reagent.core :as reagent]
[utils.number :as utils.number]
[utils.collection :as utils.collection]
[utils :as utils]
[quo2.foundations.colors :as colors]
[quo2.components.notifications.notification-dot :refer [notification-dot]]
[react-native.masked-view :as masked-view]
@@ -51,7 +50,7 @@
;; Truncate to avoid unnecessary rendering.
(if (> fade-percentage 0.99)
0.99
(utils.number/naive-round fade-percentage 2))))
(utils/naive-round fade-percentage 2))))
(defn scrollable-tabs
"Just like the component `tabs`, displays horizontally scrollable tabs with
@@ -121,7 +120,7 @@
:scroll-on-press?
:size)
(when scroll-on-press?
{:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)})
{:initial-scroll-index (utils/first-index #(= @active-tab-id (:id %)) data)})
{:ref #(reset! flat-list-ref %)
:extra-data (str @active-tab-id)
:horizontal true
+4 -18
View File
@@ -28,18 +28,12 @@
quo2.components.messages.gap
quo2.components.messages.system-message
quo2.components.reactions.reaction
quo2.components.notifications.activity-log.view
quo2.components.notifications.activity-logs
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.navigation.top-nav
quo2.components.navigation.floating-shell-button
quo2.components.tags.status-tags
quo2.components.navigation.page-nav
quo2.components.selectors.disclaimer))
quo2.components.tabs.account-selector))
(def button quo2.components.buttons.button/button)
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
@@ -56,16 +50,9 @@
(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)
@@ -83,7 +70,6 @@
(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
@@ -96,6 +82,6 @@
(def preview-list quo2.components.list-items.preview-list/preview-list)
;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-log.view/view)
(def activity-log quo2.components.notifications.activity-logs/activity-log)
(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)
+2 -7
View File
@@ -1,8 +1,7 @@
(ns react-native.core
(:require [reagent.core :as reagent]
["react-native" :as react-native]
[react-native.flat-list :as flat-list]
[react-native.section-list :as section-list]))
[react-native.flat-list :as flat-list]))
(def app-state ^js (.-AppState ^js react-native))
@@ -10,7 +9,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)))
@@ -18,8 +17,6 @@
(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)))
@@ -51,5 +48,3 @@
(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,9 +27,6 @@
(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) #()))
+1 -9
View File
@@ -2,9 +2,8 @@
(: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 withRepeat Easing Keyframe)]))
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring Easing Keyframe)]))
;; Animated Components
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
@@ -13,8 +12,6 @@
(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)
@@ -24,7 +21,6 @@
(def with-delay withDelay)
(def with-spring withSpring)
(def key-frame Keyframe)
(def with-repeat withRepeat)
;; Easings
(def bezier (.-bezier ^js Easing))
@@ -72,7 +68,3 @@
(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
@@ -1,40 +0,0 @@
(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})])
+29 -80
View File
@@ -6,26 +6,6 @@
[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
@@ -38,7 +18,8 @@
~excessively~ big, this implementation will probably need to be revisited."
[db-notifications new-notifications]
(reduce (fn [acc {:keys [id type read] :as notification}]
(let [remove-notification (fn [data]
(let [filter-status (if read :read :unread)
remove-notification (fn [data]
(remove #(= id (:id %)) data))
insert-and-sort (fn [data]
(->> notification
@@ -46,17 +27,14 @@
(sort-by (juxt :timestamp :id))
reverse))]
(as-> acc $
(update-in $ [type :all :data] remove-notification)
(update-in $ [types/no-type :all :data] remove-notification)
(update-in $ [type :read :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))
$
(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))))))
(-> $ (update-in [type filter-status :data] insert-and-sort)
(update-in [types/no-type filter-status :data] insert-and-sort))))))
db-notifications
new-notifications))
@@ -67,69 +45,38 @@
{:db (update-in db [:activity-center :notifications]
update-notifications new-notifications)}))
(fx/defn notifications-reconcile-from-response
{:events [:activity-center/reconcile-notifications-from-response]}
;;;; 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]}
[cofx response]
(->> response
:activityCenterNotifications
(map data-store.activities/<-rpc)
(notifications-reconcile cofx)))
;;;; 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
%])}]})
(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)
;;;; Notifications fetching and pagination
(def defaults
{:filter-status :unread
:filter-type types/no-type
;; 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})
:notifications-per-page 10})
(def start-or-end-cursor
"")
@@ -139,13 +86,15 @@
(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
+269 -219
View File
@@ -3,11 +3,10 @@
[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-im2.setup.config :as config]))
[status-im.utils.config :as config]))
(defn setup []
(h/register-helper-events)
@@ -15,140 +14,87 @@
;;;; 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 "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}))))
(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}]}))
(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}))))
(h/spy-fx spy-queue ::json-rpc/call)
(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}))))
(rf/dispatch [:activity-center.contact-verification/decline contact-verification-id])
(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}))))
(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))))))))))
;;;; Notification reconciliation
@@ -158,12 +104,12 @@
(rf-test/run-test-sync
(setup)
(let [notifications {types/one-to-one-chat
{:all {:cursor ""
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}
{:id "0x2"
:read false
:read true
:type types/one-to-one-chat}]}
:unread {:cursor ""
:data [{:id "0x3"
@@ -183,112 +129,216 @@
(testing "removes dismissed or accepted notifications"
(rf-test/run-test-sync
(setup)
(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 [: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}]}}}])
(rf/dispatch [:activity-center.notifications/reconcile
[(assoc notif-1 :dismissed true)
(assoc notif-3 :accepted true)
(assoc notif-4 :dismissed true)
notif-5]])
(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}]])
(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]))))))
(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])))))
(testing "replaces old notifications with newly arrived ones"
(rf-test/run-test-sync
(setup)
(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 [: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}]}}}])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1 new-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}]])
(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]))))))
(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])))))
(testing "reconciles notifications that switched their read/unread status"
(rf-test/run-test-sync
(setup)
(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 [:test/assoc-in [:activity-center :notifications]
{types/one-to-one-chat
{:read {:cursor ""
:data [{:id "0x1"
:read true
:type types/one-to-one-chat}]}}}])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1]])
(rf/dispatch [:activity-center.notifications/reconcile
[{:id "0x1"
:read false
:type types/one-to-one-chat}]])
(is (= {types/no-type
{:all {:data [new-notif-1]}
:unread {:data [new-notif-1]}}
(is (= {types/no-type
{:read {:data []}
:unread {:data [{:id "0x1"
:read false
:type types/one-to-one-chat}]}}
types/one-to-one-chat
{:all {:cursor "" :data [new-notif-1]}
:unread {:data [new-notif-1]}}}
(get-in (h/db) [:activity-center :notifications]))))))
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])))))
;; 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)
(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 [: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}]}}}])
(rf/dispatch [:activity-center.notifications/reconcile [new-notif-1 new-notif-4]])
(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 {}}]])
(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]))))))))
(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])))))))
;;;; Notifications fetching and pagination
@@ -406,12 +456,12 @@
(let [spy-queue (atom [])]
(h/spy-fx spy-queue ::json-rpc/call)
(rf/dispatch [:test/assoc-in [:activity-center :filter :status]
:all])
:read])
(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 :all :cursor]
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :read :cursor]
"10"])
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :all :loading?]
(rf/dispatch [:test/assoc-in [:activity-center :notifications types/one-to-one-chat :read :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 10)
(def ^:const contact-verification 6)
;; 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 [:communities/join]}
{:events [::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 [:communities/leave]}
[{:keys [db]} community-id]
{:events [::leave]}
[{:keys [db] :as cofx} 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 [:communities/invite-people-pressed]}
{:events [::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 [:communities/share-community-pressed]}
{:events [::share-community-pressed]}
[cofx id]
(fx/merge cofx
(reset-community-id-input id)
+6 -7
View File
@@ -21,13 +21,12 @@
(def ^:const contact-request-state-received 3)
(def ^:const contact-request-state-dismissed 4)
(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 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 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-im2.setup.config :as config]))
[status-im.utils.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-im2.setup.config :as config]))
[status-im.utils.config :as config]))
(def chat-id
"0x04c66155")
@@ -13,7 +13,7 @@
(def raw-notification
{:chatId chat-id
:contactVerificationStatus constants/contact-verification-status-pending
:contactVerificationStatus constants/contact-verification-state-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-status-pending}
:contact-verification-status constants/contact-verification-state-pending}
(-> raw-notification
store/<-rpc
(dissoc :last-message :message :reply-message)))))
-1
View File
@@ -46,7 +46,6 @@
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
:setup/open-multiaccounts #(re-frame/dispatch [:setup/initialize-multiaccounts % {:logout? logout?}])}
::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])}
(keychain/save-auth-method key-uid auth-method)
(wallet/clear-timeouts)
(init/initialize-app-db))))
-444
View File
@@ -1,444 +0,0 @@
(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]))}))
+20 -19
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))
waku-nodes (:waku-nodes current-fleet)
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))
wakuv2-nodes (into (vals (:waku current-fleet)) (vals (get wakuv2-config :CustomNodes)))
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,8 +124,9 @@
(into (pick-nodes 2
(vals (:whisper current-fleet)))
(vals (:static current-fleet))))
:RendezvousNodes (if wakuv2-enabled [] rendezvous-nodes)
:WakuNodes (or waku-nodes [])})
:RelayNodes wakuv2-nodes
:StoreNodes wakuv2-nodes
:RendezvousNodes (if wakuv2-enabled [] rendezvous-nodes)})
:always
(assoc :LocalNotificationsConfig {:Enabled true}
@@ -134,10 +135,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)
@@ -173,8 +174,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
@@ -1,11 +1,9 @@
(ns status-im2.contexts.shell.animation
(ns status-im.switcher.animation
(:require [re-frame.core :as re-frame]
[react-native.reanimated :as reanimated]
[quo2.foundations.colors :as colors]
[status-im2.contexts.shell.constants :as constants]
;;TODO remove when not used anymore
[status-im.async-storage.core :as async-storage]))
[status-im.async-storage.core :as async-storage]
[status-im.switcher.constants :as constants]))
;;;; Bottom Tabs & Home Stack Animations
@@ -1,10 +1,10 @@
(ns status-im2.contexts.shell.bottom-tabs
(:require [reagent.core :as reagent]
(ns status-im.switcher.bottom-tabs
(:require [quo.react-native :as rn]
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[react-native.core :as rn]
[status-im2.contexts.shell.style :as styles]
[status-im2.contexts.shell.constants :as constants]
[status-im2.contexts.shell.animation :as animation]
[status-im.switcher.styles :as styles]
[status-im.switcher.constants :as constants]
[status-im.switcher.animation :as animation]
[quo2.components.navigation.bottom-nav-tab :as bottom-nav-tab]))
;; Reagent atoms used for lazily loading home screen tabs
@@ -38,8 +38,7 @@
(defn bottom-tab [icon stack-id shared-values]
[bottom-nav-tab/bottom-nav-tab
{:test-ID stack-id
:icon icon
{:icon icon
:icon-color-anim (get
shared-values
(get constants/tabs-icon-color-keywords stack-id))
@@ -1,20 +1,24 @@
(ns status-im2.contexts.shell.constants
(:require [react-native.platform :as platform]
[utils.re-frame :as rf]
[react-native.core :as rn]))
(ns status-im.switcher.constants
(:require [quo.react-native :as rn]
[reagent.core :as reagent]
[status-im.utils.handlers :refer [<sub]]
[status-im.utils.platform :as platform]))
(def shell-animation-time 200)
(defn bottom-tabs-container-height []
(if platform/android? 57 82))
(defn bottom-tabs-extended-container-height []
(if platform/android? 90 120))
(defn status-bar-offset []
(if platform/android? (.-currentHeight ^js rn/status-bar) 0))
;; status bar height is not included in : the dimensions/window for devices with a notch
;; https://github.com/facebook/react-native/issues/23693#issuecomment-662860819
(defn dimensions []
(let [{:keys [width height]} (rf/sub [:dimensions/window])]
(let [{:keys [width height]} (<sub [:dimensions/window])]
{:width width
:height (if (> (status-bar-offset) 28)
(+ height (status-bar-offset))
@@ -39,3 +43,5 @@
:chats-stack :chats-tab-icon-opacity
:wallet-stack :wallet-tab-icon-opacity
:browser-stack :browser-tab-icon-opacity})
(def pass-through? (reagent/atom false))
@@ -1,14 +1,12 @@
(ns status-im2.contexts.shell.home-stack
(:require [react-native.reanimated :as reanimated]
[status-im2.contexts.shell.style :as styles]
[status-im2.contexts.shell.constants :as constants]
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
[status-im2.contexts.communities.home.view :as communities]
;; TODO move to status-im2
(ns status-im.switcher.home-stack
(:require [status-im.switcher.styles :as styles]
[react-native.reanimated :as reanimated]
[status-im.switcher.constants :as constants]
[status-im.ui2.screens.chat.home :as chat.home]
[status-im.switcher.bottom-tabs :as bottom-tabs]
[status-im.ui.screens.profile.user.views :as profile.user]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
[status-im.ui2.screens.chat.home :as chat.home]))
[status-im.ui2.screens.communities.communities-home :as communities-home]))
(defn load-stack? [stack-id]
(case stack-id
@@ -32,7 +30,7 @@
:right 0
:accessibility-label stack-id})}
(case stack-id
:communities-stack [communities/home]
:communities-stack [communities-home/views]
:chats-stack [chat.home/home]
:wallet-stack [wallet.accounts/accounts-overview]
:browser-stack [profile.user/my-profile])])]))
+54
View File
@@ -0,0 +1,54 @@
(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
@@ -0,0 +1,24 @@
(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,7 +1,7 @@
(ns status-im2.contexts.shell.style
(ns status-im.switcher.styles
(:require [quo2.foundations.colors :as colors]
[status-im2.contexts.shell.constants :as constants]
[react-native.platform :as platform]))
[status-im.utils.platform :as platform]
[status-im.switcher.constants :as constants]))
;; Bottom Tabs
(defn bottom-tabs-container [pass-through?]
@@ -1,4 +1,4 @@
(ns status-im2.contexts.shell.cards.style
(ns status-im.switcher.switcher-cards.styles
(:require [quo2.foundations.colors :as colors]))
(def colors-map
@@ -1,6 +1,5 @@
(ns status-im2.contexts.shell.cards.view
(:require [i18n.i18n :as i18n]
[react-native.core :as rn]
(ns status-im.switcher.switcher-cards.switcher-cards
(:require [react-native.core :as rn]
[react-native.fast-image :as fast-image]
[quo2.foundations.colors :as colors]
[quo2.components.markdown.text :as text]
@@ -11,26 +10,27 @@
[quo2.components.avatars.group-avatar :as group-avatar]
[quo2.components.list-items.preview-list :as preview-list]
[quo2.components.avatars.channel-avatar :as channel-avatar]
[status-im2.contexts.shell.cards.style :as style]))
[status-im.switcher.switcher-cards.styles :as styles]
[status-im.i18n.i18n :as i18n]))
(defn content-container [{:keys [content-type data new-notifications? color-50]}]
[rn/view {:style (style/content-container new-notifications?)}
[rn/view {:style (styles/content-container new-notifications?)}
(case content-type
:text [text/text (style/last-message-text-props) data]
:text [text/text (styles/last-message-text-props) data]
:photo [preview-list/preview-list {:type :photo
:more-than-99-label (i18n/label :counter-99-plus)
:size 24
:override-theme :dark} data]
:sticker [fast-image/fast-image {:source (:source data)
:style (style/sticker)}]
:style (styles/sticker)}]
:gif [fast-image/fast-image {:source (:source data)
:style (style/gif)}]
:style (styles/gif)}]
:channel [rn/view {:style {:flex-direction :row
:align-items :center}}
[channel-avatar/channel-avatar
{:emoji (:emoji data)
:emoji-background-color (colors/alpha color-50 0.1)}]
[text/text (style/community-channel-props) (:channel-name data)]]
[text/text (styles/community-channel-props) (:channel-name data)]]
:community-info (case (:type data)
:pending [status-tags/status-tag
{:status :pending
@@ -47,12 +47,12 @@
[:<>])])
(defn notification-container [{:keys [notification-indicator counter-label color-60]}]
[rn/view {:style (style/notification-container)}
[rn/view {:style (styles/notification-container)}
(if (= notification-indicator :counter)
[counter/counter {:outline false
:override-text-color colors/white
:override-bg-color color-60} counter-label]
[rn/view {:style (style/unread-dot color-60)}])])
[rn/view {:style (styles/unread-dot color-60)}])])
(defn bottom-container [{:keys [new-notifications?] :as content}]
[:<>
@@ -71,7 +71,7 @@
:size :large
:override-theme :dark}]
:community-card [fast-image/fast-image {:source (:source avatar-params)
:style (style/community-avatar)}]))
:style (styles/community-avatar)}]))
(defn subtitle [{:keys [content-type data]}]
(case content-type
@@ -92,18 +92,18 @@
(let [color-50 (colors/custom-color customization-color 50)
color-60 (colors/custom-color customization-color 60)]
[rn/touchable-without-feedback {:on-press on-press}
[rn/view {:style (style/base-container color-50)}
[rn/view {:style (styles/base-container color-50)}
(when banner
[rn/image {:source (:source banner)
:style {:width 160}}])
[rn/view {:style (style/secondary-container)}
[text/text (style/title-props) title]
[text/text (style/subtitle-props) (subtitle content)]
[rn/view {:style (styles/secondary-container)}
[text/text (styles/title-props) title]
[text/text (styles/subtitle-props) (subtitle content)]
[bottom-container (merge {:color-50 color-50 :color-60 color-60} content)]]
(when avatar
[rn/view {:style (style/avatar-container)}
[rn/view {:style (styles/avatar-container)}
[avatar avatar-params type customization-color]])
[button/button (style/close-button-props on-close) :i/close]]]))
[button/button (styles/close-button-props on-close) :i/close]]]))
;; browser Card
(defn browser-card [_]
+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-im2.setup.config :as config]
[status-im.utils.config :as config]
[status-im.contact.core :as models.contact]
[status-im.communities.core :as models.communities]
[status-im.pairing.core :as models.pairing]
+29 -1
View File
@@ -2,7 +2,22 @@
(: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]))
[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})
(def action-button-container-old
{:position :absolute
@@ -29,6 +44,19 @@
"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
@@ -1,11 +0,0 @@
(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})
@@ -1,59 +0,0 @@
(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))])))
@@ -1,11 +0,0 @@
(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})
@@ -1,109 +0,0 @@
(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}])})})))])))))
@@ -1,9 +0,0 @@
(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})
@@ -1,28 +0,0 @@
(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})
@@ -1,6 +0,0 @@
(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,32 +1,154 @@
(ns status-im.ui.screens.activity-center.views
(:require [quo.components.safe-area :as safe-area]
(:require [quo.components.animated.pressable :as animation]
[quo.react :as react]
[quo.react-native :as rn]
[quo2.core :as quo2]
[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.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.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]))
[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]])
(defn filter-selector-read-toggle
[]
(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)}])}
(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)}])}
:i/unread]))
;; TODO(@ilmotta,2022-10-07): The empty state is still under design analysis, so we
;; TODO(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
@@ -39,24 +161,24 @@
:height 120
:margin-bottom 20
:width 120}}]
[quo2/text {:size :paragraph-1
[text/text {:size :paragraph-1
:style {:padding-bottom 2}
:weight :semi-bold}
"No notifications"]
[quo2/text {:size :paragraph-2}
[text/text {:size :paragraph-2}
"Your notifications will be here"]])
(defn tabs
[]
(let [filter-type (rf/sub [:activity-center/filter-type])]
[quo2/scrollable-tabs {:size 32
(let [filter-type (<sub [:activity-center/filter-type])]
[tabs/scrollable-tabs {:size 32
:blur? true
:override-theme :dark
:style style/tabs
:style {:padding-left 20}
:fade-end-percentage 0.79
:scroll-on-press? true
:fade-end? true
:on-change #(rf/dispatch [:activity-center.notifications/fetch-first-page {:filter-type %}])
:on-change #(>evt [:activity-center.notifications/fetch-first-page {:filter-type %}])
:default-active filter-type
:data [{:id types/no-type
:label (i18n/label :t/all)}
@@ -81,16 +203,19 @@
[]
(let [screen-padding 20]
[rn/view
[quo2/button {:icon true
:type :blur-bg
:size 32
:override-theme :dark
:style style/header-button
:on-press #(rf/dispatch [:hide-popover])}
[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])}
:i/close]
[quo2/text {:size :heading-1
[text/text {:size :heading-1
:weight :semi-bold
:style style/header-heading}
:style {:padding-horizontal screen-padding
:padding-vertical 12
:color colors/white}}
(i18n/label :t/notifications)]
[rn/view {:flex-direction :row
:padding-vertical 12}
@@ -102,30 +227,22 @@
: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 (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)}
(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}}
[header]
[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}]]))])
[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}]]))])
@@ -1,13 +1,12 @@
(ns status-im.ui.screens.bottom-sheets.views
(:require [quo.core :as quo]
(:require [status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[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.multiaccounts.recover.views :as recover.views]))
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[quo.core :as quo]))
(defn bottom-sheet []
(let [{:keys [show? view options]} @(re-frame/subscribe [:bottom-sheet])
@@ -28,9 +27,6 @@
(= 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)
@@ -44,4 +40,4 @@
(merge key-storage/migrate-account-password))]
[quo/bottom-sheet opts
(when content
[content (when options options)])]))
[content (when options options)])]))
@@ -1,77 +0,0 @@
(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,7 +4,6 @@
[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
@@ -19,17 +18,16 @@
chat-id]
connected? [:mailserver/connected?]
use-status-nodes? [:mailserver/use-status-nodes?]
first-gap? (= gap-ids #{:first-gap})
window-height [:dimensions/window-height]]
first-gap? (= gap-ids #{:first-gap})]
(when (or (not first-gap?) public? community?)
[react/view {:style (when-not in-progress? style/gap-container)}
[react/view {:style (style/gap-container)}
[react/touchable-highlight
{:on-press (when (and (not in-progress?) use-status-nodes? connected?)
(on-press chat-id gap-ids))
:style {:height (if in-progress? window-height 48)}}
:style style/touchable}
[react/view {:style style/label-container}
(if in-progress?
[messages-skeleton/messages-skeleton window-height]
[react/activity-indicator]
[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,29 +1,28 @@
(ns status-im.ui.screens.communities.community
(: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]
(:require [status-im.ui.components.topbar :as topbar]
[quo.react-native :as rn]
[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]
[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]))
[quo2.components.community.style :as styles]))
(def request-cooldown-ms (* 24 60 60 1000))
@@ -62,8 +61,8 @@
(i18n/label :t/open-membership))]]]))
(defn hide-sheet-and-dispatch [event]
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(>evt [:bottom-sheet/hide])
(>evt 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))
@@ -88,14 +87,14 @@
:title (i18n/label :t/invite-people)
:icon :main-icons/share
:accessibility-label :community-invite-people
:on-press #(rf/dispatch [:communities/invite-people-pressed id])}])
:on-press #(>evt [::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 #(rf/dispatch [:communities/share-community-pressed id])}])]))
:on-press #(>evt [::communities/share-community-pressed id])}])]))
(defn community-actions [{:keys [id name images color can-manage-users?]}]
(let [thumbnail-image (get-in images [:thumbnail :uri])]
@@ -154,13 +153,13 @@
;; unread indicator
(assoc home-item :public? true)
{:on-press (fn []
(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])}])}])
(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])}])}])
(defn categories-accordion [community-id chats categories data]
[:<>
@@ -168,8 +167,8 @@
^{:key (str "cat" name id)}
[:<>
[accordion/section
{:on-open #(rf/dispatch [::communities/store-category-state community-id id true])
:on-close #(rf/dispatch [::communities/store-category-state community-id id false])
{:on-open #(>evt [::communities/store-category-state community-id id true])
:on-close #(>evt [::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}]
@@ -181,7 +180,7 @@
[quo/separator]])])
(defn community-chat-list [community-id categories from-chat]
(let [chats (rf/sub [:chats/sorted-categories-by-community-id community-id])]
(let [chats (<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
@@ -231,25 +230,25 @@
:render-fn channel-preview-item}]))
(defn unknown-community [community-id]
(let [fetching (rf/sub [:communities/fetching-community community-id])]
(let [fetching (<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 #(rf/dispatch [::link-preview/resolve-community-info community-id]))
[quo/button {:on-press (when-not fetching #(>evt [::link-preview/resolve-community-info community-id]))
:disabled fetching
:color :secondary}
:color :secondary}
(if fetching
[react/small-loading-indicator]
[components.react/small-loading-indicator]
(i18n/label :t/fetch-community))]]]))
(defn community []
(let [{:keys [community-id from-chat]} (rf/sub [:get-screen-params])]
(let [{:keys [community-id from-chat]} (<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} (rf/sub [:communities/community community-id])
categories (rf/sub [:communities/sorted-categories community-id])]
:as community} (<sub [:communities/community community-id])
categories (<sub [:communities/sorted-categories community-id])]
(if community
[rn/view {:style {:flex 1}}
[topbar/topbar
@@ -265,24 +264,24 @@
(when (or admin joined)
[{:icon :main-icons/more
:accessibility-label :community-menu-button
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[community-actions community])}])}])}]
:on-press #(>evt [: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 #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[community-plus-actions community])}])
{:on-press #(>evt [: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 #(rf/dispatch [:communities/join id])
:center [quo/button {:on-press #(>evt [::communities/join id])
:type :secondary}
(i18n/label :t/join)]}]
can-request-access?
@@ -293,13 +292,13 @@
:left [quo/text {:color :secondary} (i18n/label :t/membership-request-pending)]}]
[toolbar/toolbar
{:show-border? true
:center [quo/button {:on-press #(rf/dispatch [::communities/request-to-join id])
:center [quo/button {:on-press #(>evt [::communities/request-to-join id])
:type :secondary}
(i18n/label :t/request-access)]}])
:else
[toolbar/toolbar
{:show-border? true
:center [quo/button {:on-press #(rf/dispatch [:communities/join id])
:center [quo/button {:on-press #(>evt [::communities/join id])
:type :secondary}
(i18n/label :t/follow)]}]))]
[unknown-community community-id])))))
@@ -0,0 +1,89 @@
(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}])}])}]))
@@ -0,0 +1,171 @@
(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,7 +21,6 @@
[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,7 +73,6 @@
: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
@@ -0,0 +1,132 @@
(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,3 +159,15 @@
: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]]]])
+8 -3
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-im2.setup.config :as config]
[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.screen :as chat-icon.screen]
@@ -234,7 +234,7 @@
(views/defview plus-button []
(views/letsubs [logging-in? [:multiaccounts/login]]
[components.plus-button/plus-button-old
[components.plus-button/plus-button
{:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
:loading logging-in?
@@ -259,7 +259,12 @@
:on-press #(do
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
(if config/new-activity-center-enabled?
(re-frame/dispatch [:activity-center/open])
(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 [: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,8 +234,7 @@
:height 110}}])]]]
[react/view {:margin-bottom 50}
[quo/button
{:test-id :generate-new-key
:on-press #(re-frame/dispatch [:keycard.recovery.no-key.ui/generate-key-pressed])}
{: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 {:test-ID :terms-of-service :on-press #(swap! tos-accepted not)}
[rn/touchable-opacity {: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,8 +167,7 @@
" "
(i18n/label :t/terms-of-service)]]]]
[react/view {:style {:margin-bottom 24}}
[quo/button {:test-ID :get-started
:disabled (not @tos-accepted)
[quo/button {:disabled (not @tos-accepted)
:on-press #(do (re-frame/dispatch [:init-root :onboarding])
;; clear atom state for next use
(reset! tos-accepted false)
@@ -83,8 +83,7 @@
[react/view {:style {:align-items :center}}
[react/view {:style (assoc styles/bottom-button :margin-bottom 16)}
[quo/button
{:test-ID :generate-keys
;:disabled existing-account?
{;:disabled existing-account?
:on-press #(re-frame/dispatch [:generate-and-derive-addresses])
:accessibility-label :onboarding-next-button}
(i18n/label :t/generate-a-key)]]
@@ -44,8 +44,7 @@
(i18n/label :intro-wizard-title-alt4)]
[rn/view
[rn/view {:style {:padding 16}}
[quo/text-input {:test-ID :password-placeholder
:secure-text-entry true
[quo/text-input {:secure-text-entry true
:auto-capitalize :none
:auto-focus true
:show-cancel false
@@ -57,8 +56,7 @@
(some-> ^js @confirm-ref .focus))}]]
[rn/view {:style {:padding 16
:opacity (if-not valid-password 0.33 1)}}
[quo/text-input {:test-ID :confirm-password-placeholder
:secure-text-entry true
[quo/text-input {:secure-text-entry true
:get-ref #(reset! confirm-ref %)
:auto-capitalize :none
:show-cancel false
+7 -4
View File
@@ -18,6 +18,7 @@
[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]
@@ -114,8 +115,7 @@
[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.ui2.screens.chat.group-details.view :as group-details]))
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]))
(defn right-button-options [id icon]
{:id id
@@ -212,9 +212,10 @@
:component pin-messages/pinned-messages}
{:name :group-chat-profile
:insets {:top false}
;;TODO animated-header
:options {:topBar {:visible false}}
:component group-details/group-details}
:component profile.group-chat/group-chat-profile}
{:name :group-chat-invite
;;TODO parameter in the event
:options {:topBar {:visible false}}
@@ -306,7 +307,9 @@
{: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
+56 -88
View File
@@ -3,24 +3,22 @@
[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? add-divider?]}]
(defn- entry [{:keys [icon label on-press danger? sub-label chevron?]}]
{: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)
:add-divider? add-divider?})
{:icon icon
:label label
:on-press on-press
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)})
(defn hide-sheet-and-dispatch [event]
(rf/dispatch [:bottom-sheet/hide])
@@ -42,40 +40,14 @@
(defn unmute-chat-action [chat-id]
(hide-sheet-and-dispatch [::chat.models/mute-chat-toggled chat-id false]))
(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 clear-history-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/clear-history-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 delete-chat-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/remove-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 leave-group-action [chat-id]
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-pressed chat-id]))
(defn mute-chat-entry [chat-id]
(let [muted? (rf/sub [:chats/muted chat-id])]
@@ -92,35 +64,33 @@
: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
:add-divider? true}))
(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}))
(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
:add-divider? true}))
(defn delete-chat-entry [item]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action item)
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
:danger? true
:sub-label nil
:chevron? false}))
(defn leave-group-entry [item]
(defn delete-chat-entry [chat-id]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action chat-id)
:danger? true
:sub-label nil
:chevron? false}))
(defn leave-group-entry [chat-id]
(entry {:icon :i/log-out
:label (i18n/label :t/leave-group)
:on-press #(leave-group-action item)
:on-press #(leave-group-action chat-id)
:danger? true
:sub-label nil
:chevron? false}))
@@ -206,18 +176,17 @@
:chevron? false}))
(defn mark-untrustworthy-entry []
(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}))
(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}))
(defn block-user-entry [item]
(defn block-user-entry []
(entry {:icon :i/block
:label (i18n/label :t/block-user)
:on-press #(block-user-action item)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? true
:sub-label nil
:chevron? false}))
@@ -262,11 +231,11 @@
:sub-label nil
:chevron? false}))
(defn destructive-actions [{:keys [group-chat] :as item}]
[(clear-history-entry item)
(defn destructive-actions [chat-id group-chat]
[(clear-history-entry chat-id)
(if group-chat
(leave-group-entry item)
(delete-chat-entry item))])
(leave-group-entry chat-id)
(delete-chat-entry chat-id))])
(defn notification-actions [{:keys [chat-id group-chat public?]} inside-chat?]
[(mark-as-read-entry chat-id)
@@ -293,33 +262,32 @@
(when (and admin? inside-chat?) (edit-group-entry))
(when (and admin? inside-chat?) (group-privacy-entry))]))
(defn one-to-one-actions [{:keys [chat-id] :as item} inside-chat?]
(defn one-to-one-actions [{:keys [chat-id group-chat] :as item} inside-chat?]
[drawer/action-drawer [[(view-profile-entry chat-id)
(edit-nickname-entry chat-id)]
(notification-actions item inside-chat?)
(destructive-actions item)]])
(destructive-actions chat-id group-chat)]])
(defn public-chat-actions [{:keys [chat-id] :as item} inside-chat?]
(defn public-chat-actions [{:keys [chat-id group-chat] :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 item)]])
(destructive-actions chat-id group-chat)]])
(defn private-group-chat-actions [item inside-chat?]
(defn private-group-chat-actions [{:keys [chat-id group-chat] :as item} inside-chat?]
[drawer/action-drawer [(group-actions item inside-chat?)
(notification-actions item inside-chat?)
(destructive-actions item)]])
(destructive-actions chat-id group-chat)]])
(defn contact-actions [{:keys [public-key added] :as contact}]
(defn contact-actions [{:keys [public-key] :as contact}]
[drawer/action-drawer [[(view-profile-entry public-key)
(when added
(remove-from-contacts-entry contact)
(rename-entry)
(show-qr-entry)
(share-profile-entry))]
(remove-from-contacts-entry contact)
(rename-entry)
(show-qr-entry)
(share-profile-entry)]
[(mark-untrustworthy-entry)
(block-user-entry contact)]]])
(block-user-entry)]]])
(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]
[utils.re-frame :as rf]
[status-im.utils.re-frame :as rf]
[status-im.ui2.screens.chat.actions :as actions]))
(defn open-chat [chat-id]
@@ -22,13 +22,11 @@
(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]))
current-pk (rf/sub [:multiaccount/public-key])]
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))]
[rn/touchable-opacity (merge {:style (style/container)
:on-press #(open-chat public-key)
:on-long-press #(when-not (= current-pk public-key)
(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}]))})
:on-long-press #(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
@@ -46,14 +44,11 @@
(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)]]
(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)}]])]))
[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)}]]]))
@@ -1,10 +1,11 @@
(ns status-im.ui2.screens.chat.components.message-home-item.view
(:require [clojure.string :as string]
[utils.re-frame :as rf]
[status-im.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]
@@ -89,11 +90,14 @@
(defn display-pic-view [group-chat color display-name photo-path]
(if group-chat
[quo2/group-avatar {:color color
:size :medium}]
[quo2/user-avatar {:full-name display-name
:profile-picture photo-path
:size :small}]))
[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}]))
(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
{:text-transform :none
:margin-left 4
:margin-top 2}
{:ellipsize-mode :tail
: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))
@@ -1,20 +0,0 @@
(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)})
@@ -1,90 +0,0 @@
(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}]]))

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