Compare commits

..
Author SHA1 Message Date
Ulises M 747d6bb128 WIP: debugging 2024-02-13 13:30:46 -06:00
Ulises M a29264a1a1 Reimplement avatar animations using new worklet approach 2024-02-12 15:06:35 -06:00
Ulises M 1386bd4777 Add worklet translation to shadow-cljs 2024-02-12 15:06:03 -06:00
133 changed files with 933 additions and 1677 deletions
-3
View File
@@ -194,6 +194,3 @@ test/appium/tests/users.py
## git hooks
lefthook.yml
## metro server logs
metro-server-logs.log
+13 -6
View File
@@ -44,7 +44,7 @@ export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
# Our custom config is located in nix/nix.conf
export NIX_USER_CONF_FILES = $(PWD)/nix/nix.conf
# Location of symlinks to derivations that should not be garbage collected
export _NIX_GCROOTS = ./.nix-gcroots
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,\
BUILD_TYPE,BUILD_NUMBER,COMMIT_HASH,\
@@ -214,7 +214,7 @@ build-fdroid: ##@build Build release for F-Droid
build-android: export BUILD_ENV ?= prod
build-android: export BUILD_TYPE ?= nightly
build-android: export ORG_GRADLE_PROJECT_versionCode ?= $(TMP_BUILD_NUMBER)
build-android: export BUILD_NUMBER ?= $(TMP_BUILD_NUMBER)
build-android: export ANDROID_ABI_SPLIT ?= false
build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
build-android: ##@build Build unsigned Android APK
@@ -267,7 +267,7 @@ run-clojure: ##@run Watch for and build Clojure changes for mobile
run-metro: export TARGET := clojure
run-metro: ##@run Start Metro to build React Native changes
@scripts/run-metro.sh
@scripts/start-react-native.sh
run-re-frisk: export TARGET := clojure
run-re-frisk: ##@run Start re-frisk server
@@ -278,15 +278,22 @@ run-android: export TARGET := android
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
run-android: export ORG_GRADLE_PROJECT_hermesEnabled := false
# INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set.
run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_abis.sh)
run-android: ##@run Build Android APK and start it on the device
@scripts/run-android.sh
npx react-native run-android --appIdSuffix debug
SIMULATOR=iPhone 13
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios: export TARGET := ios
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios: ##@run Build iOS app and start it in on the simulator
@scripts/run-ios.sh "${SIMULATOR}"
run-ios: export XCBeautify=$(shell which xcbeautify) # for react-native-cli to pick this up and to auto format output
run-ios: ##@run Build iOS app and start it in a simulator/device
ifneq ("$(SIMULATOR)", "")
npx react-native run-ios --simulator="$(SIMULATOR)"
else
npx react-native run-ios
endif
show-ios-devices: ##@other shows connected ios device and its name
xcrun xctrace list devices
+2 -2
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'linux && x86_64 && nix-2.19' }
agent { label 'linux && x86_64 && nix-2.14' }
options {
timestamps()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent { label 'linux' }
+2 -2
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'macos && arm64 && nix-2.19 && xcode-15.1' }
agent { label 'macos && arm64 && nix-2.14 && xcode-15.1' }
parameters {
string(
+2 -2
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'linux && x86_64 && nix-2.19' }
agent { label 'linux && x86_64 && nix-2.14' }
options {
timestamps()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent { label 'macos' }
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent { label params.AGENT_LABEL }
@@ -82,7 +82,7 @@ pipeline {
env.NIXPKGS_SYSTEM_OVERRIDE = nixSysOverride(os, arch, 'android')
/* Build/fetch deps required to build android release. */
nix.build(
attr: 'targets.mobile.android.build.buildInputs',
attr: 'targets.mobile.android.release.buildInputs',
sandbox: false,
pure: false,
link: false
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.5'
pipeline {
agent {
+2 -1
View File
@@ -122,9 +122,10 @@ See below:
Do the following:
Ensure you have 2 terminals running the following
Ensure you have 3 terminals running the following
- `make run-clojure`
- `make run-metro`
- `make run-ios` / `make run-android`
[See the STARTING GUIDE for details](STARTING_GUIDE.md#development)
+2 -1
View File
@@ -15,7 +15,8 @@ This step will take a while the first time as it will download all dependencies.
There are three steps necessary to start development, in this case for Android:
1. `make run-clojure` - Compiles Clojure into JavaScript, watches for changes on cljs files, and hot-reloads code in the app.
2. `make run-android` or `make run-ios` - Builds the Android/iOS app, starts it on the device and starts metro bundler.
2. `make run-metro` - Starts metro bundler and watches JavaScript code.
3. `make run-android` or `make run-ios` - Builds the Android/iOS app and starts it on the device.
The first two will continue watching for changes and keep re-building the app. They need to be ready first.
The last one will exit once the app is up and ready.
+1 -1
View File
@@ -793,7 +793,7 @@ CHECKOUT OPTIONS:
:submodules: true
SPEC CHECKSUMS:
boost: 64032b9e9b938fda23325e68a3771f0fabf414dc
boost: 57d2868c099736d80fcd648bf211b4431e51a558
BVLinearGradient: 612a04ff38e8480291f3379ee5b5a2c571f03fe0
CryptoSwift: c4f2debceb38bf44c80659afe009f71e23e4a082
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
@@ -120,12 +120,9 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkAddressChecksum:(NSString *)address)
return StatusgoCheckAddressChecksum(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isAddress:(NSString *)address) {
return StatusgoIsAddress(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}
@end
+5 -7
View File
@@ -61,7 +61,7 @@ We will use the `make jsbundle` target as an example of a derivation you can bui
3. [`build.sh`](/nix/scripts/build.sh) calls `nix-build --attr targets.mobile.jsbundle` with extra arguments
4. `nix-build` builds the derivation from [`nix/mobile/jsbundle/default.nix`](/nix/mobile/jsbundle/default.nix)
The same can be done for other targets like `targets.mobile.android.build`.
The same can be done for other targets like `targets.mobile.android.release`.
Except in that case extra arguments are required which is why the [`scripts/release-android.sh`](/scripts/release-android.sh) is used in the `make release-android` target.
If you run `make release-android` you'll see the `nix-build` command used:
@@ -71,23 +71,21 @@ nix-build \
--fallback \
--no-out-link \
--show-trace \
--attr targets.mobile.android.build \
--attr targets.mobile.android.release \
--argstr secrets-file '/tmp/tmp-status-mobile-559a3a441/tmp.xAnrPuNtAP' \
--option extra-sandbox-paths '/home/joe/.gradle/status-im.keystore /tmp/tmp-status-mobile-559a3a441/tmp.xAnrPuNtAP' \
default.nix
```
Some of those are required which is why just calling:
```
nix-build --attr targets.mobile.android.build
nix-build --attr targets.mobile.android.release
```
Would fail.
# Garbage Collection
The `make nix-gc` target calls `nix-store --gc` and normally would remove almost everything, but to prevent that we place symlinks to protected derivations in `.nix-gcroots` folder. Specifically:
The `make nix-gc` target calls `nix-store --gc` and normally would remove almost everything, but to prevent that we place symlinks to protected derivations in `/nix/var/nix/gcroots` subfolder. Specifically:
```sh
_NIX_GCROOTS="${_NIX_GCROOTS:-${GIT_ROOT}/.nix-gcroots}
_NIX_GCROOTS="${_NIX_GCROOTS:-/nix/var/nix/gcroots/per-user/${USER}/status-mobile}"
```
These symlinks in turn will be symlinked from `/nix/var/nix/gcroots/auto` through use of `nix-store --add-gcroots`.
Whenever `nix/scripts/build.sh` or `nix/scripts/shell.sh` are called they update symlinks named after given targets in that folder. This in combination with `keep-outputs = true` set in `nix/nix.conf` prevents garbage collection from removing too much.
+1 -1
View File
@@ -28,7 +28,7 @@ export STATUS_GO_IPFS_GATEWAY_URL="https://ipfs.status.im/"
```
You can see the defaults in code:
- [`nix/status-go/default.nix`](./status-go/default.nix)
- [`nix/mobile/android/release.nix`](./mobile/android/build.nix)
- [`nix/mobile/android/release.nix`](./mobile/android/release.nix)
## Shell
+1 -1
View File
@@ -6,7 +6,7 @@ This directory contains the tools and the data that allows Nix to manage Gradle
Simply calling `generate.sh` should result in a `deps.json` file which is used in the derivation that provides Gradle dependencies when building the Android app.
You can see in [`nix/mobile/android/release.nix`](../../mobile/android/build.nix) that it's used via the `-Dmaven.repo.local='${deps.gradle}'` Gradle flag.
You can see in [`nix/mobile/android/release.nix`](../../mobile/android/release.nix) that it's used via the `-Dmaven.repo.local='${deps.gradle}'` Gradle flag.
# Files
+2 -2
View File
@@ -2,7 +2,7 @@
, jsbundle, status-go, androidPkgs, androidShell }:
rec {
build = callPackage ./build.nix {
release = callPackage ./release.nix {
inherit jsbundle status-go;
};
@@ -15,7 +15,7 @@ rec {
];
inputsFrom = [
(build {})
(release {})
androidShell
];
@@ -7,15 +7,15 @@
# Path to the file containing secret environment variables
secretsFile ? "",
# Build type (influences which .env file gets used for feature flags)
# TODO: pr or relase for default?
buildType ? lib.getEnvWithDefault "BUILD_TYPE" "release",
# Used for versionCode
versionCode ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_versionCode" 9999,
buildNumber ? lib.getEnvWithDefault "BUILD_NUMBER" 9999,
# Included in APK Manifest for easier identification.
commitHash ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_commitHash" "unknown",
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
hermesEnabled ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_hermesEnabled" "true",
buildUrl ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_buildUrl" null,
# TODO: or GIT_COMMIT from Jenkins?
commitHash ? lib.getEnvWithDefault "COMMIT_HASH" "unknown",
# Gradle options passed for Android builds
androidGradleOpts ? lib.getEnvWithDefault "ANDROID_GRADLE_OPTS" null,
statusGoSrcOverride ? lib.getEnvWithDefault "STATUS_GO_SRC_OVERRIDE" null,
# If APKs should be split based on architectures
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "false",
@@ -40,10 +40,8 @@ let
else if (elem buildType ["pr" "manual"]) then ".env.jenkins"
else ".env";
gradleBuildType =
if buildType == "pr" then "Pr"
else if buildType == "debug" then "Debug"
else "Release";
# There are only two types of Gradle build targets: pr and release
gradleBuildType = if buildType == "pr" then "Pr" else "Release";
apksPath = "./android/app/build/outputs/apk/${toLower gradleBuildType}";
@@ -83,10 +81,7 @@ in stdenv.mkDerivation rec {
ANDROID_ABI_INCLUDE = androidAbiInclude;
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
ORG_GRADLE_PROJECT_versionCode = versionCode;
ORG_GRADLE_PROJECT_commitHash = commitHash;
ORG_GRADLE_PROJECT_buildUrl = buildUrl;
ORG_GRADLE_PROJECT_hermesEnabled = hermesEnabled;
ORG_GRADLE_PROJECT_hermesEnabled = true;
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
NODE_OPTIONS = "--openssl-legacy-provider";
@@ -121,6 +116,8 @@ in stdenv.mkDerivation rec {
# Symlink React Native entrypoint.
cp -Lr ${builtJsBundle} ./result
pwd
find -L result
# Copy android/ directory
mkdir -p ./android/build
@@ -147,6 +144,7 @@ in stdenv.mkDerivation rec {
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${makeLibraryPath [ pkgs.zlib ]}";
gradleCommand = ''
${pkgs.gradle}/bin/gradle \
${toString androidGradleOpts} \
--console=plain \
--offline \
--no-daemon \
@@ -154,6 +152,8 @@ in stdenv.mkDerivation rec {
--no-watch-fs \
--no-build-cache \
-Dmaven.repo.local='${deps.gradle}' \
-PversionCode=${toString buildNumber} \
-PcommitHash=${commitHash} \
assemble${gradleBuildType}
'';
in
@@ -171,14 +171,12 @@ in stdenv.mkDerivation rec {
${adhocEnvVars} ${gradleCommand}
popd > /dev/null
'';
doCheck = buildType != "debug";
checkPhase = ''
doCheck = true;
checkPhase = ''
ls ${apksPath}/*.apk \
| xargs -n1 ${pkgs.unzip}/bin/unzip -qql \
| grep 'index.android.bundle'
'';
installPhase = ''
mkdir -p $out
cp ${apksPath}/*.apk $out/
+1 -1
View File
@@ -45,7 +45,7 @@ if [[ -z "${TARGET}" ]]; then
fi
# Hack fix for missing Android SDK for aarch64 on Darwin. See systemOverride in `nix/pkgs.nix`.
if [[ "${TARGET}" =~ ^(targets.status-go.mobile.android|targets.mobile.android.build)$ ]]; then
if [[ "${TARGET}" =~ ^(targets.status-go.mobile.android|targets.mobile.android.release)$ ]]; then
os=$(uname -s | tr '[:upper:]' '[:lower:]')
export NIXPKGS_SYSTEM_OVERRIDE="x86_64-${os}"
fi
+2 -2
View File
@@ -2,12 +2,12 @@
set -Ee
_NIX_GCROOTS="${_NIX_GCROOTS:-/nix/var/nix/gcroots/per-user/${USER}/status-mobile}"
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/nix/scripts/source.sh"
source "${GIT_ROOT}/scripts/colors.sh"
_NIX_GCROOTS="${_NIX_GCROOTS:-${GIT_ROOT}/.nix-gcroots}"
TARGET="${1}"
shift
if [[ -z "${TARGET}" ]]; then
+5 -3
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
export NIX_VERSION="2.19.3"
export NIX_PACKAGE="nixVersions.nix_2_19"
# WARNING: Versions 2.14, 2.15, 2.16 have an issue creating gcroots:
# https://github.com/NixOS/nix/issues/8564
export NIX_VERSION="2.13.4"
export NIX_PACKAGE="nixVersions.nix_2_13"
export NIX_INSTALL_URL="https://nixos.org/releases/nix/nix-${NIX_VERSION}/install"
export NIX_INSTALL_SHA256="73d47b0ab783fddca1b2d44a03d52a74c97c28a1fc8ff5a29419079302ef9c3d"
export NIX_INSTALL_SHA256="a9908cc48f5886b4f22172bdd2f9657873276fd295e78c6ed97fb308c6d284d0"
export NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}"
+3 -1
View File
@@ -21,6 +21,8 @@ function append_env_export() {
VAR_VALUE=$(must_get_env "${VAR_NAME}")
echo "export ${VAR_NAME}=\"${VAR_VALUE}\";" >> "${SECRETS_FILE_PATH}"
}
export COMMIT_HASH="$(git rev-parse --verify HEAD)"
nixOpts=()
# We create if now so the trap knows its location
@@ -71,4 +73,4 @@ else
fi
"${GIT_ROOT}/nix/scripts/build.sh" targets.mobile.android.build "${nixOpts[@]}"
"${GIT_ROOT}/nix/scripts/build.sh" targets.mobile.android.release "${nixOpts[@]}"
-53
View File
@@ -1,53 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
set -m # needed to access jobs
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
# We run Metro in background while calling adb.
cleanupMetro() {
pkill -f run-metro.sh
rm -f metro-server-logs.log
}
# Using function gives a neater jobspec name.
runMetro() {
nohup "${GIT_ROOT}/scripts/run-metro.sh" 2>&1 \
| tee metro-server-logs.log
}
waitForMetro() {
set +e # Allow grep command to fail in the loop.
TIMEOUT=5
echo "Waiting for Metro server..." >&2
while ! grep -q "Welcome to Metro" metro-server-logs.log; do
echo -n "." >&2
sleep 1
if ((TIMEOUT == 0)); then
echo -e "\nMetro server timed out, exiting" >&2
set -e # Restore errexit for rest of script.
return 1
fi
((TIMEOUT--))
done
set -e # Restore errexit for rest of script.
}
# Generate android debug build.
export ANDROID_ABI_INCLUDE=$("${GIT_ROOT}/scripts/adb_devices_abis.sh")
export BUILD_ENV=debug
export BUILD_TYPE=debug
"${GIT_ROOT}/scripts/build-android.sh"
# Install the APK on running emulator or android device.
adb install ./result/app-debug.apk
trap cleanupMetro EXIT ERR INT QUIT
runMetro &
waitForMetro
# Start the installed app.
adb shell monkey -p im.status.ethereum.debug 1
# bring metro job to foreground
fg 'runMetro'
-79
View File
@@ -1,79 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
set -m # needed to access jobs
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
# We run Metro in background while calling adb.
cleanupMetro() {
pkill -f run-metro.sh
rm -f metro-server-logs.log
}
# Using function gives a neater jobspec name.
runMetro() {
nohup "${GIT_ROOT}/scripts/run-metro.sh" 2>&1 \
| tee metro-server-logs.log
}
waitForMetro() {
set +e # Allow grep command to fail in the loop.
TIMEOUT=5
echo "Waiting for Metro server..." >&2
while ! grep -q "Welcome to Metro" metro-server-logs.log; do
echo -n "." >&2
sleep 1
if ((TIMEOUT == 0)); then
echo -e "\nMetro server timed out, exiting" >&2
set -e # Restore errexit for rest of script.
return 1
fi
((TIMEOUT--))
done
set -e # Restore errexit for rest of script.
}
# Check if the first argument is provided
if [ -z "${1-}" ]; then
echo "Error: No simulator name provided." >&2
exit 1
fi
SIMULATOR=${1}
# get our desired UUID
UUID=$(xcrun simctl list devices | grep -E "$SIMULATOR \(" | head -n 1 | awk -F '[()]' '{print $2}')
# get simulator status
SIMULATOR_STATE=$(xcrun simctl list devices | grep -E "$SIMULATOR \(" | head -n 1 | awk '{print $NF}')
# sometimes a simulator is already running, shut it down to avoid errors
if [ "$SIMULATOR_STATE" != "(Shutdown)" ]; then
xcrun simctl shutdown "$UUID"
fi
# boot up iOS for simulator
xcrun simctl boot "$UUID"
# start the simulator
open -a Simulator --args -CurrentDeviceUDID "$UUID"
BUILD_DIR="${GIT_ROOT}/build"
#iOS build of debug scheme
xcodebuild -workspace "ios/StatusIm.xcworkspace" -configuration Debug -scheme StatusIm -destination id="$UUID" -derivedDataPath "${BUILD_DIR}" | xcbeautify
APP_PATH="${BUILD_DIR}/Build/Products/Debug-iphonesimulator/StatusIm.app"
# Install on the simulator
xcrun simctl install "$UUID" "$APP_PATH"
trap cleanupMetro EXIT ERR INT QUIT
runMetro &
waitForMetro
# launch the app when metro is ready
xcrun simctl launch "$UUID" im.status.ethereum.debug
# bring metro job to foreground
fg 'runMetro'
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env bash
pkill -f 'react-native start'
react-native start --reset-cache
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/scripts/colors.sh"
METRO_PORT=8081
METRO_PID="$(lsof -i :${METRO_PORT} | awk 'NR!=1 {print $2}' | sort -u | tr '\r\n' ' ')"
if [ ! -z "$METRO_PID" ]; then
echo -e "${YLW}TCP port ${METRO_PORT} is required by the Metro packager.\nThe following processes currently have the port open, preventing Metro from starting:${RST}"
ps -fp $METRO_PID
echo -e "${YLW}Do you want to terminate them (y/n)?${RST}"
read -n 1 term
[[ $term == 'y' ]] && kill $METRO_PID
fi
react-native start --reset-cache
+3
View File
@@ -45,6 +45,9 @@
;; To match the folder created by Nix build of JSBundle.
:output-dir "result"
:init-fn status-im.core/init
:build-hooks [(status-im.setup.build-hooks.worklets/transform-output)
(status-im.setup.build-hooks.worklets/optimize-start)
(status-im.setup.build-hooks.worklets/optimize-output)]
;; When false, the Shadow-CLJS watcher won't automatically refresh
;; the target files (a.k.a hot reload). When false, you can manually
;; reload by calling `shadow.cljs.devtools.api/watch-compile-all!`.
@@ -36,7 +36,7 @@
[(mailserver/process-next-messages-request)
(bottom-sheet/hide-bottom-sheet-old)
(wallet/restart-wallet-service nil)
#(add-new-contact/set-new-identity-reconnected %)]
(add-new-contact/set-new-identity-reconnected)]
logged-in?
[(mailserver/process-next-messages-request)
+1 -1
View File
@@ -72,7 +72,7 @@
:PeerExchange true
:Port 0
:UDPPort 0
:LightClient false})
:LightClient true})
(def login-node-config
{:WalletConfig (cond-> {:Enabled true}
+1 -5
View File
@@ -81,9 +81,5 @@
{:db (-> db
(assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name))
:dispatch [:contacts/build-contact
{:pubkey identity
:ens ens-name
:success-fn (fn [_]
{:dispatch [:open-modal :profile]})}]}
:dispatch [:contacts/build-contact identity ens-name true]}
{:dispatch [:navigate-to :my-profile]})))
@@ -55,8 +55,7 @@
:on-change (fn [text]
(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed text])
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input text}]
300))}]]))
(debounce/debounce-and-dispatch [:contacts/set-new-identity text] 300))}]]))
(defn section
[_ _ _]
@@ -3,7 +3,7 @@
(def container
{:height 40
:flex-direction :row
:padding-horizontal 16
:padding-horizontal 20
:align-items :center})
(defn text
@@ -30,7 +30,7 @@
(defn circular-progress
[{:keys [color percentage]}]
(let [strength-indicator-radius 7.5
(let [strength-indicator-radius 6.5
strength-indicator-circumference (* 2 Math/PI strength-indicator-radius)]
[svg/svg
{:view-box "0 0 16 16"
@@ -63,10 +63,7 @@
:alert [icon/icon :i/alert
{:color color
:size 16}]
[rn/view
{:padding-left 4
:padding-right 2}
[circular-progress {:color color :percentage percentage}]])))
[circular-progress {:color color :percentage percentage}])))
(defn view
"Options
@@ -137,8 +137,7 @@
:description description}]))
(defn- right-icon
[{:keys [theme type on-button-press on-button-long-press button-disabled? button-icon button-type]
:or {button-type :primary}}]
[{:keys [theme type on-button-press on-button-long-press button-disabled? button-icon]}]
(cond
(= :info type)
[icons/icon
@@ -154,7 +153,7 @@
:on-press on-button-press
:on-long-press on-button-long-press
:disabled? button-disabled?
:type button-type
:type :primary
:size 24
:icon-only? true}
button-icon]))
@@ -183,7 +182,7 @@
(defn- view-internal
[{:keys [title title-icon type theme description blur? community-name community-logo button-icon
account-name emoji context-tag-type button-type
account-name emoji context-tag-type
on-button-press
on-button-long-press
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
@@ -222,7 +221,6 @@
[right-icon
{:theme theme
:type type
:button-type button-type
:on-button-press on-button-press
:on-button-long-press on-button-long-press
:button-disabled? button-disabled?
@@ -311,7 +311,7 @@
- title
- description
- picture: a valid rn/image `:source` value
`:wallet-networks`
`:wallet-network`
- networks: a vector of network image source
- networks-on-press: a callback
`:community`
@@ -11,8 +11,8 @@
:padding-bottom 8})
(defn settings-items
[{:keys [label blur? theme]}]
{:margin-top (if label 12 4)
[{:keys [blur? theme]}]
{:margin-top 12
:border-radius 16
:background-color (if blur?
colors/white-opa-5
@@ -1,52 +0,0 @@
(ns quo.components.tags.collectible-tag.component-spec
(:require
[quo.components.tags.collectible-tag.view :as collectible-tag]
[test-helpers.component :as h]))
(def collectible-name "Collectible")
(def collectible-id "#123")
(defn get-test-data
[{:keys [options blur? size]}]
{:collectible-name collectible-name
:collectible-id collectible-id
:collectible-img-src {:uri "https://example.com/image.jpg"}
:options options
:blur? (or blur? false)
:size (or size :size-24)})
(h/describe "Collectible_tag tests"
(h/test "Renders Default option"
(let [data (get-test-data {})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders Add option"
(let [data (get-test-data {:options :add})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders Hold option"
(let [data (get-test-data {:options :hold})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders with Blur"
(let [data (get-test-data {:blur? true})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders without Blur"
(let [data (get-test-data {:blur? false})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders with Size 24"
(let [data (get-test-data {:size :size-24})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name))))
(h/test "Renders with Size 32"
(let [data (get-test-data {:size :size-32})]
(h/render-with-theme-provider [collectible-tag/view data])
(h/is-truthy (h/get-by-text collectible-name)))))
@@ -1,15 +0,0 @@
(ns quo.components.tags.collectible-tag.schema)
(def ?schema
[:=>
[:catn
[:props
[:map
[:options {:optional true} [:maybe [:enum :add :hold]]]
[:size {:optional true} [:maybe [:enum :size-24 :size-32]]]
[:blur? {:optional true} [:maybe :boolean]]
[:theme :schema.common/theme]
[:collectible-img-src :schema.common/image-source]
[:collectible-name :string]
[:collectible-id :string]]]]
:any])
@@ -1,59 +1,70 @@
(ns quo.components.tags.collectible-tag.view
(:require
[oops.core :as oops]
[quo.components.icon :as icons]
[quo.components.markdown.text :as text]
[quo.components.tags.collectible-tag.schema :as component-schema]
[quo.components.tags.collectible-tag.style :as style]
[quo.theme]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[reagent.core :as reagent]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:options {:optional true} [:maybe [:enum false :add :hold]]]
[:size {:optional true} [:enum :size-24 :size-32]]
[:blur? {:optional true} :boolean]
[:theme :schema.common/theme]
[:collectible-img-src [:or :int :string]]
[:collectible-name :string]
[:collectible-id :string]
[:container-width :number]
[:on-layout {:optional true} [:maybe fn?]]]]]
:any])
(defn- view-internal
[]
(let [container-width (reagent/atom 0)
on-layout #(->> (oops/oget % :nativeEvent :layout :width)
(reset! container-width))]
(fn [{:keys [options blur? theme collectible-img-src collectible-name collectible-id] :as props}]
(let [size (or (:size props) :size-24)]
[rn/view
{:on-layout on-layout}
[hole-view/hole-view
{:holes (if options
[{:x (- @container-width
(case size
:size-24 10
:size-32 12
nil))
:y (case size
:size-24 -6
:size-32 -4
nil)
:width 16
:height 16
:borderRadius 8}]
[])}
[rn/view {:style (style/container size options blur? theme)}
[rn/image {:style (style/collectible-img size) :source collectible-img-src}]
[text/text
{:size :paragraph-2
:weight :medium
:style (style/label theme)}
collectible-name]
[text/text
{:size :paragraph-2
:weight :medium
:margin-left 5
:style (style/label theme)}
collectible-id]]]
(when options
[rn/view {:style (style/options-icon size)}
[icons/icon (if (= options :hold) :i/hold :i/add-token)
{:size 20
:no-color true}]])]))))
(fn [{:keys [options size blur? theme collectible-img-src collectible-name collectible-id
container-width on-layout]
:or {size :size-24}}]
[rn/view
{:on-layout on-layout}
[hole-view/hole-view
{:holes (if options
[{:x (- container-width
(case size
:size-24 10
:size-32 12
nil))
:y (case size
:size-24 -6
:size-32 -4
nil)
:width 16
:height 16
:borderRadius 8}]
[])}
[rn/view {:style (style/container size options blur? theme)}
[rn/image {:style (style/collectible-img size) :source collectible-img-src}]
[text/text
{:size :paragraph-2
:weight :medium
:style (style/label theme)}
collectible-name]
[text/text
{:size :paragraph-2
:weight :medium
:margin-left 5
:style (style/label theme)}
collectible-id]]]
(when options
[rn/view {:style (style/options-icon size)}
[icons/icon (if (= options :hold) :i/hold :i/add-token)
{:size 20
:no-color true}]])]))
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))
(schema/instrument #'view-internal ?schema)))
@@ -18,6 +18,5 @@
[:disabled? {:optional true} [:maybe :boolean]]
[:on-change {:optional true} [:maybe fn?]]
[:container-style {:optional true} [:maybe :map]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:theme :schema.common/theme]]]]
:any])
@@ -42,11 +42,9 @@
(defn- view-internal
[{:keys
[checked? disabled? on-change token-details keycard? theme container-style customization-color]
[checked? disabled? on-change token-details keycard? theme container-style]
{:keys
[name address emoji]
:as account} :account
:or {customization-color :blue}}]
[name address emoji customization-color]} :account}]
[rn/view
{:style (merge (style/container theme) container-style)
:accessibility-label :wallet-account-permissions}
@@ -54,7 +52,7 @@
[account-avatar/view
{:size 32
:emoji emoji
:customization-color (:customization-color account)}]
:customization-color customization-color}]
[rn/view {:style style/account-details}
[rn/view {:style style/name-and-keycard}
[text/text
@@ -69,11 +67,10 @@
{:address address
:format :short}]]
[selectors/view
{:type :checkbox
:checked? checked?
:customization-color customization-color
:disabled? disabled?
:on-change on-change}]]
{:type :checkbox
:checked? checked?
:disabled? disabled?
:on-change on-change}]]
[token-details-section token-details]])
@@ -15,101 +15,101 @@
(h/describe "Confirmation Progress"
(h/test "component renders when state is sending and network is optimism"
(h/render-with-theme-provider [quo/confirmation-progress
(h/render-with-theme-provider [quo/confirmation-propgress
(get-test-data {:state :sending
:network :optimism})])
(h/is-truthy (h/get-by-label-text :progress-box))))
(h/test "component renders when state is confirmed and network is optimism"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :confirmed
:network :optimism})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is finalising and network is optimism"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :finalising
:network :optimism})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is finalized and network is optimism"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :finalized
:network :optimism})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is error and network is optimism"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :error
:network :optimism})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is sending and network is arbitrum"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :sending
:network :arbitrum})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is confirmed and network is arbitrum"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :confirmed
:network :arbitrum})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is finalising and network is arbitrum"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :finalising
:network :arbitrum})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is finalized and network is arbitrum"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :finalized
:network :arbitrum})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is error and network is arbitrum"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :error
:network :arbitrum})])
(h/is-truthy (h/get-by-label-text :progress-box)))
(h/test "component renders when state is pending and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress (get-test-data {})])
[quo/confirmation-propgress (get-test-data {})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
(h/test "component renders when state is sending and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress (get-test-data {:state :sending})])
[quo/confirmation-propgress (get-test-data {:state :sending})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
(h/test "component renders when state is confirmed and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress (get-test-data {:state :confirmed})])
[quo/confirmation-propgress (get-test-data {:state :confirmed})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
(h/test "component renders when state is finalising and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress (get-test-data {:state :finalising})])
[quo/confirmation-propgress (get-test-data {:state :finalising})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
(h/test "component renders when state is finalized and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress (get-test-data {:state :finalized})])
[quo/confirmation-propgress (get-test-data {:state :finalized})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
(h/test "component renders when state is error and network is mainnet"
(h/render-with-theme-provider
[quo/confirmation-progress
[quo/confirmation-propgress
(get-test-data {:state :error})])
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
+1 -1
View File
@@ -418,7 +418,7 @@
(def account-permissions quo.components.wallet.account-permissions.view/view)
(def address-text quo.components.wallet.address-text.view/view)
(def amount-input quo.components.wallet.amount-input.view/view)
(def confirmation-progress quo.components.wallet.confirmation-progress.view/view)
(def confirmation-propgress quo.components.wallet.confirmation-progress.view/view)
(def keypair quo.components.wallet.keypair.view/view)
(def network-amount quo.components.wallet.network-amount.view/view)
(def network-bridge quo.components.wallet.network-bridge.view/view)
-1
View File
@@ -79,7 +79,6 @@
quo.components.share.share-qr-code.component-spec
quo.components.switchers.base-card.component-spec
quo.components.switchers.group-messaging-card.component-spec
quo.components.tags.collectible-tag.component-spec
quo.components.tags.network-tags.component-spec
quo.components.tags.status-tags-component-spec
quo.components.tags.summary-tag.component-spec
+4 -1
View File
@@ -20,7 +20,8 @@
LinearTransition
enableLayoutAnimations
useAnimatedScrollHandler
runOnJS)]
runOnJS)
:as reanimated*]
["react-native-redash" :refer (withPause)]
[oops.core :as oops]
[react-native.flat-list :as rn-flat-list]
@@ -113,6 +114,8 @@
(when (and anim (some? v))
(set! (.-value anim) v)))
(def interpolate* reanimated*/interpolate)
(defn interpolate
([shared-value input-range output-range]
(interpolate shared-value input-range output-range nil))
+2 -6
View File
@@ -63,7 +63,7 @@
item-height (reagent/atom 0)]
(fn [{:keys [hide? insets theme]}
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
gradient-cover? customization-color hide-handle? blur-radius]
gradient-cover? customization-color hide-handle?]
:or {border-radius 12}}]
(let [{window-height :height} (rn/get-window)
bg-opacity (reanimated/use-shared-value 0)
@@ -106,11 +106,7 @@
{:transform [{:translateY translate-y}]}
(style/sheet insets window-height selected-item))}
(when shell?
[blur/ios-view
{:style style/shell-bg
:blur-radius (or blur-radius 20)
:blur-type :transparent
:overlay-color :transparent}])
[blur/ios-view {:style style/shell-bg}])
(when selected-item
[rn/view
{:on-layout #(reset! item-height (.-nativeEvent.layout.height ^js %))
@@ -15,12 +15,12 @@
(def ^:const drag-threshold 200)
(defn drag-gesture
[{:keys [translate-y opacity scroll-enabled? curr-scroll close reset-open-sheet set-animating-true]}]
[{:keys [translate-y opacity scroll-enabled curr-scroll close reset-open-sheet set-animating-true]}]
(-> (gesture/gesture-pan)
(gesture/on-start (fn [e]
(set-animating-true)
(when (< (oops/oget e "velocityY") 0)
(reset! scroll-enabled? true))))
(reset! scroll-enabled true))))
(gesture/on-update (fn [e]
(let [translation (oops/oget e "translationY")
progress (Math/abs (/ translation drag-threshold))]
@@ -34,7 +34,7 @@
(gesture/on-finalize (fn [e]
(when (and (>= (oops/oget e "velocityY") 0)
(<= @curr-scroll (if platform/ios? -1 0)))
(reset! scroll-enabled? false))))))
(reset! scroll-enabled false))))))
(defn on-scroll
[e curr-scroll]
@@ -43,7 +43,7 @@
(defn- f-view
[_]
(let [scroll-enabled? (reagent/atom true)
(let [scroll-enabled (reagent/atom true)
curr-scroll (reagent/atom 0)
animating? (reagent/atom true)
set-animating-true #(reset! animating? true)
@@ -63,7 +63,7 @@
(reanimated/animate translate-y 0 300)
(reanimated/animate opacity 1 300)
(set-animating-false 300)
(reset! scroll-enabled? true))]
(reset! scroll-enabled true))]
(rn/use-effect
(fn []
(reanimated/animate translate-y 0 300)
@@ -76,7 +76,7 @@
[gesture/gesture-detector
{:gesture (drag-gesture {:translate-y translate-y
:opacity opacity
:scroll-enabled? scroll-enabled?
:scroll-enabled scroll-enabled
:curr-scroll curr-scroll
:close close
:reset-open-sheet reset-open-sheet
@@ -87,7 +87,7 @@
[content
{:insets insets
:close close
:scroll-enabled? @scroll-enabled?
:scroll-enabled scroll-enabled
:current-scroll curr-scroll
:on-scroll #(on-scroll % curr-scroll)
:sheet-animating? animating?}]]]]))))
+2 -2
View File
@@ -94,11 +94,11 @@
:container-style style/empty-results}])
(defn- render-list
[{:keys [theme filtered-data on-viewable-items-changed scroll-enabled? on-scroll
[{:keys [theme filtered-data on-viewable-items-changed scroll-enabled on-scroll
on-select set-scroll-ref close sheet-animating?]}]
[gesture/flat-list
{:ref set-scroll-ref
:scroll-enabled scroll-enabled?
:scroll-enabled @scroll-enabled
:data (or filtered-data emoji-picker.data/flatten-data)
:initial-num-to-render 14
:max-to-render-per-batch 10
+1 -1
View File
@@ -33,7 +33,7 @@
nil)]
[quo/top-nav
{:avatar-on-press #(rf/dispatch [:open-modal :settings])
:scan-on-press #(rf/dispatch [:open-modal :shell-qr-reader])
:scan-on-press #(js/alert "to be implemented")
:activity-center-on-press #(rf/dispatch [:activity-center/open])
:qr-code-on-press #(rf/dispatch [:open-modal :share-shell])
:container-style (merge style/top-nav-container container-style)
+9 -19
View File
@@ -26,18 +26,8 @@
(def web2-domain "status.app")
(def user-path "u#")
(def user-with-data-path "u/")
(def community-path "c#")
(def community-with-data-path "c/")
(def channel-path "cc/")
(def web-urls (map #(str % web2-domain "/") web-prefixes))
(defn path-urls
[path]
(map #(str % path) web-urls))
(def handled-schemes (set (into uri-schemes web-urls)))
(def group-chat-extractor
@@ -51,15 +41,15 @@
(def routes
[""
{handled-schemes {[community-with-data-path :community-data] :community
[channel-path :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
[user-with-data-path :user-data] :user
"c" :community
"u" :user}
{handled-schemes {["c/" :community-data] :community
["cc/" :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
["u/" :user-data] :user
"c" :community
"u" :user}
ethereum-scheme eip-extractor}])
(defn parse-query-params
+2 -13
View File
@@ -1,11 +1,11 @@
(ns status-im.common.validation.profile
(:require [clojure.string :as string]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
;; NOTE - validation should match with Desktop
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
(def min-length 5)
(def max-length 24)
(def emoji-regex
#"(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])")
@@ -22,9 +22,7 @@
(defn name-too-short? [s] (< (count (string/trim (str s))) min-length))
(defn name-too-long? [s] (> (count (string/trim (str s))) constants/profile-name-max-length))
(defn bio-too-long? [s] (> (count (string/trim (str s))) constants/profile-bio-max-length))
(defn name-too-long? [s] (> (count (string/trim (str s))) max-length))
(defn validation-name
[s]
@@ -41,12 +39,3 @@
{:check (i18n/label :t/special-characters)})
(name-too-short? s) (i18n/label :t/minimum-characters {:min-chars min-length})
(name-too-long? s) (i18n/label :t/profile-name-is-too-long)))
(defn validation-bio
[s]
(cond
(or (= s nil) (= s "")) nil
(has-emojis? s) (i18n/label :t/are-not-allowed {:check (i18n/label :t/emojis)})
(has-special-characters? s) (i18n/label :t/are-not-allowed
{:check (i18n/label :t/special-characters)})
(bio-too-long? s) (i18n/label :t/bio-is-too-long)))
+1 -1
View File
@@ -167,5 +167,5 @@
(def default-kdf-iterations 3200)
(def community-accounts-selection-enabled? true)
(def community-accounts-selection-enabled? (enabled? (get-config :ACCOUNT_SELECTION_ENABLED "0")))
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
-4
View File
@@ -107,7 +107,6 @@
(def ^:const profile-default-color :blue)
(def ^:const profile-name-max-length 24)
(def ^:const profile-bio-max-length 240)
(def ^:const profile-default-currency :usd)
(def ^:const profile-pictures-show-to-contacts-only 1)
@@ -258,7 +257,6 @@
(def ^:const terms-of-service-link "https://status.im/terms-of-use")
(def ^:const docs-link "https://status.im/docs/")
(def ^:const principles-link "https://our.status.im/our-principles/")
(def ^:const create-account-link "https://status.app/help/wallet/create-wallet-accounts")
(def ^:const visibility-status-unknown 0)
(def ^:const visibility-status-automatic 1)
@@ -433,8 +431,6 @@
(def ^:const optimism-network-name :optimism)
(def ^:const arbitrum-network-name :arbitrum)
(def ^:const default-network-names #{mainnet-network-name optimism-network-name arbitrum-network-name})
(def ^:const chain-id-separator ":")
(def ^:const account-default-customization-color :blue)
@@ -1,12 +1,13 @@
(ns status-im.contexts.chat.home.add-new-contact.events
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.common.validators :as validators]
[status-im.contexts.chat.contacts.events :as data-store.contacts]
status-im.contexts.chat.home.add-new-contact.effects
[status-im.navigation.events :as navigation]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.re-frame :as rf]
[utils.string :as utils.string]))
(defn init-contact
@@ -86,64 +87,72 @@
(def validate-contact (comp ->state ->type ->id))
(declare build-contact)
(defn dispatcher [event input] (fn [arg] (rf/dispatch [event input arg])))
(defn set-new-identity
[{:keys [db]} [{:keys [input build-success-fn failure-fn]}]]
(rf/defn set-new-identity
{:events [:contacts/set-new-identity]}
[{:keys [db]} input scanned]
(let [user-public-key (get-in db [:profile/profile :public-key])
{:keys [input id ens state]
:as contact} (-> {:user-public-key user-public-key
:input input
:scanned input}
:scanned scanned}
init-contact
validate-contact)]
(case state
:empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact)
:serialization/decompress-public-key
{:compressed-key id
:on-success
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
(dispatcher :contacts/set-new-identity-success input)
:on-error
#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}}
(dispatcher :contacts/set-new-identity-error input)}}
:resolve-ens {:db (assoc db :contacts/new-identity contact)
:effects.contacts/resolve-public-key-from-ens
{:chain-id (chain/chain-id db)
:ens ens
:on-success
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
(dispatcher :contacts/set-new-identity-success input)
:on-error
#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}})))
(dispatcher :contacts/set-new-identity-error input)}})))
(re-frame/reg-event-fx :contacts/set-new-identity set-new-identity)
(defn- set-new-identity-success
[{:keys [db]} [{:keys [input pubkey build-success-fn]}]]
(rf/defn build-contact
{:events [:contacts/build-contact]}
[_ pubkey ens open-profile-modal?]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(rf/dispatch [:contacts/contact-built
pubkey
open-profile-modal?
(data-store.contacts/<-rpc-js %)])}]})
(rf/defn contact-built
{:events [:contacts/contact-built]}
[{:keys [db]} pubkey open-profile-modal? contact]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when open-profile-modal?
{:dispatch [:open-modal :profile]})))
(rf/defn set-new-identity-success
{:events [:contacts/set-new-identity-success]}
[{:keys [db]} input pubkey]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
{:db (assoc db :contacts/new-identity (->state (assoc contact :public-key pubkey)))
:dispatch [:contacts/build-contact
{:pubkey pubkey
:ens (:ens contact)
:success-fn build-success-fn}]})))
(rf/merge {:db (assoc db
:contacts/new-identity
(->state (assoc contact :public-key pubkey)))}
(build-contact pubkey (:ens contact) false)))))
(re-frame/reg-event-fx :contacts/set-new-identity-success set-new-identity-success)
(defn- set-new-identity-error
[{:keys [db]} [{:keys [input err failure-fn]}]]
(rf/defn set-new-identity-error
{:events [:contacts/set-new-identity-error]}
[{:keys [db]} input err]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(let [state (cond
@@ -154,41 +163,21 @@
(string/includes? (:message err) "no such host")))
{:state :invalid :msg :t/lost-connection}
:else {:state :invalid})]
(merge {:db (assoc db :contacts/new-identity (merge contact state))}
(when failure-fn
(failure-fn)))))))
{:db (assoc db :contacts/new-identity (merge contact state))}))))
(re-frame/reg-event-fx :contacts/set-new-identity-error set-new-identity-error)
(defn- build-contact
[_ [{:keys [pubkey ens success-fn]}]]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(re-frame/dispatch [:contacts/build-contact-success
{:pubkey pubkey
:contact (data-store.contacts/<-rpc-js %)
:success-fn success-fn}])}]})
(re-frame/reg-event-fx :contacts/build-contact build-contact)
(defn- build-contact-success
[{:keys [db]} [{:keys [pubkey contact success-fn]}]]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when success-fn
(success-fn contact))))
(re-frame/reg-event-fx :contacts/build-contact-success build-contact-success)
(defn- clear-new-identity
(rf/defn clear-new-identity
{:events [:contacts/clear-new-identity :contacts/new-chat-focus]}
[{:keys [db]}]
{:db (dissoc db :contacts/new-identity)})
(re-frame/reg-event-fx :contacts/clear-new-identity clear-new-identity)
(rf/defn qr-code-scanned
{:events [:contacts/qr-code-scanned]}
[{:keys [db] :as cofx} scanned]
(rf/merge cofx
(set-new-identity scanned scanned)
(navigation/navigate-back)))
(defn set-new-identity-reconnected
(rf/defn set-new-identity-reconnected
[{:keys [db]}]
(let [input (get-in db [:contacts/new-identity :input])]
(re-frame/dispatch [:contacts/set-new-identity {:input input}])))
(rf/dispatch [:contacts/set-new-identity input])))
@@ -2,7 +2,6 @@
(:require
[cljs.test :refer-macros [deftest are]]
matcher-combinators.test
[re-frame.core :as re-frame]
[status-im.contexts.chat.home.add-new-contact.events :as events]))
(def user-ukey
@@ -91,8 +90,8 @@
:config {:NetworkId 1}}}})
(deftest set-new-identity-test
(with-redefs [re-frame/dispatch (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} [{:input i}]) edb)
(with-redefs [events/dispatcher (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} i nil) edb)
"" {:db db}
@@ -104,7 +103,6 @@
:id ukey
:type :public-key
:public-key ukey
:scanned ukey
:state :invalid
:msg :t/not-a-chatkey}))}
@@ -117,7 +115,6 @@
:type :ens
:ens ens-stateofus-eth
:public-key nil ; not yet...
:scanned ens
:state :resolve-ens}))
:effects.contacts/resolve-public-key-from-ens
{:chain-id 1
@@ -134,7 +131,6 @@
:id user-ckey
:type :compressed-key
:public-key nil ; not yet...
:scanned user-ckey
:state :decompress-key}))
:serialization/decompress-public-key
{:compressed-key user-ckey
@@ -13,8 +13,7 @@
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input %}]
300)}]]))
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity % %] 300)}]]))
(defn view
[]
@@ -59,8 +59,7 @@
paste-on-input #(clipboard/get-string
(fn [clipboard-text]
(reset! input-value clipboard-text)
(rf/dispatch [:contacts/set-new-identity
{:input clipboard-text}])))]
(rf/dispatch [:contacts/set-new-identity clipboard-text nil])))]
(let [{:keys [scanned]} (rf/sub [:contacts/new-identity])
empty-input? (and (string/blank? @input-value)
(string/blank? scanned))]
@@ -87,7 +86,7 @@
:value (or scanned @input-value)
:on-change-text (fn [new-text]
(reset! input-value new-text)
(as-> [:contacts/set-new-identity {:input new-text}] $
(as-> [:contacts/set-new-identity new-text nil] $
(if (string/blank? scanned)
(debounce/debounce-and-dispatch $ 600)
(rf/dispatch-sync $))))}]
@@ -65,7 +65,7 @@
item])))
(defn- view-internal
[{:keys [scroll-enabled? on-scroll close theme]}]
[{:keys [scroll-enabled on-scroll close theme]}]
(let [contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter])
selected-contacts-count (rf/sub [:selected-contacts-count])
selected-contacts (rf/sub [:group/selected-contacts])
@@ -105,7 +105,7 @@
:render-section-header-fn contact-list/contacts-section-header
:content-container-style {:padding-bottom 70}
:render-fn contact-item-render
:scroll-enabled scroll-enabled?
:scroll-enabled @scroll-enabled
:on-scroll on-scroll}])
(when contacts-selected?
[quo/button
@@ -61,7 +61,7 @@
(str (:title item) index))
(defn- f-album-selector
[{:keys [scroll-enabled? on-scroll]} album? selected-album top]
[{:keys [scroll-enabled on-scroll]} album? selected-album top]
(let [albums (rf/sub [:camera-roll/albums])
total-photos-count-android (rf/sub [:camera-roll/total-photos-count-android])
total-photos-count-ios (rf/sub [:camera-roll/total-photos-count-ios])
@@ -87,7 +87,7 @@
:content-container-style {:padding-top 64
:padding-bottom 40}
:key-fn key-fn
:scroll-enabled scroll-enabled?
:scroll-enabled @scroll-enabled
:on-scroll on-scroll
:style {:height window-height}}]]))
@@ -90,7 +90,7 @@
(inc (utils.collection/first-index #(= (:uri item) (:uri %)) @selected))]])]))
(defn photo-selector
[{:keys [scroll-enabled? on-scroll current-scroll close] :as sheet}]
[{:keys [scroll-enabled on-scroll current-scroll close] :as sheet}]
(rf/dispatch [:photo-selector/get-photos-for-selected-album])
(rf/dispatch [:photo-selector/camera-roll-get-albums])
(let [album? (reagent/atom false)
@@ -134,7 +134,7 @@
:padding-bottom (+ (safe-area/get-bottom) 100)
:padding-top 64}
:on-scroll on-scroll
:scroll-enabled scroll-enabled?
:scroll-enabled @scroll-enabled
:on-end-reached (fn []
(when (and (not loading?) has-next-page?)
(rf/dispatch [:photo-selector/camera-roll-loading-more true])
@@ -7,6 +7,10 @@
(def container
{:flex 1})
(def page-top
{:padding-vertical 12
:padding-horizontal screen-horizontal-padding})
(def section-title
{:padding-top 12
:padding-bottom 4
@@ -14,6 +18,11 @@
(defn bottom-actions
[]
{:padding-top 12
{:position :absolute
:background-color (colors/theme-colors colors/white colors/neutral-95)
:bottom 0
:left 0
:right 0
:padding-horizontal screen-horizontal-padding
:background-color (colors/theme-colors colors/white colors/neutral-95)})
:padding-vertical 12
:flex 1})
@@ -28,7 +28,7 @@
highest-role-text (i18n/label (communities.utils/role->translation-key
highest-permission-role
:t/member))]
[rn/safe-area-view {:style style/container}
[rn/view {:style style/container}
[quo/page-nav
{:text-align :left
:icon-name :i/close
@@ -2,7 +2,6 @@
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
@@ -28,37 +27,32 @@
:collectible-img-src (resources/get-mock-image :collectible))
(= type constants/community-token-type-erc20)
(assoc :amount (str (money/token->unit amount decimals))
(assoc :amount (str (money/with-precision (money/token->unit amount decimals) 3))
:token (:symbol balance)))))
(defn- account-item
[{:keys [color address name emoji]} _ _
{:keys [selected-addresses community-id share-all-addresses? community-color]}]
[{:keys [customization-color address name emoji]} _ _ [selected-addresses community-id]]
(let [balances (rf/sub [:communities/permissioned-balances-by-address community-id address])]
[quo/account-permissions
{:account {:name name
:address address
:emoji emoji
:customization-color color}
:token-details (balances->components-props balances)
:checked? (contains? selected-addresses address)
:disabled? share-all-addresses?
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
address community-id])
:container-style {:margin-bottom 8}
:customization-color community-color}]))
{:account {:name name
:address address
:emoji emoji
:customization-color customization-color}
:token-details (balances->components-props balances)
:checked? (contains? selected-addresses address)
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
address community-id])
:container-style {:margin-bottom 8}}]))
(defn view
[{:keys [scroll-enabled? on-scroll]}]
[]
(let [{id :community-id} (rf/sub [:get-screen-params])]
(rf/dispatch [:communities/get-permissioned-balances id])
(fn []
(let [{:keys [name color images]} (rf/sub [:communities/community id])
{:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id])
accounts (rf/sub [:wallet/accounts-without-watched-accounts])
accounts (rf/sub [:wallet/accounts-with-customization-color])
selected-addresses (rf/sub [:communities/selected-permission-addresses id])
share-all-addresses? (rf/sub [:communities/share-all-addresses? id])
unsaved-address-changes? (rf/sub [:communities/unsaved-address-changes? id])
highest-role-text (when highest-permission-role
(i18n/label (communities.utils/role->translation-key
highest-permission-role)))]
@@ -69,31 +63,14 @@
:context-tag-type :community
:community-name name
:button-icon :i/info
:button-type :grey
:on-button-press not-implemented/alert
:community-logo (get-in images [:thumbnail :uri])
:customization-color color}]
[quo/category
{:list-type :settings
:data [{:title (i18n/label :t/share-all-current-and-future-addresses)
:action :selector
:action-props {:on-change #(rf/dispatch
[:communities/toggle-share-all-addresses
id])
:customization-color color
:checked? share-all-addresses?}}]
:container-style {:padding-bottom 16}}]
[gesture/flat-list
[rn/flat-list
{:render-fn account-item
:render-data {:selected-addresses selected-addresses
:community-id id
:share-all-addresses? share-all-addresses?
:community-color color}
:content-container-style {:padding-horizontal 20}
:scroll-enabled scroll-enabled?
:on-scroll on-scroll
:render-data [selected-addresses id]
:content-container-style {:padding 20}
:key-fn :address
:data accounts}]
@@ -129,9 +106,7 @@
[quo/button
{:container-style {:flex 1}
:customization-color color
:disabled? (or (empty? selected-addresses)
(not highest-permission-role)
(not unsaved-address-changes?))
:disabled? (empty? selected-addresses)
:on-press (fn []
(rf/dispatch [:communities/update-previous-permission-addresses id])
(rf/dispatch [:navigate-back]))}
@@ -3,6 +3,5 @@
(def community-rule
{:flex 1
:align-items :flex-start
:padding-top 8
:margin-bottom 12
:padding-vertical 8
:padding-horizontal 20})
@@ -8,7 +8,8 @@
(defn token-requirements
[]
(fn [id]
(let [{:keys [can-request-access? tokens]} (rf/sub [:community/token-gated-overview id])]
(let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
[rn/view {:style {:padding-horizontal 12}}
[quo/text {:weight :medium}
(if can-request-access?
@@ -16,6 +17,7 @@
(i18n/label :t/you-not-eligible-to-join))]
[quo/text {:style {:padding-bottom 18} :size :paragraph-2}
(if can-request-access?
(i18n/label :t/you-hodl)
(i18n/label :t/you-hold-number-of-hold-tokens-of-these
{:number-of-hold-tokens number-of-hold-tokens})
(i18n/label :t/you-must-hold))]
[quo/token-requirement-list {:tokens tokens}]])))
+11 -34
View File
@@ -12,7 +12,6 @@
status-im.contexts.communities.actions.addresses-for-permissions.events
status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events
[status-im.contexts.communities.utils :as utils]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
@@ -164,16 +163,15 @@
(defn initialize-permission-addresses
[{:keys [db]} [community-id]]
(when community-id
(let [accounts (utils/sorted-non-watch-only-accounts db)
addresses (set (map :address accounts))]
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
addresses (set (map :address sorted-accounts))]
{:db (update-in db
[:communities community-id]
assoc
:previous-share-all-addresses? true
:share-all-addresses? true
:previous-permission-addresses addresses
:selected-permission-addresses addresses
:airdrop-address (:address (first accounts)))})))
:airdrop-address (:address (first sorted-accounts)))})))
(rf/reg-event-fx :communities/initialize-permission-addresses
initialize-permission-addresses)
@@ -181,18 +179,17 @@
(defn update-previous-permission-addresses
[{:keys [db]} [community-id]]
(when community-id
(let [accounts (utils/sorted-non-watch-only-accounts db)
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
selected-permission-addresses (get-in db
[:communities community-id
:selected-permission-addresses])
selected-accounts (filter #(contains? selected-permission-addresses (:address %))
accounts)
current-airdrop-address (get-in db [:communities community-id :airdrop-address])
share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])]
sorted-accounts)
current-airdrop-address (get-in db [:communities community-id :airdrop-address])]
{:db (update-in db
[:communities community-id]
assoc
:previous-share-all-addresses? share-all-addresses?
:previous-permission-addresses selected-permission-addresses
:airdrop-address (if (contains? selected-permission-addresses
current-airdrop-address)
@@ -221,32 +218,12 @@
(rf/reg-event-fx :communities/toggle-selected-permission-address
toggle-selected-permission-address)
(defn toggle-share-all-addresses
[{:keys [db]} [community-id]]
(let [share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])
accounts (utils/sorted-non-watch-only-accounts db)
addresses (set (map :address accounts))]
{:db (update-in db
[:communities community-id]
(fn [community]
(-> community
(assoc :share-all-addresses? (not share-all-addresses?))
(cond-> (not share-all-addresses?)
(assoc :selected-permission-addresses addresses)))))}))
(rf/reg-event-fx :communities/toggle-share-all-addresses
toggle-share-all-addresses)
(rf/reg-event-fx :communities/reset-selected-permission-addresses
(fn [{:keys [db]} [community-id]]
(when community-id
{:db (update-in db
[:communities community-id]
assoc
:selected-permission-addresses
(get-in db [:communities community-id :previous-permission-addresses])
:share-all-addresses?
(get-in db [:communities community-id :previous-share-all-addresses?]))
{:db (assoc-in db
[:communities community-id :selected-permission-addresses]
(get-in db [:communities community-id :previous-permission-addresses]))
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
(rf/reg-event-fx :communities/share-community-channel-url-with-data
@@ -16,8 +16,6 @@
expected-db {:db (update-in (:db initial-db)
[:communities community-id]
assoc
:share-all-addresses? true
:previous-share-all-addresses? true
:previous-permission-addresses #{"0x1" "0x2"}
:selected-permission-addresses #{"0x1" "0x2"}
:airdrop-address "0x1")}]
@@ -41,16 +39,12 @@
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
:selected-permission-addresses #{"0x1" "0x2"
"0x3"}
:share-all-addresses? true
:previous-share-all-addresses? false
:airdrop-address "0x1"}}}}
expected-db {:db {:wallet wallet
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"
"0x3"}
:selected-permission-addresses #{"0x1" "0x2"
"0x3"}
:share-all-addresses? true
:previous-share-all-addresses? true
:airdrop-address "0x1"}}}}]
(is
(match? expected-db
@@ -67,40 +61,6 @@
(match? expected-db
(events/update-previous-permission-addresses initial-db [community-id]))))))
(deftest toggle-share-all-addresses-test
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
:position 0}
"0x2" {:address "0x2"
:position 1}}}
:communities {community-id {:share-all-addresses? true
:previous-share-all-addresses? true
:previous-permission-addresses #{"0x1"}
:selected-permission-addresses #{"0x1"}
:airdrop-address "0x1"}}}}
expected-db (update-in initial-db
[:db :communities community-id]
assoc
:previous-share-all-addresses? true
:share-all-addresses?
false)]
(is (match? expected-db (events/toggle-share-all-addresses initial-db [community-id]))))
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
:position 0}
"0x2" {:address "0x2"
:position 1}}}
:communities {community-id {:share-all-addresses? false
:previous-share-all-addresses? false
:previous-permission-addresses #{"0x1"}
:selected-permission-addresses #{"0x1"}
:airdrop-address "0x1"}}}}
expected-db (update-in initial-db
[:db :communities community-id]
assoc
:selected-permission-addresses #{"0x1" "0x2"}
:previous-share-all-addresses? false
:share-all-addresses? true)]
(is (match? expected-db (events/toggle-share-all-addresses initial-db [community-id])))))
(deftest fetch-community
(testing "with community id"
(testing "update fetching indicator in db"
@@ -10,16 +10,16 @@
{:db (-> db
(assoc-in [:community-channels-permissions community-id]
(data-store/rpc->channel-permissions (:channels response)))
(assoc-in [:communities/channel-permissions-check community-id] false))}))
(assoc-in [:communities community-id :checking-all-channels-permissions?] false))}))
(rf/reg-event-fx :communities/check-all-community-channels-permissions-failed
(fn [{:keys [db]} [community-id]]
{:db (assoc-in db [:communities/channel-permissions-check community-id] false)}))
{:db (assoc-in db [:communities community-id :checking-all-channels-permissions?] false)}))
(rf/reg-event-fx :communities/check-all-community-channels-permissions
(fn [{:keys [db]} [community-id]]
(when (get-in db [:communities community-id])
{:db (assoc-in db [:communities/channel-permissions-check community-id] true)
{:db (assoc-in db [:communities community-id :checking-all-channels-permissions?] true)
:fx [[:json-rpc/call
[{:method "wakuext_checkAllCommunityChannelsPermissions"
:params [{:CommunityID community-id}]
@@ -38,19 +38,21 @@
(let [token-permissions-check (cond-> result
based-on-client-selection? (assoc :based-on-client-selection? true))]
{:db (-> db
(assoc-in [:communities/permissions-check community-id]
{:checking? false
:check token-permissions-check}))})))
(assoc-in [:communities community-id :checking-permissions?] false)
(assoc-in [:communities community-id :token-permissions-check]
token-permissions-check))})))
(rf/reg-event-fx :communities/check-permissions-to-join-community-failed
(fn [{:keys [db]} [community-id]]
{:db (assoc-in db [:communities/permissions-check community-id :checking?] false)}))
{:db (assoc-in db [:communities community-id :checking-permissions?] false)}))
(rf/reg-event-fx :communities/check-permissions-to-join-community
(fn [{:keys [db]} [community-id addresses based-on-client-selection?]]
(when-let [community (get-in db [:communities community-id])]
(when-not (:checking-permissions? community)
{:db (assoc-in db [:communities/permissions-check community-id :checking?] true)
{:db (-> db
(assoc-in [:communities community-id :checking-permissions?] true)
(assoc-in [:communities community-id :can-request-access?] false))
:json-rpc/call [{:method "wakuext_checkPermissionsToJoinCommunity"
:params [(cond-> {:communityId community-id}
addresses
@@ -110,82 +110,66 @@
[rn/view
[quo/icon :i/info {:no-color true}]]])
(defn- network-not-supported
[]
[quo/text (i18n/label :t/network-not-supported)])
(defn- request-access-button
[id color]
[quo/button
{:on-press (if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection
{:community-id id}])
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
:accessibility-label :show-request-to-join-screen-button
:customization-color color
:icon-left :i/communities}
(i18n/label :t/request-to-join)])
(defn- token-requirements
[{:keys [id color role-permissions?]}]
[{:keys [id color]}]
(let [{:keys [can-request-access?
no-member-permission?
tokens
networks-not-supported?
number-of-hold-tokens tokens
highest-permission-role]} (rf/sub [:community/token-gated-overview id])
highest-role-text
(i18n/label
(communities.utils/role->translation-key highest-permission-role :t/member))]
(cond
networks-not-supported?
[network-not-supported]
(or (not role-permissions?) no-member-permission?)
[request-access-button id color]
:else
[rn/view {:style (style/token-gated-container)}
[rn/view
{:style {:padding-horizontal 12
:flex-direction :row
:align-items :center
:justify-content :space-between
:flex 1}}
[quo/text {:weight :medium}
(if (and can-request-access? highest-permission-role)
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
(i18n/label :t/you-not-eligible-to-join))]
[info-button]]
[rn/view {:style (style/token-gated-container)}
[rn/view
{:style {:padding-horizontal 12
:flex-direction :row
:align-items :center
:justify-content :space-between
:flex 1}}
[quo/text {:weight :medium}
(if can-request-access?
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
(i18n/label :t/you-not-eligible-to-join))]
[info-button]]
(when (pos? number-of-hold-tokens)
[quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2}
(if can-request-access?
(i18n/label :t/you-hodl)
(i18n/label :t/you-must-hold))]
[quo/token-requirement-list
{:tokens tokens
:padding? true}]
[quo/button
{:on-press (if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection
{:community-id id}])
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
:accessibility-label :join-community-button
:customization-color color
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
:disabled? (not can-request-access?)
:icon-left (if can-request-access? :i/unlocked :i/locked)}
(i18n/label :t/join-open-community)]])))
(i18n/label :t/you-hold-number-of-hold-tokens-of-these
{:number-of-hold-tokens number-of-hold-tokens})
(i18n/label :t/you-must-hold))])
[quo/token-requirement-list
{:tokens tokens
:padding? true}]
[quo/button
{:on-press (if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection
{:community-id id}])
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
:accessibility-label :join-community-button
:customization-color color
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
:disabled? (not can-request-access?)
:icon-left (if can-request-access? :i/unlocked :i/locked)}
(i18n/label :t/join-open-community)]]))
(defn- join-community
[{:keys [id joined permissions role-permissions? can-join?] :as community}]
[{:keys [id color joined permissions role-permissions? can-join?] :as community}]
(let [pending? (rf/sub [:communities/my-pending-request-to-join id])
access-type (get-access-type (:access permissions))
unknown-access? (= access-type :unknown-access)
invite-only? (= access-type :invite-only)]
[:<>
(when-not (or joined pending? invite-only? unknown-access?)
[token-requirements community])
(if role-permissions?
[token-requirements community]
[quo/button
{:on-press (if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection
{:community-id id}])
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
:accessibility-label :show-request-to-join-screen-button
:customization-color color
:icon-left :i/communities}
(i18n/label :t/request-to-join)]))
(when (not (or pending? role-permissions? can-join?))
[quo/text
{:size :paragraph-2
@@ -253,17 +237,15 @@
:description-accessibility-label :community-description}])
(defn- community-content
[id]
[{:keys [id]}]
(rf/dispatch [:communities/check-all-community-channels-permissions id])
(fn [id
(fn [{:keys [name description joined spectated images tags color id membership-permissions?]
:as community}
{:keys [on-category-layout
collapsed?
on-first-channel-height-changed]}]
(let [{:keys [name description joined spectated images tags color id membership-permissions?]
:as community}
(rf/sub [:communities/community id])
joined-or-spectated (or joined spectated)
chats-by-category (rf/sub [:communities/categorized-channels id])]
(let [joined-or-spectated (or joined spectated)
chats-by-category (rf/sub [:communities/categorized-channels id])]
[:<>
[rn/view {:style style/community-content-container}
(when-not collapsed?
@@ -313,24 +295,20 @@
(and (>= scroll-height (+ height first-channel-height))
category)))))
(defn- community-scroll-page
[{:keys [joined]}]
(let [scroll-height (reagent/atom 0)
categories-heights (reagent/atom {})
first-channel-height (reagent/atom 0)
;; We track the initial value of joined
;; as we open the page to avoid switching
;; from not collapsed to collapsed if the
;; user is on this page
(defn- community-scroll-page
[_ initial-joined? _ _]
(let [scroll-height (reagent/atom 0)
categories-heights (reagent/atom {})
first-channel-height (reagent/atom 0)
on-category-layout (partial add-category-height categories-heights)
on-first-channel-height-changed (fn [height categories]
(swap! categories-heights select-keys categories)
(reset! first-channel-height height))]
(fn [id joined name images]
initial-joined? joined]
(fn [{:keys [id name images] :as community}]
(let [cover {:uri (get-in images [:banner :uri])}
logo {:uri (get-in images [:thumbnail :uri])}
collapsed? (and initial-joined? joined)
collapsed? (and initial-joined? (:joined community))
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))]
[scroll-page/scroll-page
{:cover-image cover
@@ -353,22 +331,24 @@
@first-channel-height
@categories-heights)}]}
[community-content
id
{:on-category-layout on-category-layout
community
{:on-category-layout (partial add-category-height categories-heights)
:collapsed? collapsed?
:on-first-channel-height-changed
;; Here we set the height of the component and we filter out the categories, as some
;; might have been removed.
on-first-channel-height-changed}]]))))
(fn [height categories]
(swap! categories-heights select-keys categories)
(reset! first-channel-height height))}]]))))
(defn- community-card-page-view
[id]
(let [{:keys [id joined name images]
(let [{:keys [id joined]
:as community} (rf/sub [:communities/community id])]
(when community
(when joined
(rf/dispatch [:activity-center.notifications/dismiss-community-overview id]))
[community-scroll-page id joined name images])))
[community-scroll-page community])))
(defn view
[id]
@@ -11,10 +11,3 @@
constants/community-token-permission-become-admin :t/admin
constants/community-token-permission-become-member :t/member
fallback-to)))
(defn sorted-non-watch-only-accounts
[db]
(->> (get-in db [:wallet :accounts])
(vals)
(remove :watch-only?)
(sort-by :position)))
@@ -8,8 +8,30 @@
(def heading-subtitle {:color colors/white})
(def heading-title (assoc heading-subtitle :margin-bottom 8))
(def info-message
{:margin-top 8})
(def label-container
{:margin-top 8
:flex-direction :row
:align-items :center
:height 16})
(def label-icon
{:width 16
:height 18
:margin-right 4})
(defn label-icon-color
[status]
(get {:neutral colors/neutral-40
:success colors/success-60
:danger colors/danger-60}
status))
(defn label-color
[status]
(let [colors {:neutral colors/white-opa-70
:success colors/success-60
:danger colors/danger-60}]
{:color (get colors status)}))
(def space-between-inputs {:height 16})
@@ -2,7 +2,6 @@
(:require
[oops.core :refer [ocall]]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
@@ -34,25 +33,24 @@
(dissoc :hint)
(assoc :type :password
:blur? true))]
[rn/view {:style style/info-message}
[rn/view {:style style/label-container}
(when shown
[quo/info-message
{:type status
:size :default
:icon (if (= status :success) :i/positive-state :i/info)
:text-color (when (= status :default)
colors/white-70-blur)
:icon-color (when (= status :default)
colors/white-70-blur)
:style {}}
text])]])
[:<>
[quo/icon (if (= status :success) :i/check-circle :i/info)
{:container-style style/label-icon
:color (style/label-icon-color status)
:size 16}]
[quo/text
{:style (style/label-color status)
:size :paragraph-2}
text]])]])
(defn password-inputs
[{:keys [passwords-match? on-change-password on-change-repeat-password on-input-focus
password-long-enough? empty-password? show-password-validation?
on-blur-repeat-password]}]
(let [hint-1-status (if password-long-enough? :success :default)
hint-2-status (if passwords-match? :success :error)
(let [hint-1-status (if password-long-enough? :success :neutral)
hint-2-status (if passwords-match? :success :danger)
hint-2-text (if passwords-match?
(i18n/label :t/password-creation-match)
(i18n/label :t/password-creation-dont-match))
@@ -1,5 +1,6 @@
(ns status-im.contexts.preview.quo.tags.collectible-tag
(:require
[oops.core :refer [oget]]
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
@@ -15,7 +16,9 @@
:value "Size 32"}]}
{:key :options
:type :select
:options [{:key :add
:options [{:key false
:value false}
{:key :add
:value :add}
{:key :hold
:value :hold}]}
@@ -28,11 +31,16 @@
(defn view
[]
(let [state (reagent/atom {:size :size-24
:collectible-name "Collectible"
:collectible-id "#123"
:collectible-img-src (resources/mock-images :collectible)
:blur? false})]
(let [state (reagent/atom {:size :size-24
:collectible-name "Collectible"
:collectible-id "#123"
:collectible-img-src (resources/mock-images :collectible)
:options false
:blur? false
:container-width 0})
on-layout #(swap! state assoc
:container-width
(oget % :nativeEvent :layout :width))]
(fn []
[preview/preview-container
{:state state
@@ -40,4 +48,4 @@
:show-blur-background? true
:descriptor descriptor}
[rn/view {:style {:align-items :center}}
[quo/collectible-tag @state]]])))
[quo/collectible-tag (assoc @state :on-layout on-layout)]]])))
@@ -24,8 +24,7 @@
{:key :empty-token-list}
{:key :1-token}
{:key :3-tokens}
{:key :5-tokens}]}
(preview/customization-color-option {:key :customization-color})])
{:key :5-tokens}]}])
(def ^:private token-details
{:no-tokens nil
@@ -51,25 +50,23 @@
(defn view
[]
(let [state (reagent/atom {:name "Trip to Vegas"
:address "0x2f0fbf0a93c5999e9b4410848403a02b38983eb2"
:emoji "😊"
:account-color :blue
:token-details :no-tokens
:customization-color :blue
:keycard? true
:checked? true
:disabled? false})]
(let [state (reagent/atom {:name "Trip to Vegas"
:address "0x2f0fbf0a93c5999e9b4410848403a02b38983eb2"
:emoji "😊"
:account-color :blue
:token-details :no-tokens
:keycard? true
:checked? true
:disabled? false})]
(fn []
[preview/preview-container {:state state :descriptor descriptor}
[quo/account-permissions
{:account {:name (:name @state)
:address (:address @state)
:emoji (:emoji @state)
:customization-color (:account-color @state)}
:token-details (token-details (:token-details @state))
:keycard? (:keycard? @state)
:checked? (:checked? @state)
:disabled? (:disabled? @state)
:customization-color (:customization-color @state)
:on-change (fn [checked?] (swap! state assoc :checked? checked?))}]])))
{:account {:name (:name @state)
:address (:address @state)
:emoji (:emoji @state)
:customization-color (:account-color @state)}
:token-details (token-details (:token-details @state))
:keycard? (:keycard? @state)
:checked? (:checked? @state)
:disabled? (:disabled? @state)
:on-change (fn [checked?] (swap! state assoc :checked? checked?))}]])))
@@ -69,7 +69,7 @@
(stop-interval)))
[(:state @state)])
[preview/preview-container {:state state :descriptor descriptor}
[quo/confirmation-progress
[quo/confirmation-propgress
(assoc @state
:counter
@counter)]]))
+1 -1
View File
@@ -43,7 +43,7 @@
:upstreamConfig config/default-network-rpc-url
:networkId config/default-network-id
:currentNetwork config/default-network
:wakuV2LightClient false
:wakuV2LightClient true
:previewPrivacy config/blank-preview?})))
(defn strip-file-prefix
@@ -1,22 +0,0 @@
(ns status-im.contexts.profile.edit.bio.events
(:require [utils.i18n :as i18n]
[utils.re-frame :as rf]))
(rf/reg-event-fx :profile/edit-profile-bio-success
(fn [_]
{:fx [[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label :t/bio-added)}]]]}))
(defn edit-profile-bio
[{:keys [db]} [bio]]
{:db (assoc-in db [:profile/profile :bio] bio)
:fx [[:json-rpc/call
[{:method "wakuext_setBio"
:params [bio]
:on-success [:profile/edit-profile-bio-success]}]]]})
(rf/reg-event-fx :profile/edit-bio edit-profile-bio)
@@ -1,15 +0,0 @@
(ns status-im.contexts.profile.edit.bio.events-test
(:require [cljs.test :refer [deftest is]]
matcher-combinators.test
[status-im.contexts.profile.edit.bio.events :as sut]))
(deftest edit-bio-test
(let [new-bio "New Bio text"
cofx {:db {:profile/profile {:bio "Old Bio text"}}}
expected {:db {:profile/profile {:bio new-bio}}
:fx [[:json-rpc/call
[{:method "wakuext_setBio"
:params [new-bio]
:on-success [:profile/edit-profile-bio-success]}]]]}]
(is (match? expected
(sut/edit-profile-bio cofx [new-bio])))))
@@ -1,17 +0,0 @@
(ns status-im.contexts.profile.edit.bio.style)
(defn page-wrapper
[insets]
{:padding-top (:top insets)
:padding-bottom (:bottom insets)
:padding-horizontal 1
:flex 1})
(def screen-container
{:flex 1
:padding-top 14
:padding-horizontal 20
:justify-content :space-between})
(def button-wrapper
{:margin-vertical 12})
@@ -1,71 +0,0 @@
(ns status-im.contexts.profile.edit.bio.view
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.validation.profile :as profile-validator]
[status-im.constants :as constants]
[status-im.contexts.profile.edit.bio.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [insets (safe-area/get-insets)
profile (rf/sub [:profile/profile-with-image])
customization-color (rf/sub [:profile/customization-color])
profile-bio (:bio profile)
unsaved-bio (reagent/atom profile-bio)
error-msg (reagent/atom nil)
typing? (reagent/atom false)
validate-bio (debounce/debounce (fn [bio]
(reset! error-msg
(profile-validator/validation-bio bio))
(reset! typing? false))
300)
on-change-text (fn [s]
(reset! typing? true)
(reset! unsaved-bio s)
(validate-bio s))]
(fn []
[quo/overlay
{:type :shell
:container-style (style/page-wrapper insets)}
[quo/page-nav
{:key :header
:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])}]
[rn/keyboard-avoiding-view
{:key :content
:style style/screen-container}
[rn/view {:style {:gap 22}}
[quo/text-combinations {:title (i18n/label :t/bio)}]
[quo/input
{:theme :dark
:blur? true
:multiline? true
:error? (not (string/blank? @error-msg))
:container-style {:margin-bottom -11}
:default-value @unsaved-bio
:auto-focus true
:char-limit constants/profile-bio-max-length
:label (i18n/label :t/profile-bio)
:placeholder (i18n/label :t/something-about-you)
:on-change-text on-change-text}]
(when-not (string/blank? @error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info}
@error-msg])]
[rn/view {:style style/button-wrapper}
[quo/button
{:type :primary
:customization-color customization-color
:on-press (fn []
(rf/dispatch [:profile/edit-bio @unsaved-bio]))
:disabled? (boolean (or @typing? (not (string/blank? @error-msg))))}
(i18n/label :t/save-bio)]]]])))
@@ -1,6 +1,5 @@
(ns status-im.contexts.profile.edit.list-items
(:require [legacy.status-im.utils.core :as utils]
[quo.foundations.colors :as colors]
(:require [quo.foundations.colors :as colors]
[status-im.common.not-implemented :as not-implemented]
[status-im.contexts.profile.edit.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
@@ -11,7 +10,6 @@
[theme]
(let [profile (rf/sub [:profile/profile-with-image])
customization-color (rf/sub [:profile/customization-color])
bio (:bio profile)
full-name (profile.utils/displayed-name profile)]
[{:label (i18n/label :t/profile)
:items [{:title (i18n/label :t/name)
@@ -22,10 +20,8 @@
:action :arrow
:container-style style/item-container}
{:title (i18n/label :t/bio)
:on-press #(rf/dispatch [:open-modal :edit-bio])
:on-press not-implemented/alert
:blur? true
:label :text
:label-props (utils/truncate-str bio 15)
:action :arrow
:container-style style/item-container}
{:title (i18n/label :t/accent-colour)
@@ -4,7 +4,6 @@
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.contexts.profile.edit.accent-colour.events]
[status-im.contexts.profile.edit.bio.events]
[status-im.contexts.profile.edit.header.events]
[status-im.contexts.profile.edit.name.events]
[status-im.contexts.profile.login.events :as profile.login]
@@ -1,34 +1,36 @@
(ns status-im.contexts.profile.settings.header.avatar
(ns ^:workletize status-im.contexts.profile.settings.header.avatar
(:require [quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.reanimated :as reanimated]
[status-im.contexts.profile.settings.header.style :as style]))
(def scroll-animation-input-range [0 50])
(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.4]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)
theme (quo.theme/get-theme)]
[reanimated/view
{:style (style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
(let [avatar-total-size 88
border-height 4
translation-to-bottom (fn [scale inverse-scale]
(js* "'worklet'")
(let [current-avatar-size (* avatar-total-size (- 1 scale))
current-center (/ current-avatar-size 2)]
(* current-center inverse-scale)))
transform (reanimated/use-animated-style
(fn []
(js* "'worklet'")
(let [scale (reanimated/interpolate*
(.-value scroll-y)
#js [0 48]
#js [1 0.4]
"clamp")
inverse-scale (/ 1 scale)
translation (translation-to-bottom scale inverse-scale)
bottom (* border-height inverse-scale (- 1 scale))]
#js
{:transform #js
[#js {:scale scale}
#js {:translateX (- translation)}
#js {:translateY (- translation bottom)}]})))
theme (quo.theme/get-theme)]
[reanimated/view {:style [transform (style/avatar-container theme)]}
[quo/user-avatar
{:full-name full-name
:online? online?
@@ -1,10 +1,11 @@
(ns status-im.contexts.profile.settings.header.header-shape
(ns ^:workletize status-im.contexts.profile.settings.header.header-shape
(:require [quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.svg :as svg]
[status-im.contexts.profile.settings.header.style :as style]))
(defn left-radius
[background-color]
[svg/svg {:width "20" :height "20" :viewBox "0 0 20 20" :fill "none"}
@@ -21,13 +22,17 @@
(defn f-view
[{:keys [scroll-y customization-color theme]}]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity-animation (reanimated/interpolate scroll-y
[0 45 50]
[1 1 0])]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity (reanimated/use-animated-style
(fn []
(js* "'worklet'")
#js
{:opacity (reanimated/interpolate* (.-value scroll-y)
#js [0 45 50]
#js [1 1 0])}))]
[:<>
[rn/view {:style (style/header-middle-shape background-color)}]
[reanimated/view {:style (style/radius-container opacity-animation)}
[reanimated/view {:style [opacity style/radius-container]}
[left-radius background-color]
[right-radius background-color]]]))
@@ -27,19 +27,13 @@
:height 48
:flex-grow 1})
(defn radius-container
[opacity-animation]
{:opacity opacity-animation
:flex-direction :row
(def radius-container
{:flex-direction :row
:justify-content :space-between})
(defn avatar-container
[theme scale-animation top-margin-animation side-margin-animation]
[{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 100}])
[theme]
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 44})
@@ -20,7 +20,6 @@
[:visibility-status-updates/visibility-status-update
public-key])
customization-color (rf/sub [:profile/customization-color])
bio (:bio profile)
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
emoji-string (string/join emoji-hash)
@@ -54,7 +53,6 @@
{:title-accessibility-label :username
:container-style style/title-container
:emoji-hash emoji-string
:description bio
:title full-name}]]))
(def view (quo.theme/with-theme f-view))
@@ -40,10 +40,9 @@
:size 32
:accessibility-label :activity-center-open-more
:on-press #(rf/dispatch [:show-bottom-sheet
{:content drawer/options
:theme :dark
:shell? true
:blur-radius 20}])}
{:content drawer/options
:theme :dark
:shell? true}])}
:i/options]]
[quo/text
{:size :heading-1
@@ -1,126 +0,0 @@
(ns status-im.contexts.shell.qr-reader.view
(:require
[clojure.string :as string]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[status-im.common.router :as router]
[status-im.common.scan-qr-code.view :as scan-qr-code]
[status-im.common.validators :as validators]
[status-im.contexts.communities.events]
[status-im.contexts.wallet.common.validation :as wallet-validation]
[utils.debounce :as debounce]
[utils.ethereum.eip.eip681 :as eip681]
[utils.i18n :as i18n]
[utils.url :as url]))
(def invalid-qr-toast
{:type :negative
:theme :dark
:text (i18n/label :t/invalid-qr)})
(defn- text-for-url-path?
[text path]
(some #(string/starts-with? text %) (router/path-urls path)))
(defn- extract-id
[scanned-text]
(let [index (string/index-of scanned-text "#")]
(subs scanned-text (inc index))))
(defn eth-address?
[scanned-text]
(wallet-validation/eth-address? scanned-text))
(defn eip681-address?
[scanned-text]
(-> scanned-text
eip681/parse-uri
:address
boolean))
(defn pairing-qr-code?
[_]
false)
(defn wallet-connect-code?
[scanned-text]
(string/starts-with? scanned-text "wc:"))
(defn url?
[scanned-text]
(url/url? scanned-text))
(defn load-and-show-profile
[address]
(debounce/debounce-and-dispatch
[:contacts/set-new-identity
{:input address
:build-success-fn (fn [{:keys [public-key ens-name]}]
{:dispatch-n [[:chat.ui/show-profile public-key ens-name]
[:contacts/clear-new-identity]]})
:failure-fn (fn []
{:dispatch [:toasts/upsert invalid-qr-toast]})}]
300))
(defn show-invalid-qr-toast
[]
(debounce/debounce-and-dispatch
[:toasts/upsert invalid-qr-toast]
300))
(defn on-qr-code-scanned
[scanned-text]
(cond
(text-for-url-path? scanned-text router/community-with-data-path)
;; TODO: https://github.com/status-im/status-mobile/issues/18743
nil
(text-for-url-path? scanned-text router/channel-path)
;; TODO: https://github.com/status-im/status-mobile/issues/18743
nil
(text-for-url-path? scanned-text router/user-with-data-path)
(let [address (extract-id scanned-text)]
(load-and-show-profile address))
(or (validators/valid-public-key? scanned-text)
(validators/valid-compressed-key? scanned-text))
(load-and-show-profile scanned-text)
(eth-address? scanned-text)
(debounce/debounce-and-dispatch [:navigate-to :wallet-accounts scanned-text] 300)
(eip681-address? scanned-text)
(do
(debounce/debounce-and-dispatch [:wallet-legacy/request-uri-parsed
(eip681/parse-uri scanned-text)]
300)
(debounce/debounce-and-dispatch [:navigate-change-tab :wallet-stack] 300))
(pairing-qr-code? scanned-text)
;; TODO: https://github.com/status-im/status-mobile/issues/18744
nil
(wallet-connect-code? scanned-text)
;; WalletConnect is not working yet, this flow should be updated once WalletConnect is ready
nil
(url? scanned-text)
(debounce/debounce-and-dispatch [:browser.ui/open-url scanned-text] 300)
:else
(show-invalid-qr-toast)))
(defn- f-internal-view
[]
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)]
[:<>
(when keyboard-shown
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:on-success-scan on-qr-code-scanned}]]))
(defn view
[]
[:f> f-internal-view])
+1 -3
View File
@@ -29,9 +29,7 @@
:background :blur
:size 32
:accessibility-label :shell-scan-button
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :shell-qr-reader]))}
:on-press #(rf/dispatch [:navigate-back])}
:i/scan]]
[quo/text
{:size :heading-1
@@ -31,3 +31,4 @@
(rf/dispatch [:wallet/bridge-select-token
{:token token
:stack-id :wallet-bridge}]))}]])))
@@ -1,4 +0,0 @@
(ns status-im.contexts.wallet.account.bridge-send.style)
(def bridge-send-wrapper
{:flex 1})
@@ -1,19 +0,0 @@
(ns status-im.contexts.wallet.account.bridge-send.view
(:require
[quo.theme]
[react-native.core :as rn]
[status-im.contexts.wallet.account.bridge-send.style :as style]
[status-im.contexts.wallet.send.input-amount.view :as input-amount]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- view-internal
[]
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:button-one-label (i18n/label :t/confirm-bridge)
:button-one-props {:icon-left :i/bridge}
:on-navigate-back (fn []
(rf/dispatch [:navigate-back-within-stack :wallet-bridge-send]))}]])
(def view (quo.theme/with-theme view-internal))
@@ -28,10 +28,7 @@
{:label (name network-name)
:network-image (quo.resources/get-network (:network-name network))
:token-value (str crypto-formatted " " (:symbol token))
:fiat-value fiat-formatted
:on-press #(rf/dispatch [:wallet/select-bridge-network
{:network-chain-id chain-id
:stack-id :wallet-bridge}])}])))
:fiat-value fiat-formatted}])))
(defn- view-internal
[]
@@ -53,7 +50,7 @@
:accessibility-label :top-bar}]
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/bridge-to {:name (string/upper-case (str (:name token)))})}]
:title (i18n/label :t/bridge-to {:name (string/upper-case (str (:label token)))})}]
[rn/view style/content-container
[bridge-token-component (assoc mainnet :network-name :t/mainnet) account-token]]
@@ -38,9 +38,7 @@
(let [{:keys [name color formatted-balance
watch-only?]} (rf/sub [:wallet/current-viewing-account])]
[rn/view {:style {:flex 1}}
[account-switcher/view
{:type :wallet-networks
:on-press #(rf/dispatch [:wallet/close-account-page])}]
[account-switcher/view {:on-press #(rf/dispatch [:wallet/close-account-page])}]
[quo/account-overview
{:current-value formatted-balance
:account-name name
@@ -56,7 +54,7 @@
:buy-action #(rf/dispatch [:show-bottom-sheet
{:content buy-drawer}])
:bridge-action #(ff/alert ::ff/wallet.bridge-token
(fn [] (rf/dispatch [:wallet/start-bridge])))}])
(fn [] (rf/dispatch [:open-modal :wallet-bridge])))}])
[quo/tabs
{:style style/tabs
:size 32
@@ -1,14 +1,20 @@
(ns status-im.contexts.wallet.add-address-to-watch.confirm-address.component-spec
(:require
[status-im.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address]
[test-helpers.component :as h]))
[test-helpers.component :as h]
[utils.re-frame :as rf]))
(h/describe "Add Watch Only Account Page"
(h/setup-restorable-re-frame)
(h/test "Create Account button is disabled while no account name exists"
(h/setup-subs {:wallet/watch-only-accounts []
:get-screen-params {:address "0xmock-address"}})
(h/render [confirm-address/view])
(h/is-truthy (h/get-by-text "0xmock-address"))
(h/is-disabled (h/get-by-label-text :confirm-button-label))))
(let [callback (h/mock-fn)]
(with-redefs [rf/dispatch #(callback)]
(h/setup-subs {:profile/wallet-accounts []
:get-screen-params {:address "0xmock-address"}})
(h/render [confirm-address/view {}])
(h/is-truthy (h/get-by-text "0xmock-address"))
(h/was-not-called callback)
(h/fire-event :change-text (h/get-by-label-text :profile-title-input) "NAME")
(h/fire-event :press (h/get-by-translation-text :t/add-watched-address))
(h/was-called callback)))))

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