Compare commits

..
Author SHA1 Message Date
Omar Basem 9bbeac1ed5 updates 2023-06-26 13:42:11 +04:00
297 changed files with 2896 additions and 3129 deletions
+37
View File
@@ -0,0 +1,37 @@
module.exports = {
testRunner: 'jest',
testRegex: '\\.visual\\.js$',
'runner-config': 'visual-test/config.json',
devices: {
simulator: {
type: 'ios.simulator',
device: {
type: 'iPhone 11 Pro',
},
},
},
apps: {
'ios.release': {
name: 'StatusIm',
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/StatusIm.app',
build: 'make release-ios',
},
'ios.debug': {
name: 'StatusIm',
type: 'ios.app',
binaryPath: process.env.TEST_BINARY_PATH,
build: "make run-ios SIMULATOR='iPhone 11 Pro'",
},
},
configurations: {
'ios.sim.release': {
device: 'simulator',
app: 'ios.release',
},
'ios.sim.debug': {
device: 'simulator',
app: 'ios.debug',
},
},
};
+8
View File
@@ -343,6 +343,14 @@ test: ##@test Run tests once in NodeJS
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js target/test/test.js
run-visual-test-ios: export TARGET := clojure
run-visual-test-ios: XCODE_DERIVED_DATA := $(HOME)/Library/Developer/Xcode/DerivedData
run-visual-test-ios: APPLICATION_NAME := StatusIm-brfnruzfrkkycpbndmdoeyrigthc
run-visual-test-ios: export TEST_BINARY_PATH := $(XCODE_DERIVED_DATA)/$(APPLICATION_NAME)/Build/Products/Debug-iphonesimulator/StatusIm.app
run-visual-test-ios: ##@test Run tests once in NodeJS
detox test --configuration ios.sim.debug
component-test-watch: export TARGET := clojure
component-test-watch: export COMPONENT_TEST := true
component-test-watch: export BABEL_ENV := test
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
/**
* This job runs daily and executes `pod repo update` on MacOS
* This is done to avoid issues with out of date repo causing errors like:
-1
View File
@@ -1,4 +1,3 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1 -1
View File
@@ -169,7 +169,7 @@ For VS Code users.
### Start and connect the REPL
1. Open the `status-mobile` folder.
1. Start [Status development](starting-guide.md#development) (Starting the `run-clojure` and `run-metro` jobs in split view in the VS Code integrated terminal works great.)
1. Start [Status development](STARTING_GUIDE.md#development) (Starting the `run-clojure` and `run-metro` jobs in split view in the VS Code integrated terminal works great.)
1. Run the VS Code command: **Calva: Connect to a running REPL Server in the project**
1. Select the project type `shadow-cljs`
1. Accept the suggested connection `host:port`
@@ -1156,7 +1156,23 @@ RCT_EXPORT_METHOD(deactivateKeepAwake)
- (NSString*) deviceName
{
return [[UIDevice currentDevice] name];;
NSString* deviceName = nil;
if ([self.deviceId rangeOfString:@"iPod"].location != NSNotFound) {
deviceName = @"iPod Touch";
}
else if([self.deviceId rangeOfString:@"iPad"].location != NSNotFound) {
deviceName = @"iPad";
}
else if([self.deviceId rangeOfString:@"iPhone"].location != NSNotFound){
deviceName = @"iPhone";
}
else if([self.deviceId rangeOfString:@"AppleTV"].location != NSNotFound){
deviceName = @"Apple TV";
}
return deviceName;
}
- (NSDictionary *)constantsToExport
-6
View File
@@ -49,12 +49,6 @@ in {
doCheck = false;
});
# Downgrade watchman in attempt to fix "too many files open issue"
watchman = callPackage ./pkgs/watchman {
inherit (super.darwin.apple_sdk.frameworks) CoreServices;
autoconf = super.buildPackages.autoconf269;
};
# Package version adjustments
gradle = super.gradle_7;
nodejs = super.nodejs-18_x;
-11
View File
@@ -17,20 +17,9 @@ let
# Override some packages and utilities
pkgsOverlay = import ./overlay.nix;
# Fix for lack of Android SDK for M1 Macs.
systemOverride = let
inherit (builtins) currentSystem getEnv;
envSystemOverride = getEnv "NIXPKGS_SYSTEM_OVERRIDE";
in
if envSystemOverride != "" then
envSystemOverride
else
currentSystem;
in
# import nixpkgs with a config override
(import nixpkgsSrc) {
config = defaultConfig // config;
system = systemOverride;
overlays = [ pkgsOverlay ];
}
+1 -4
View File
@@ -3,10 +3,7 @@
# for the Android development environment.
#
{ androidenv, lib, stdenv }:
assert lib.assertMsg (stdenv.system != "aarch64-darwin")
"aarch64-darwin not supported for Android SDK. Use: NIXPKGS_SYSTEM_OVERRIDE=x86_64-darwin";
{ androidenv }:
# The "android-sdk-license" license is accepted
# by setting android_sdk.accept_license = true.
-23
View File
@@ -1,23 +0,0 @@
# Issue
`watchman` was upgraded significantly during the last nixpkgs upgrade (`4.9.0` (Aug 16, 2017) to `2023.01.30.00` - 6 years between):
- https://github.com/status-im/status-mobile/pull/14944
- https://github.com/status-im/nixpkgs/commit/4e9c02bcc709fe1737a746add0e8e0109133d808
Probably causing developers to have "too many files open" issue:
https://github.com/status-im/status-mobile/issues/16341
```
Error: A non-recoverable condition has triggered. Watchman needs your help!
The triggering condition was at timestamp=1687286390: opendir(/Users/javid/Projects/status-mobile/node_modules/metro-core/node_modules/jest-regex-util/build) -> Too many open files
All requests will continue to fail with this message until you resolve
the underlying problem. You will find more information on fixing this at
https://facebook.github.io/watchman/docs/troubleshooting.html#poison-opendir
```
# Fix
This is an attempt to fix the issue by downgrading the watchman
# Upgrade
When upgrading in the future, please read the comments:
https://github.com/status-im/status-mobile/issues/16341
-48
View File
@@ -1,48 +0,0 @@
{ stdenv, lib, config, fetchFromGitHub, autoconf, automake, pcre
, libtool, pkg-config, openssl
, confFile ? config.watchman.confFile or null
, withApple ? stdenv.isDarwin, CoreServices
}:
stdenv.mkDerivation rec {
pname = "watchman";
version = "4.9.0";
src = fetchFromGitHub {
owner = "facebook";
repo = "watchman";
rev = "v${version}";
sha256 = "0fdaj5pmicm6j17d5q7px800m5rmam1a400x3hv1iiifnmhgnkal";
};
nativeBuildInputs = [ autoconf automake pkg-config libtool ];
buildInputs = [ pcre openssl ]
#++ lib.optionals withApple [ CoreServices ];
++ lib.optionals stdenv.isDarwin [ CoreServices ];
configureFlags = [
"--enable-lenient"
"--enable-conffile=${if confFile == null then "no" else confFile}"
"--with-pcre=yes"
# For security considerations re: --disable-statedir, see:
# https://github.com/facebook/watchman/issues/178
"--disable-statedir"
];
prePatch = ''
patchShebangs .
'';
preConfigure = ''
./autogen.sh
'';
meta = with lib; {
description = "Watches files and takes action when they change";
homepage = "https://facebook.github.io/watchman";
maintainers = with maintainers; [ cstrahan ];
platforms = with platforms; linux ++ darwin;
license = licenses.asl20;
};
}
+1 -7
View File
@@ -25,7 +25,7 @@ cleanup() {
# If you want to clean after every build set _NIX_CLEAN=true
if [[ -n "${_NIX_CLEAN}" ]]; then
trap cleanup EXIT ERR INT QUIT
trap cleanup EXIT ERR INT QUIT
fi
# build output will end up under /nix, we have to extract it
@@ -44,12 +44,6 @@ if [[ -z "${TARGET}" ]]; then
exit 1
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.release)$ ]]; then
os=$(uname -s | tr '[:upper:]' '[:lower:]')
export NIXPKGS_SYSTEM_OVERRIDE="x86_64-${os}"
fi
# Some defaults flags, --pure could be optional in the future.
# NOTE: The --keep-failed flag can be used for debugging issues.
nixOpts=(
+1 -2
View File
@@ -8,8 +8,7 @@ file_group() {
if [[ "${UNAME}" == "Linux" ]]; then
stat -Lc "%G" "${1}" 2>/dev/null
elif [[ "${UNAME}" == "Darwin" ]]; then
# Avoid using Nix GNU stat when in Nix shell.
/usr/bin/stat -Lf "%Sg" "${1}" 2>/dev/null
stat -Lf "%Sg" "${1}" 2>/dev/null
fi
}
+1 -6
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env bash
#
# This script is used by the Makefile to have an implicit nix-shell.
# The following environment variables modify the script behavior:
# - TARGET: This attribute is passed via --attr to Nix, defining the scope.
@@ -63,12 +64,6 @@ if [[ -n "${_NIX_PURE}" ]]; then
pureDesc='pure '
fi
# Hack fix for missing Android SDK for aarch64 on Darwin. See systemOverride in `nix/pkgs.nix`.
if [[ "${TARGET}" =~ ^(android-sdk|android|gradle|keytool|status-go)$ ]]; then
os=$(uname -s | tr '[:upper:]' '[:lower:]')
export NIXPKGS_SYSTEM_OVERRIDE="x86_64-${os}"
fi
echo -e "${GRN}Configuring ${pureDesc}Nix shell for target '${TARGET}'...${RST}" 1>&2
# Save derivation from being garbage collected
+1
View File
@@ -90,6 +90,7 @@
"@testing-library/react-native": "^11.2.0",
"@types/jest": "^28.1.6",
"concurrently": "^7.6.0",
"detox": "^19.9.1",
"jest": "^26.6.3",
"jest-circus": "^26.0.0",
"jest-image-snapshot": "^5.1.0",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,92 +0,0 @@
import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
export function background(color, progress) {
return useDerivedValue(function () {
'worklet';
const r = parseInt(color.substring(1, 3), 16);
const g = parseInt(color.substring(3, 5), 16);
const b = parseInt(color.substring(5, 7), 16);
return progress.value <= 25 ? `rgba(${r}, ${g}, ${b}, .4)` : `rgba(${r}, ${g}, ${b}, .2)`;
});
}
export function opacity(progress) {
return useDerivedValue(function () {
'worklet';
return progress.value <= 25 ? 1 : 0.3;
});
}
export function avatarOpacity(progress) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
switch (true) {
case progressValue <= 25:
return 1;
case progressValue <= 50:
return 0.1;
default:
return 0.3;
}
});
}
export function ringOpacity(progress) {
return useDerivedValue(function () {
'worklet';
return progress.value <= 50 ? 1 : 0.3;
});
}
export function userHashOpacity(progress) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
switch (true) {
case progressValue <= 25:
return 1;
case progressValue <= 50:
return 0.3;
case progressValue <= 75:
return 1;
default:
return 0.3;
}
});
}
export function userHashColor(progress) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
switch (true) {
case progressValue <= 25:
return 'rgba(255, 255, 255, .6)';
case progressValue <= 50:
return 'rgba(255, 255, 255, .6)';
case progressValue <= 75:
return 'rgb(255, 255, 255)';
default:
return 'rgba(255, 255, 255, .6)';
}
});
}
export function emojiHashStyle(progress) {
return useAnimatedStyle(function () {
'worklet';
const progressValue = progress.value;
switch (true) {
case progressValue <= 25:
return { opacity: 1 };
case progressValue <= 75:
return { opacity: 0.3 };
default:
return { opacity: 1 };
}
});
}
-7
View File
@@ -6,10 +6,3 @@ export function infoLayout(input, isTop) {
return isTop ? input.value : -input.value;
});
}
export function textSheet(input, isHeight) {
return useDerivedValue(function () {
'worklet';
return isHeight ? input.value : -input.value;
});
}
+21 -9
View File
@@ -1,8 +1,6 @@
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300;
const totalPages = 4;
const pageSize = 100 / totalPages;
const easeOut = {
duration: slideAnimationDuration,
@@ -17,15 +15,29 @@ export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
});
}
export function carouselLeftPosition(windowWidth, progress, isDragging, dragAmount) {
export function carouselLeftPosition(windowWidth, progress) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
const dragAmountValue = dragAmount.value;
const baseOffset = (Math.floor(progressValue / pageSize) % totalPages) * windowWidth;
const adjustedOffset = baseOffset === 0 && dragAmountValue > 0 ? baseOffset : -baseOffset + dragAmountValue;
return isDragging.value ? withTiming(adjustedOffset, easeOut) : withTiming(-baseOffset, easeOut);
switch (true) {
case progressValue < 25:
return 0;
case progressValue === 25:
return withTiming(-windowWidth, easeOut);
case progressValue < 50:
return -windowWidth;
case progressValue === 50:
return withTiming(-2 * windowWidth, easeOut);
case progressValue < 75:
return -2 * windowWidth;
case progressValue === 75:
return withTiming(-3 * windowWidth, easeOut);
case progressValue < 100:
return -3 * windowWidth;
case progressValue === 100:
return withTiming(-4 * windowWidth, easeOut);
default:
return 0;
}
});
}
-1
View File
@@ -13,7 +13,6 @@ which is explained in better detail in this video
https://www.youtube.com/watch?v=iEBoZDHCN5Y&t=2205s
there is a bug with the pitch and roll calculations provided directly from the sensor data so the calculation had to
be done using the quaternions directly.
This link is useful to understand this: https://engineering.stackexchange.com/questions/3348/calculating-pitch-yaw-and-roll-from-mag-acc-and-gyro-data
*/
export function sensorAnimatedImage(zIndex, offset, stretch) {
'worklet';
+1 -59
View File
@@ -1,4 +1,4 @@
import { useDerivedValue, withTiming, withSequence, withDelay, Easing, runOnJS } from 'react-native-reanimated';
import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated';
import * as constants from './constants';
// Derived Values
@@ -88,61 +88,3 @@ export function screenZIndex(screenState) {
}
});
}
export function screenBorderRadius(screenState) {
return useDerivedValue(function () {
'worklet';
switch (screenState.value) {
case constants.OPEN_SCREEN_WITH_SHELL_ANIMATION:
return withDelay(constants.SHELL_ANIMATION_TIME, withTiming(0, { duration: 0 }));
case constants.OPEN_SCREEN_WITH_SLIDE_ANIMATION:
case constants.OPEN_SCREEN_WITHOUT_ANIMATION:
return 0;
case constants.CLOSE_SCREEN_WITH_SLIDE_ANIMATION:
return withDelay(constants.SHELL_ANIMATION_TIME, withTiming(20, { duration: 0 }));
case constants.CLOSE_SCREEN_WITHOUT_ANIMATION:
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
return 20;
}
});
}
export function screenGestureOnUpdate(screenLeft) {
return function (event) {
'worklet';
const absoluteX = event.absoluteX;
if (absoluteX !== null) {
screenLeft.value = event.absoluteX;
}
};
}
export function screenGestureOnEnd(data) {
return function (event) {
'worklet';
const { screenLeft, screenState, screenWidth, leftVelocity, rightVelocity, screenClosedCallback } = data;
const absoluteX = event.absoluteX ?? 0;
const velocityX = event.velocityX ?? 0;
const closeScreen = velocityX > rightVelocity || (velocityX > leftVelocity && absoluteX >= screenWidth / 2);
// Velocity (points/sec) = Distance/time
var animationVelocity = (screenWidth * 1000) / constants.SHELL_ANIMATION_TIME;
if (Math.abs(velocityX) > animationVelocity) {
animationVelocity = velocityX; // Faster fling
}
const newDistance = closeScreen ? screenWidth - absoluteX : absoluteX;
const animationTime = (newDistance * 1000) / animationVelocity;
screenLeft.value = withTiming(closeScreen ? screenWidth : 0, {
duration: animationTime,
easing: Easing.bezier(0, 0, 0.58, 1),
});
if (closeScreen) {
runOnJS(screenClosedCallback)(animationTime);
}
};
}
+73 -75
View File
@@ -364,79 +364,77 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
(defn mock
[module]
(case module
"react-native-languages" react-native-languages
"react-native-background-timer" background-timer
"react-native-image-crop-picker" image-crop-picker
"react-native-gesture-handler" react-native-gesture-handler
"react-native-static-safe-area-insets" react-native-static-safe-area-insets
"react-native-config" config
"react-native-iphone-x-helper" (clj->js {:getStatusBarHeight (fn [])
:getBottomSpace (fn [])})
"react-native-screens" (clj->js {})
"react-native-reanimated" react-native-reanimated
"react-native-redash/lib/module/v1" react-native-redash
"react-native-redash" react-native-redash
"react-native-fetch-polyfill" fetch
"react-native-status-keycard" status-keycard
"react-native-keychain" keychain
"react-native-touch-id" touchid
"@react-native-community/netinfo" net-info
"react-native-dialogs" dialogs
"react-native" react-native
"react-native-fs" fs
"react-native-mail" react-native-mail
"react-native-image-resizer" image-resizer
"react-native-haptic-feedback" react-native-haptic-feedback
"react-native-device-info" react-native-device-info
"react-native-push-notification" react-native-push-notification
"react-native-linear-gradient" react-native-gradien
"@react-native-community/masked-view" masked-view
"react-native-blob-util" react-native-blob-util
"react-native-navigation" react-native-navigation
"@react-native-community/push-notification-ios" push-notification-ios
"@react-native-community/blur" react-native-blur
"@react-native-community/cameraroll" react-native-camera-roll
"react-native-camera-kit" react-native-camera-kit
"react-native-permissions" react-native-permissions
"rn-emoji-keyboard" rn-emoji-keyboard
"react-native-hole-view" react-native-hole-view
"react-native-draggable-flatlist" react-native-draggable-flatlist
"react-native-webview" react-native-webview
"@react-native-community/audio-toolkit" react-native-audio-toolkit
"react-native-image-viewing" react-native-image-viewing
"react-native-share" react-native-share
"@react-native-async-storage/async-storage" async-storage
"react-native-svg" react-native-svg
"react-native-transparent-video" react-native-transparent-video
"react-native-orientation-locker" react-native-orientation-locker
"../src/js/worklets/core.js" worklet-factory
"../src/js/worklets/shell/bottom_tabs.js" #js {}
"../src/js/worklets/shell/home_stack.js" #js {}
"../src/js/worklets/shell/floating_screen.js" #js {}
"../src/js/worklets/bottom_sheet.js" #js {}
"../src/js/worklets/record_audio.js" #js {}
"../src/js/worklets/scroll_view.js" #js {}
"../src/js/worklets/onboarding_carousel.js" #js {}
"../src/js/worklets/lightbox.js" #js {}
"../src/js/worklets/parallax.js" #js {}
"../src/js/worklets/identifiers_highlighting.js" #js {}
"./fleets.js" default-fleets
"@walletconnect/client" wallet-connect-client
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))
"../translations/es.json" (js/JSON.parse (slurp "./translations/es.json"))
"../translations/es_419.json" (js/JSON.parse (slurp "./translations/es_419.json"))
"../translations/fil.json" (js/JSON.parse (slurp "./translations/fil.json"))
"../translations/fr.json" (js/JSON.parse (slurp "./translations/fr.json"))
"../translations/id.json" (js/JSON.parse (slurp "./translations/id.json"))
"../translations/it.json" (js/JSON.parse (slurp "./translations/it.json"))
"../translations/ko.json" (js/JSON.parse (slurp "./translations/ko.json"))
"../translations/pt_BR.json" (js/JSON.parse (slurp "./translations/pt_BR.json"))
"../translations/ru.json" (js/JSON.parse (slurp "./translations/ru.json"))
"../translations/tr.json" (js/JSON.parse (slurp "./translations/tr.json"))
"../translations/zh.json" (js/JSON.parse (slurp "./translations/zh.json"))
"../translations/zh_hant.json" (js/JSON.parse (slurp
"./translations/zh_hant.json"))
"../translations/zh_TW.json" (js/JSON.parse (slurp "./translations/zh_TW.json"))
"react-native-languages" react-native-languages
"react-native-background-timer" background-timer
"react-native-image-crop-picker" image-crop-picker
"react-native-gesture-handler" react-native-gesture-handler
"react-native-static-safe-area-insets" react-native-static-safe-area-insets
"react-native-config" config
"react-native-iphone-x-helper" (clj->js {:getStatusBarHeight (fn [])
:getBottomSpace (fn [])})
"react-native-screens" (clj->js {})
"react-native-reanimated" react-native-reanimated
"react-native-redash/lib/module/v1" react-native-redash
"react-native-redash" react-native-redash
"react-native-fetch-polyfill" fetch
"react-native-status-keycard" status-keycard
"react-native-keychain" keychain
"react-native-touch-id" touchid
"@react-native-community/netinfo" net-info
"react-native-dialogs" dialogs
"react-native" react-native
"react-native-fs" fs
"react-native-mail" react-native-mail
"react-native-image-resizer" image-resizer
"react-native-haptic-feedback" react-native-haptic-feedback
"react-native-device-info" react-native-device-info
"react-native-push-notification" react-native-push-notification
"react-native-linear-gradient" react-native-gradien
"@react-native-community/masked-view" masked-view
"react-native-blob-util" react-native-blob-util
"react-native-navigation" react-native-navigation
"@react-native-community/push-notification-ios" push-notification-ios
"@react-native-community/blur" react-native-blur
"@react-native-community/cameraroll" react-native-camera-roll
"react-native-camera-kit" react-native-camera-kit
"react-native-permissions" react-native-permissions
"rn-emoji-keyboard" rn-emoji-keyboard
"react-native-hole-view" react-native-hole-view
"react-native-draggable-flatlist" react-native-draggable-flatlist
"react-native-webview" react-native-webview
"@react-native-community/audio-toolkit" react-native-audio-toolkit
"react-native-image-viewing" react-native-image-viewing
"react-native-share" react-native-share
"@react-native-async-storage/async-storage" async-storage
"react-native-svg" react-native-svg
"react-native-transparent-video" react-native-transparent-video
"react-native-orientation-locker" react-native-orientation-locker
"../src/js/worklets/core.js" worklet-factory
"../src/js/worklets/shell/bottom_tabs.js" #js {}
"../src/js/worklets/shell/home_stack.js" #js {}
"../src/js/worklets/shell/floating_screen.js" #js {}
"../src/js/worklets/bottom_sheet.js" #js {}
"../src/js/worklets/record_audio.js" #js {}
"../src/js/worklets/scroll_view.js" #js {}
"../src/js/worklets/onboarding_carousel.js" #js {}
"../src/js/worklets/lightbox.js" #js {}
"../src/js/worklets/parallax.js" #js {}
"./fleets.js" default-fleets
"@walletconnect/client" wallet-connect-client
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))
"../translations/es.json" (js/JSON.parse (slurp "./translations/es.json"))
"../translations/es_419.json" (js/JSON.parse (slurp "./translations/es_419.json"))
"../translations/fil.json" (js/JSON.parse (slurp "./translations/fil.json"))
"../translations/fr.json" (js/JSON.parse (slurp "./translations/fr.json"))
"../translations/id.json" (js/JSON.parse (slurp "./translations/id.json"))
"../translations/it.json" (js/JSON.parse (slurp "./translations/it.json"))
"../translations/ko.json" (js/JSON.parse (slurp "./translations/ko.json"))
"../translations/pt_BR.json" (js/JSON.parse (slurp "./translations/pt_BR.json"))
"../translations/ru.json" (js/JSON.parse (slurp "./translations/ru.json"))
"../translations/tr.json" (js/JSON.parse (slurp "./translations/tr.json"))
"../translations/zh.json" (js/JSON.parse (slurp "./translations/zh.json"))
"../translations/zh_hant.json" (js/JSON.parse (slurp "./translations/zh_hant.json"))
"../translations/zh_TW.json" (js/JSON.parse (slurp "./translations/zh_TW.json"))
nil))
+1 -10
View File
@@ -4,8 +4,7 @@
[taoensso.timbre :as log]
[react-native.platform :as platform]
[react-native.core :as rn]
[utils.transforms :as types]
[clojure.string :as string]))
[utils.transforms :as types]))
(defn status
[]
@@ -388,14 +387,6 @@
:build-id (.-buildId status)
:device-id (.-deviceId status)}))
(defn get-installation-name
[]
;; NOTE(rasom): Only needed for android devices currently
(when platform/android?
(string/join " "
((juxt :model :device-id)
(get-device-model-info)))))
(defn get-node-config
[callback]
(log/debug "[native-module] get-node-config")
+18 -66
View File
@@ -4,9 +4,7 @@
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[react-native.core :as rn]
[react-native.blur :as blur]
[reagent.core :as reagent]
[quo2.components.buttons.style :as style]))
[reagent.core :as reagent]))
(defn themes
[customization-color]
@@ -68,16 +66,6 @@
:background-color {:default colors/neutral-80-opa-5
:pressed colors/neutral-80-opa-10
:disabled colors/neutral-80-opa-5}}
:blurred {:icon-color colors/neutral-100
:icon-secondary-color colors/neutral-100
:icon-background-color {:default colors/neutral-20
:blurred colors/neutral-80-opa-10}
:label-color colors/neutral-100
:background-color {:default colors/neutral-10
:pressed colors/neutral-10
:disabled colors/neutral-10-opa-10-blur}
:blur-overlay-color colors/neutral-10-opa-40-blur
:blur-type :light}
:blur-bg-outline {:icon-color colors/neutral-100
:icon-secondary-color colors/neutral-80-opa-40
:label-color colors/neutral-100
@@ -147,16 +135,6 @@
:background-color {:default colors/white-opa-5
:pressed colors/white-opa-10
:disabled colors/white-opa-5}}
:blurred {:icon-color colors/white
:icon-secondary-color colors/white
:icon-background-color {:default colors/neutral-80
:blurred colors/white-opa-10}
:label-color colors/white
:background-color {:default colors/neutral-90
:pressed colors/neutral-90
:disabled colors/neutral-90-opa-10-blur}
:blur-overlay-color colors/neutral-80-opa-40
:blur-type :dark}
:blur-bg-outline {:icon-color colors/white
:icon-secondary-color colors/white-opa-40
:label-color colors/white
@@ -179,11 +157,12 @@
24 8))})
(defn style-container
[type size disabled background-color border-color icon above width before after blur-active?]
[type size disabled background-color border-color icon above width before after]
(merge {:height size
:align-items :center
:justify-content :center
:flex-direction (if above :column :row)
:background-color background-color
:padding-horizontal (when-not (or icon before after)
(case size
56 16
@@ -213,11 +192,7 @@
56 0
40 9
32 5
24 4))
:overflow :hidden}
(when (or (and (= type :blurred) (not blur-active?))
(not= type :blurred))
{:background-color background-color})
24 4))}
(shape-style-container type icon size)
(when width
{:width width})
@@ -249,23 +224,18 @@
(fn
[{:keys [on-press disabled type size before after above icon-secondary-no-color
width customization-color theme override-background-color pressed
on-long-press accessibility-label icon icon-no-color style inner-style test-ID
blur-active? override-before-margins override-after-margins icon-size icon-container-size
icon-container-rounded?]
on-long-press accessibility-label icon icon-no-color style inner-style test-ID]
:or {type :primary
size 40
customization-color :primary
blur-active? true}}
customization-color :primary}}
children]
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color blur-type
blur-overlay-color icon-background-color]}
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color]}
(get-in (themes customization-color)
[theme type])
state (cond disabled :disabled
(or @pressed-in pressed) :pressed
:else :default)
blur-state (if blur-active? :blurred :default)
icon-size (or icon-size (when (= 24 size) 12))
icon-size (when (= 24 size) 12)
icon-secondary-color (or icon-secondary-color icon-color)]
[rn/touchable-without-feedback
(merge {:test-ID test-ID
@@ -294,17 +264,9 @@
above
width
before
after
blur-active?)
after)
(when (= state :pressed) {:opacity 0.9})
inner-style)}
(when (and (= type :blurred)
blur-active?)
[blur/view
{:blur-radius 20
:blur-type blur-type
:overlay-color blur-overlay-color
:style style/blur-view}])
(when above
[rn/view
[quo2.icons/icon above
@@ -313,16 +275,11 @@
:size icon-size}]])
(when before
[rn/view
{:style (style/before-icon-style
{:override-margins override-before-margins
:size size
:icon-container-size icon-container-size
:icon-background-color (get icon-background-color blur-state)
:icon-container-rounded? icon-container-rounded?
:icon-size icon-size})}
[quo2.icons/icon before
{:color icon-secondary-color
:size icon-size}]])
{:container-style {:margin-left (if (= size 40) 12 8)
:margin-right 4}
:color icon-secondary-color
:size icon-size}]])
[rn/view
(cond
(or icon icon-no-color)
@@ -344,16 +301,11 @@
children)]
(when after
[rn/view
{:style (style/after-icon-style
{:override-margins override-after-margins
:size size
:icon-container-size icon-container-size
:icon-background-color (get icon-background-color blur-state)
:icon-container-rounded? icon-container-rounded?
:icon-size icon-size})}
[quo2.icons/icon after
{:no-color icon-secondary-no-color
:color icon-secondary-color
:size icon-size}]])]]]))))
{:container-style {:margin-left 4
:margin-right (if (= size 40) 12 8)}
:no-color icon-secondary-no-color
:color icon-secondary-color
:size icon-size}]])]]]))))
(def button (theme/with-theme button-internal))
-42
View File
@@ -1,42 +0,0 @@
(ns quo2.components.buttons.style)
(def blur-view
{:position :absolute
:top 0
:left 0
:right 0
:bottom 0})
(defn before-icon-style
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
icon-size]}]
(merge
{:margin-left (or (get override-margins :left)
(if (= size 40) 12 8))
:margin-right (or (get override-margins :right) 4)
:align-items :center
:justify-content :center}
(when icon-container-size
{:width icon-container-size
:height icon-container-size})
(when icon-background-color
{:background-color icon-background-color})
(when icon-container-rounded?
{:border-radius (/ (or icon-container-size icon-size) 2)})))
(defn after-icon-style
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
icon-size]}]
(merge
{:margin-left (or (get override-margins :left) 4)
:margin-right (or (get override-margins :right)
(if (= size 40) 12 8))
:align-items :center
:justify-content :center}
(when icon-container-size
{:width icon-container-size
:height icon-container-size})
(when icon-background-color
{:background-color icon-background-color})
(when icon-container-rounded?
{:border-radius (/ (or icon-container-size icon-size) 2)})))
+7 -7
View File
@@ -9,23 +9,23 @@
:height 20})
(defn neutral-border-color
[in-blur-view? theme]
[in-blur-view? override-theme]
(if in-blur-view?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-10 theme)
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)))
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-10 override-theme)
(colors/theme-colors colors/neutral-20 colors/neutral-80 override-theme)))
(def active-background-color (colors/custom-color :blue 50 10))
(def complete-background-color (colors/custom-color :blue 50))
(defn container
[size type in-blur-view? theme]
[size type in-blur-view? override-theme]
(cond-> container-base
(#{1 2} size) (assoc :width 20)
(= size 3) (assoc :width 28)
(= type :neutral)
(assoc :border-width 1
:border-color (neutral-border-color in-blur-view? theme))
:border-color (neutral-border-color in-blur-view? override-theme))
(= type :active)
(assoc :background-color active-background-color)
@@ -35,7 +35,7 @@
(defn text-color
([type] (text-color type nil))
([type theme]
([type override-theme]
(case type
(:neutral :active) (colors/theme-colors colors/neutral-100-opa-100 colors/white theme)
(:neutral :active) (colors/theme-colors colors/neutral-100-opa-100 colors/white override-theme)
:complete colors/white)))
+4 -7
View File
@@ -2,12 +2,11 @@
(:require
[quo2.components.counter.step.style :as style]
[quo2.components.markdown.text :as text]
[quo2.theme :as theme]
[react-native.core :as rn]
[utils.number]))
(defn themed-step
[{:keys [type accessibility-label theme in-blur-view?]} value]
(defn step
[{:keys [type accessibility-label override-theme in-blur-view?]} value]
(let [type (or type :neutral)
value (utils.number/parse-int value)
label (str value)
@@ -15,10 +14,8 @@
[rn/view
{:accessible true
:accessibility-label (or accessibility-label :step-counter)
:style (style/container size type in-blur-view? theme)}
:style (style/container size type in-blur-view? override-theme)}
[text/text
{:weight :medium
:size :label
:style {:color (style/text-color type theme)}} label]]))
(def step (theme/with-theme themed-step))
:style {:color (style/text-color type override-theme)}} label]]))
+2 -6
View File
@@ -7,12 +7,8 @@
[button/button
(merge
opts
{:after (if selected :i/chevron-top :i/chevron-down)
:icon-size 12
:icon-container-size 14
:icon-container-rounded? true
:override-after-margins {:left 7
:right 9}
{:after (if selected :i/pullup :i/dropdown)
:icon-secondary-no-color true
:pressed selected
:on-press #(when on-change (on-change selected))})
children]))
+2 -4
View File
@@ -56,10 +56,8 @@
(when (and (not locked?)
muted?)
[quo2.icons/icon :i/muted
{:size 20
:color colors/neutral-40
:container-style {:margin-right 1
:margin-top 2}}])
{:size 20
:color colors/neutral-40}])
(when (and (not locked?)
(not muted?)
(pos? (int mentions-count)))
@@ -1,9 +1,7 @@
(ns quo2.components.record-audio.record-audio.--tests--.record-audio-component-spec
(:require [quo2.components.record-audio.record-audio.view :as record-audio]
[react-native.audio-toolkit :as audio]
[test-helpers.component :as h]
[reagent.core :as reagent]
[utils.datetime :as datetime]))
[test-helpers.component :as h]))
(h/describe "record audio component"
(h/before-each
@@ -36,16 +34,12 @@
(.toHaveBeenCalledTimes 1))))
(h/test "record-audio on-reviewing-audio works"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(let [event (js/jest.fn)]
(h/render [record-audio/record-audio
{:on-reviewing-audio event
:record-audio-permission-granted true}])
(with-redefs [audio/new-recorder (fn [_ on-meter-fn _]
(reset! on-meter on-meter-fn))
audio/start-recording (fn [_ on-start _]
(on-start)
(js/setInterval #(@on-meter) 100))
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
audio/get-recorder-file-path (fn [] "file-path")]
(h/fire-event
:on-start-should-set-responder
@@ -54,30 +48,25 @@
:locationY 70
:timestamp 0
:identifier 0}})
(with-redefs [datetime/timestamp (fn [] (+ (.now js/Date) 1000))]
(h/advance-timers-by-time 100)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (h/expect event)
(.toHaveBeenCalledTimes 1))))))
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (h/expect event)
(.toHaveBeenCalledTimes 1)))))
(h/test "record-audio on-send works after reviewing audio"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(let [event (js/jest.fn)]
(h/render [record-audio/record-audio
{:on-send event
:record-audio-permission-granted true}])
(with-redefs [audio/new-recorder (fn [_ on-meter-fn _]
(reset! on-meter on-meter-fn))
audio/start-recording (fn [_ on-start _]
(on-start)
(js/setInterval #(@on-meter) 100))
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
audio/get-recorder-file-path (fn [] "audio-file-path")
audio/get-player-duration (fn [] 5000)]
(h/fire-event
@@ -87,57 +76,46 @@
:locationY 70
:timestamp 0
:identifier 0}})
(with-redefs [datetime/timestamp (fn [] (+ (.now js/Date) 1000))]
(h/advance-timers-by-time 100)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 0
:identifier 0}})
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 80
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))
(-> (js/expect event)
(.toHaveBeenCalledWith {:file-path "audio-file-path"
:duration 5000}))))))
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 0
:identifier 0}})
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 80
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))
(-> (js/expect event)
(.toHaveBeenCalledWith {:file-path "audio-file-path"
:duration 5000})))))
(h/test "record-audio on-send works after sliding to the send button"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)
last-now-ms (atom nil)
duration-ms (atom nil)]
(let [event (js/jest.fn)]
(h/render [record-audio/record-audio
{:on-send event
:record-audio-permission-granted true}])
(with-redefs [audio/new-recorder (fn [_ on-meter-fn _]
(reset! on-meter on-meter-fn))
audio/start-recording (fn [_ on-start _]
(on-start)
(js/setInterval #(@on-meter) 100))
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
audio/stop-recording (fn [_ on-stop _]
(on-stop))
audio/get-recorder-file-path (fn [] "audio-file-path")
datetime/timestamp (fn []
(let [now-ms (.now js/Date)]
(reset! last-now-ms now-ms)
now-ms))]
audio/get-recorder-file-path (fn [] "audio-file-path")]
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
@@ -145,46 +123,36 @@
:locationY 70
:timestamp 0
:identifier 0}})
(with-redefs [datetime/timestamp (fn []
(let [now-plus-ms (+ (.now js/Date) 1000)
time-diff-ms (- now-plus-ms @last-now-ms)]
(when-not @duration-ms
(reset! duration-ms time-diff-ms))
now-plus-ms))]
(h/advance-timers-by-time 100)
(h/fire-event
:on-responder-move
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 80
:locationY -30
:pageX 80
:pageY -30
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 40
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))
(-> (js/expect event)
(.toHaveBeenCalledWith {:file-path "audio-file-path"
:duration @duration-ms}))))))
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-move
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 80
:locationY -30
:pageX 80
:pageY -30
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 40
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))
(-> (js/expect event)
(.toHaveBeenCalledWith {:file-path "audio-file-path"
:duration 500})))))
(h/test "record-audio on-cancel works after reviewing audio"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(let [event (js/jest.fn)]
(h/render [record-audio/record-audio
{:on-cancel event
:record-audio-permission-granted true}])
(with-redefs [audio/new-recorder (fn [_ on-meter-fn _]
(reset! on-meter on-meter-fn))
audio/start-recording (fn [_ on-start _]
(on-start)
(js/setInterval #(@on-meter) 100))]
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))]
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
@@ -192,37 +160,32 @@
:locationY 70
:timestamp 0
:identifier 0}})
(with-redefs [datetime/timestamp (fn [] (+ (.now js/Date) 1000))]
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 40
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))))))
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX 40
:locationY 80
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1)))))
(h/test "record-audio on-cancel works after sliding to the cancel button"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(h/test "cord-audio on-cancel works after sliding to the cancel button"
(let [event (js/jest.fn)]
(h/render [record-audio/record-audio
{:on-cancel event
:record-audio-permission-granted true}])
(with-redefs [audio/new-recorder (fn [_ on-meter-fn _]
(reset! on-meter on-meter-fn))
audio/start-recording (fn [_ on-start _]
(on-start)
(js/setInterval #(@on-meter) 100))
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
audio/stop-recording (fn [_ on-stop _]
(on-stop))]
(h/fire-event
@@ -232,25 +195,22 @@
:locationY 70
:timestamp 0
:identifier 0}})
(with-redefs [datetime/timestamp (fn [] (+ (.now js/Date) 1000))]
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-move
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX -30
:locationY 80
:pageX -30
:pageY 80
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX -10
:locationY 70
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1)))))))
(h/advance-timers-by-time 500)
(h/fire-event
:on-responder-move
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX -30
:locationY 80
:pageX -30
:pageY 80
:identifier 0}})
(h/fire-event
:on-responder-release
(h/get-by-test-id "record-audio")
{:nativeEvent {:locationX -10
:locationY 70
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (js/expect event)
(.toHaveBeenCalledTimes 1))))))
@@ -29,7 +29,7 @@
(defn f-record-button-big
[recording? ready-to-send? ready-to-lock? ready-to-delete? record-button-is-animating?
record-button-at-initial-position? locked? reviewing-audio? recording-length-ms
record-button-at-initial-position? locked? reviewing-audio? recording-timer recording-length-ms
clear-timeout touch-active? recorder-ref reload-recorder-fn idle? on-send on-cancel]
(let [scale (reanimated/use-shared-value 1)
opacity (reanimated/use-shared-value 0)
@@ -82,6 +82,7 @@
(reset! ready-to-lock? false)
(reset! idle? true)
(js/setTimeout #(reset! idle? false) 1000)
(js/clearInterval @recording-timer)
(reset! recording-length-ms 0)
(log/debug "[record-audio] stop recording - success"))
#(log/error "[record-audio] stop recording - error: " %))))
@@ -15,13 +15,11 @@
[quo2.components.record-audio.record-audio.buttons.lock-button :as lock-button]
[quo2.components.record-audio.record-audio.buttons.delete-button :as delete-button]
[quo2.components.record-audio.record-audio.buttons.record-button :as record-button]
[clojure.string :as string]
[utils.datetime :as datetime]
[react-native.platform :as platform]))
[clojure.string :as string]))
(def ^:private min-audio-duration-ms 1000)
(def ^:private max-audio-duration-ms (if platform/ios? 120800 120500))
(def ^:private metering-interval 25)
(def ^:private min-audio-duration-ms 500)
(def ^:private max-audio-duration-ms 120000)
(def ^:private metering-interval 100)
(def ^:private base-filename "am")
(def ^:private default-format ".aac")
@@ -110,7 +108,7 @@
time-str]]))
(defn- f-play-button
[playing-audio? player-ref playing-timer audio-current-time-ms seeking-audio? max-duration-ms]
[playing-audio? player-ref playing-timer audio-current-time-ms seeking-audio?]
(let [on-play (fn []
(reset! playing-audio? true)
(reset! playing-timer
@@ -119,22 +117,8 @@
(let [current-time (audio/get-player-current-time @player-ref)
player-state (audio/get-state @player-ref)
playing? (= player-state audio/PLAYING)]
(when (and playing?
(not @seeking-audio?)
(> current-time 0)
(< current-time max-duration-ms))
(reset! audio-current-time-ms current-time))
(when (>= current-time max-duration-ms)
(audio/stop-playing
@player-ref
(fn []
(reset! playing-audio? false)
(when @playing-timer
(js/clearInterval @playing-timer)
(reset! playing-timer nil)
(reset! audio-current-time-ms 0)
(reset! seeking-audio? false)))
#(log/error "[record-audio] stop player - error: " %)))))
(when (and playing? (not @seeking-audio?) (> current-time 0))
(reset! audio-current-time-ms current-time))))
100)))
on-pause (fn []
(reset! playing-audio? false)
@@ -159,7 +143,7 @@
[{:keys [on-init on-start-recording on-send on-cancel on-reviewing-audio
record-audio-permission-granted
on-request-record-audio-permission on-check-audio-permissions
audio-file on-lock max-duration-ms]}]
audio-file on-lock]}]
[:f>
;; TODO we need to refactor this, and use :f> with defined function, currenly state is reseted each
;; time parent component
@@ -176,7 +160,6 @@
audio-current-time-ms (reagent/atom 0)
seeking-audio? (reagent/atom false)
force-show-controls? (reagent/atom (some? audio-file))
recording-start-ms (atom (datetime/timestamp))
clear-timeout (atom nil)
record-button-at-initial-position? (atom true)
record-button-is-animating? (atom false)
@@ -184,6 +167,7 @@
recorder-ref (atom nil)
player-ref (atom nil)
touch-active? (atom false)
recording-timer (atom nil)
playing-timer (atom nil)
output-file (atom audio-file)
reached-max-duration? (atom false)
@@ -194,7 +178,7 @@
rec-options
(merge
audio/default-recorder-options
{:filename (str base-filename (datetime/timestamp) default-format)
{:filename (str base-filename (.now js/Date) default-format)
:meteringInterval metering-interval})
destroy-player
(fn []
@@ -225,44 +209,13 @@
(fn []
(audio/destroy-recorder @recorder-ref)
(reset! recorder-ref nil))
recorder-on-meter
(fn []
(when @recording-start-ms
(let [now-ms (datetime/timestamp)
recording-duration (- now-ms
@recording-start-ms)]
(reset! recording-length-ms recording-duration)
(when (>= recording-duration max-audio-duration-ms)
(reset! reached-max-duration? (not @locked?))
(reset! reviewing-audio? true)
(reset! idle? false)
(reset! locked? false)
(reset! recording? false)
(reset! ready-to-lock? false)
(reset! ready-to-send? false)
(reset! ready-to-delete? false)
(audio/stop-recording
@recorder-ref
(fn []
(reset! output-file (audio/get-recorder-file-path
@recorder-ref))
(reload-player nil)
(log/debug "[record-audio] stop recording - success"))
#(log/error "[record-audio] stop recording - error: " %))
(js/setTimeout #(reset! idle? false) 1000)
(reset! recording-length-ms 0)
(reset! recording-start-ms nil)
(when on-reviewing-audio
(on-reviewing-audio (audio/get-recorder-file-path
@recorder-ref))))
(log/debug "[record-audio] new recorder - on meter"))))
reload-recorder
(fn []
(when @recorder-ref
(destroy-recorder))
(reset! recorder-ref (audio/new-recorder
rec-options
recorder-on-meter
#(log/debug "[record-audio] new recorder - on meter")
#(log/debug "[record-audio] new recorder - on ended"))))
reset-recorder
(fn []
@@ -285,6 +238,9 @@
(when @clear-timeout
(js/clearTimeout @clear-timeout)
(reset! clear-timeout nil))
(when @recording-timer
(js/clearInterval @recording-timer)
(reset! recording-timer nil))
(when @playing-timer
(js/clearInterval @playing-timer)
(reset! playing-timer nil))
@@ -302,7 +258,7 @@
record-button-area)
new-recorder (audio/new-recorder
rec-options
recorder-on-meter
#(log/debug "[record-audio] new recorder - on meter")
#(log/debug "[record-audio] new recorder - on ended"))]
(reset! touch-timestamp (oops/oget e "nativeEvent.timestamp"))
(reset! touch-identifier (oops/oget e "nativeEvent.identifier"))
@@ -313,13 +269,44 @@
(reset! recording? pressed-record-button?))
(when pressed-record-button?
(reset! playing-audio? false)
(when @recording-timer
(js/clearInterval @recording-timer))
(reset! output-file nil)
(reset! recorder-ref new-recorder)
(audio/start-recording
new-recorder
(fn []
(reset! recording-start-ms (datetime/timestamp))
(reset! audio-current-time-ms 0)
(reset! recording-timer
(js/setInterval
(fn []
(if (< @recording-length-ms max-audio-duration-ms)
(reset! recording-length-ms
(+ @recording-length-ms metering-interval))
(do
(reset! reached-max-duration? (not @locked?))
(reset! reviewing-audio? true)
(reset! idle? false)
(reset! locked? false)
(reset! recording? false)
(reset! ready-to-lock? false)
(reset! ready-to-send? false)
(reset! ready-to-delete? false)
(audio/stop-recording
new-recorder
(fn []
(reset! output-file (audio/get-recorder-file-path
new-recorder))
(reload-player nil)
(log/debug "[record-audio] stop recording - success"))
#(log/error "[record-audio] stop recording - error: " %))
(js/setTimeout #(reset! idle? false) 1000)
(js/clearInterval @recording-timer)
(reset! recording-length-ms 0)
(when on-reviewing-audio
(on-reviewing-audio (audio/get-recorder-file-path
new-recorder))))))
metering-interval))
(log/debug "[record-audio] start recording - success"))
#(log/error "[record-audio] start recording - error: " %))
(when on-start-recording
@@ -437,8 +424,7 @@
(reset! force-show-controls? false)
(when on-send
(on-send {:file-path @output-file
:duration (min max-audio-duration-ms
(int (audio/get-player-duration @player-ref)))}))
:duration (int (audio/get-player-duration @player-ref))}))
(when @player-ref
(audio/stop-playing
@player-ref
@@ -489,8 +475,8 @@
(log/debug "[record-audio] stop recording - success"))
#(log/error "[record-audio] stop recording - error: " %))
(js/setTimeout #(reset! idle? false) 1000)
(js/clearInterval @recording-timer)
(reset! recording-length-ms 0)
(reset! recording-start-ms nil)
(reset! disabled? false))
(if (> touch-timestamp-diff min-touch-duration) 0 250)))
(and (not @locked?) (not @reviewing-audio?) (not @record-button-is-animating?))
@@ -515,8 +501,8 @@
(reset! ready-to-lock? false)
(reset! idle? true)
(js/setTimeout #(reset! idle? false) 1000)
(js/clearInterval @recording-timer)
(reset! recording-length-ms 0)
(reset! recording-start-ms nil)
(reset! disabled? false)
(log/debug "[record-audio] stop recording - success"))
#(log/error "[record-audio] stop recording - error: " %)))
@@ -546,12 +532,11 @@
(when @reviewing-audio?
[:<>
[:f> f-play-button playing-audio? player-ref playing-timer audio-current-time-ms
seeking-audio? max-duration-ms]
seeking-audio?]
[:f> soundtrack/f-soundtrack
{:audio-current-time-ms audio-current-time-ms
:player-ref @player-ref
:seeking-audio? seeking-audio?
:max-audio-duration-ms max-duration-ms}]])
:seeking-audio? seeking-audio?}]])
(when (or @recording? @reviewing-audio?)
[:f> f-time-counter @recording? @recording-length-ms @ready-to-delete? @reviewing-audio?
@audio-current-time-ms])
@@ -582,6 +567,7 @@
record-button-at-initial-position?
locked?
reviewing-audio?
recording-timer
recording-length-ms
clear-timeout
touch-active?
@@ -10,8 +10,8 @@
(def ^:private thumb-dark (js/require "../resources/images/icons2/12x12/thumb-dark.png"))
(defn f-soundtrack
[{:keys [audio-current-time-ms player-ref style seeking-audio? max-audio-duration-ms]}]
(let [audio-duration-ms (min max-audio-duration-ms (audio/get-player-duration player-ref))]
[{:keys [audio-current-time-ms player-ref style seeking-audio?]}]
(let [audio-duration-ms (audio/get-player-duration player-ref)]
[:<>
[slider/slider
{:test-ID "soundtrack"
-6
View File
@@ -88,8 +88,6 @@
(def neutral-100-opa-5 (alpha neutral-100 0.05))
(def neutral-100-opa-10 (alpha neutral-100 0.1))
(def neutral-100-opa-30 (alpha neutral-100 0.3))
(def neutral-100-opa-50 (alpha neutral-100 0.5))
(def neutral-100-opa-60 (alpha neutral-100 0.6))
(def neutral-100-opa-70 (alpha neutral-100 0.7))
(def neutral-100-opa-80 (alpha neutral-100 0.8))
@@ -123,11 +121,7 @@
(def white-70-blur (alpha white 0.7))
(def neutral-80-opa-1-blur (alpha "#192438" 0.1))
(def neutral-5-opa-70-blur (alpha neutral-5 0.7))
(def neutral-10-opa-10-blur (alpha neutral-10 0.1))
(def neutral-10-opa-40-blur (alpha neutral-10 0.4))
(def neutral-80-opa-80-blur (alpha "#192438" 0.8))
(def neutral-90-opa-10-blur (alpha neutral-90 0.1))
(def neutral-90-opa-40-blur (alpha neutral-90 0.4))
(def neutral-90-opa-70-blur (alpha neutral-90 0.7))
(def neutral-95-opa-70-blur neutral-95-opa-70)
(def neutral-100-opa-70-blur neutral-100-opa-70)
-7
View File
@@ -1,6 +1,5 @@
(ns react-native.cameraroll
(:require ["@react-native-community/cameraroll" :as CameraRoll]
[react-native.fs :as fs]
[utils.transforms :as transforms]
[taoensso.timbre :as log]))
@@ -15,9 +14,3 @@
(-> (.getAlbums CameraRoll (clj->js opts))
(.then #(callback (transforms/js->clj %)))
(.catch #(log/warn "could not get camera roll albums" %))))
(defn save-image
[path]
(-> (.save CameraRoll (clj->js path))
(.then #(fs/unlink path))
(.catch #(fs/unlink path))))
-4
View File
@@ -68,10 +68,6 @@
(fn []
(js->clj (.get (.-Dimensions ^js react-native) "screen") :keywordize-keys true))))
(def small-screen?
(let [height (:height (get-screen))]
(< height 700)))
(defn hw-back-add-listener
[callback]
(.addEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback))
-6
View File
@@ -19,8 +19,6 @@
(defn gesture-pan [] (.Pan ^js Gesture))
(defn gesture-long-press [] (.LongPress ^js Gesture))
(defn gesture-pinch [] (.Pinch ^js Gesture))
(defn on-begin [gesture handler] (.onBegin ^js gesture handler))
@@ -37,10 +35,6 @@
(defn min-distance [gesture dist] (.minDistance ^js gesture dist))
(defn fail-offset-x [gesture offset] (.failOffsetX ^js gesture offset))
(defn hit-slop [gesture settings] (.hitSlop ^js gesture settings))
(defn number-of-taps [gesture count] (.numberOfTaps ^js gesture count))
(defn enabled [gesture enabled?] (.enabled ^js gesture enabled?))
-4
View File
@@ -33,10 +33,6 @@
[comp]
(.showOverlay Navigation (clj->js comp)))
(defn pop-to
[comp]
(.popTo Navigation (clj->js comp)))
(defn pop-to-root
[tab]
(.popToRoot Navigation (clj->js tab)))
+1 -3
View File
@@ -1,5 +1,5 @@
(ns react-native.permissions
(:require ["react-native-permissions" :refer (check openSettings requestMultiple PERMISSIONS RESULTS)]
(:require ["react-native-permissions" :refer (check requestMultiple PERMISSIONS RESULTS)]
[react-native.platform :as platform]))
(def permissions-map
@@ -38,5 +38,3 @@
(-> (check (get permissions-map permission))
(.then #(on-result (not (#{(.-BLOCKED RESULTS) (.-DENIED RESULTS)} %))))
(.catch #(on-error %))))
(def open-settings openSettings)
-1
View File
@@ -34,7 +34,6 @@
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
(def view (reagent/adapt-react-class (.-View reanimated)))
(def text (reagent/adapt-react-class (.-Text reanimated)))
(def scroll-view (reagent/adapt-react-class (.-ScrollView reanimated)))
(def image (reagent/adapt-react-class (.-Image reanimated)))
+12 -12
View File
@@ -22,7 +22,7 @@
(rf/defn fetch
[cofx id]
(let [network (get-in cofx [:db :networks/current-network])]
(get-in cofx [:db :profile/profile :custom-bootnodes network id])))
(get-in cofx [:db :multiaccount :custom-bootnodes network id])))
(rf/defn set-input
{:events [:bootnodes.ui/input-changed]}
@@ -54,26 +54,26 @@
(defn custom-bootnodes-in-use?
[{:keys [db]}]
(let [network (:networks/current-network db)]
(get-in db [:profile/profile :custom-bootnodes-enabled? network])))
(get-in db [:multiaccount :custom-bootnodes-enabled? network])))
(rf/defn delete
[{{:profile/keys [profile] :as db} :db :as cofx} id]
(let [network (:networks/current-network db)
new-profile (update-in profile [:custom-bootnodes network] dissoc id)]
[{{:keys [multiaccount] :as db} :db :as cofx} id]
(let [network (:networks/current-network db)
new-multiaccount (update-in multiaccount [:custom-bootnodes network] dissoc id)]
(rf/merge cofx
{:db (assoc db :profile/profile new-profile)}
{:db (assoc db :multiaccount new-multiaccount)}
(multiaccounts.update/multiaccount-update
:custom-bootnodes
(:custom-bootnodes new-profile)
(:custom-bootnodes new-multiaccount)
{:success-event (when (custom-bootnodes-in-use? cofx)
[:multiaccounts.update.callback/save-settings-success])}))))
(rf/defn upsert
{:events [:bootnodes.ui/save-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{{:bootnodes/keys [manage] :profile/keys [profile] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
[{{:bootnodes/keys [manage] :keys [multiaccount] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
(let [{:keys [name id url]} manage
network (:networks/current-network db)
bootnode (build
@@ -82,7 +82,7 @@
(:value url)
network)
new-bootnodes (assoc-in
(:custom-bootnodes profile)
(:custom-bootnodes multiaccount)
[network (:id bootnode)]
bootnode)]
@@ -99,7 +99,7 @@
{:events [:bootnodes.ui/custom-bootnodes-switch-toggled]}
[{:keys [db] :as cofx} value]
(let [current-network (:networks/current-network db)
bootnodes-settings (get-in db [:profile/profile :custom-bootnodes-enabled?])]
bootnodes-settings (get-in db [:multiaccount :custom-bootnodes-enabled?])]
(multiaccounts.update/multiaccount-update
cofx
:custom-bootnodes-enabled?
+11 -11
View File
@@ -20,9 +20,9 @@
{:random-id-generator (constantly "some-id")
:db {:bootnodes/manage new-bootnode
:networks/current-network "mainnet_rpc"
:profile/profile {:not-empty
"would throw an error if was empty"}}})]
(is (= expected (get-in actual [:db :profile/profile :custom-bootnodes])))))
:multiaccount {:not-empty
"would throw an error if was empty"}}})]
(is (= expected (get-in actual [:db :multiaccount :custom-bootnodes])))))
(testing "adding an existing bootnode"
(let [new-bootnode {:id {:value "a"}
:name {:value "new-name"}
@@ -35,13 +35,13 @@
{:random-id-generator (constantly "some-id")
:db {:bootnodes/manage new-bootnode
:networks/current-network "mainnet_rpc"
:profile/profile {:custom-bootnodes
:multiaccount {:custom-bootnodes
{"mainnet_rpc"
{"a" {:name "name"
:address "url"
:chain "mainnet_rpc"
:id "a"}}}}}})]
(is (= expected (get-in actual [:db :profile/profile :custom-bootnodes]))))))
(is (= expected (get-in actual [:db :multiaccount :custom-bootnodes]))))))
(deftest set-input-bootnode
(testing "it validates names"
@@ -72,7 +72,7 @@
(deftest edit-bootnode
(let [db {:networks/current-network "mainnet_rpc"
:profile/profile
:multiaccount
{:custom-bootnodes
{"mainnet_rpc"
{"a" {:id "a"
@@ -123,7 +123,7 @@
(deftest fetch-bootnode
(testing "it fetches the bootnode from the db"
(let [cofx {:db {:networks/current-network "mainnet_rpc"
:profile/profile {:custom-bootnodes
:multiaccount {:custom-bootnodes
{"mainnet_rpc"
{"a" {:id "a"
:name "name"
@@ -138,7 +138,7 @@
(testing "it returns true when enabled"
(is (model/custom-bootnodes-in-use?
{:db {:networks/current-network "mainnet_rpc"
:profile/profile {:custom-bootnodes-enabled?
:multiaccount {:custom-bootnodes-enabled?
{"mainnet_rpc" true}}}}))))
(testing "is on a different network"
(testing "it returns false when not enabled"
@@ -146,13 +146,13 @@
(testing "it returns true when enabled"
(is (not (model/custom-bootnodes-in-use?
{:db {:networks/current-network "goerli_rpc"
:profile/profile {:custom-bootnodes-enabled?
:multiaccount {:custom-bootnodes-enabled?
{"mainnnet_rpc" true}}}}))))))
(deftest delete-bootnode
(testing "non existing bootnode"
(let [cofx {:db {:networks/current-network "mainnet_rpc"
:profile/profile {:custom-bootnodes
:multiaccount {:custom-bootnodes
{"mainnet_rpc"
{"a" {:id "a"
:name "name"
@@ -165,7 +165,7 @@
(is (model/fetch actual "a")))))
(testing "existing bootnode"
(let [cofx {:db {:networks/current-network "mainnet_rpc"
:profile/profile {:custom-bootnodes
:multiaccount {:custom-bootnodes
{"mainnet_rpc"
{"a" {:id "a"
:name "name"
+1 -1
View File
@@ -385,7 +385,7 @@
(rf/defn web3-send-async
[cofx dapp-name {:keys [method params id] :as payload} message-id]
(let [message? (web3-sign-message? method)
dapps-address (get-in cofx [:db :profile/profile :dapps-address])
dapps-address (get-in cofx [:db :multiaccount :dapps-address])
typed? (and (not= constants/web3-personal-sign method)
(not= constants/web3-eth-sign method))]
(if (or message? (= constants/web3-send-transaction method))
+1 -1
View File
@@ -42,7 +42,7 @@
(defn get-permission-data
[cofx allowed-permission]
(let [multiaccount (get-in cofx [:db :profile/profile])]
(let [multiaccount (get-in cofx [:db :multiaccount])]
(get {constants/dapp-permission-contact-code (:public-key multiaccount)
constants/dapp-permission-web3 [(:dapps-address multiaccount)]}
allowed-permission)))
+1 -1
View File
@@ -9,7 +9,7 @@
(let [dapp-name "test.com"
dapp-name2 "test2.org"
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
[:profile/profile :public-key]
[:multiaccount :public-key]
"public-key")}
dapp-id (core.tests/get-dapp-id cofx dapp-name)]
(testing "dapps permissions are initialized"
+23 -8
View File
@@ -1,13 +1,16 @@
(ns status-im.chat.models.images
(:require ["react-native-blob-util" :default ReactNativeBlobUtil]
(:require ["@react-native-community/cameraroll" :as CameraRoll]
["react-native-blob-util" :default ReactNativeBlobUtil]
[re-frame.core :as re-frame]
[react-native.share :as share]
[react-native.cameraroll :as cameraroll]
[utils.i18n :as i18n]
[react-native.permissions :as permissions]
[status-im.ui.components.react :as react]
[status-im2.config :as config]
[react-native.fs :as fs]
[utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
(def temp-image-url (str (fs/cache-dir) "/StatusIm_Image.jpeg"))
@@ -19,7 +22,7 @@
:path temp-image-url}))
(.fetch "GET" base64-uri)
(.then #(on-success (.path %)))
(.catch #(log/error "could not download image" {:error %}))))
(.catch #(log/error "could not save image"))))
(defn share-image
[uri]
@@ -30,11 +33,23 @@
#(fs/unlink downloaded-url)
#(fs/unlink downloaded-url)))))
(defn save-image-to-gallery
[base64-uri on-success]
(-> (download-image-http base64-uri cameraroll/save-image)
(.then on-success)
(.catch #(log/error (str "could not save image to gallery" %)))))
(defn save-to-gallery [path] (.save CameraRoll path))
(re-frame/reg-fx
::save-image-to-gallery
(fn [base64-uri]
(if platform/ios?
(-> (download-image-http base64-uri save-to-gallery)
(.catch #(utils/show-popup (i18n/label :t/error)
(i18n/label :t/external-storage-denied))))
(permissions/request-permissions
{:permissions [:write-external-storage]
:on-allowed #(download-image-http base64-uri save-to-gallery)
:on-denied (fn []
(utils/set-timeout
#(utils/show-popup (i18n/label :t/error)
(i18n/label :t/external-storage-denied))
50))}))))
(re-frame/reg-fx
::chat-open-image-picker-camera
+9 -10
View File
@@ -11,18 +11,17 @@
[status-im2.contexts.chat.composer.link-preview.events :as link-preview]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.string :as utils.string]))
[utils.re-frame :as rf]))
(defn text->emoji
"Replaces emojis in a specified `text`"
[text]
(utils.string/safe-replace text
#":([a-z_\-+0-9]*):"
(fn [[original emoji-id]]
(if-let [emoji-map (object/get (.-lib emojis) emoji-id)]
(.-char ^js emoji-map)
original))))
(utils/safe-replace text
#":([a-z_\-+0-9]*):"
(fn [[original emoji-id]]
(if-let [emoji-map (object/get (.-lib emojis) emoji-id)]
(.-char ^js emoji-map)
original))))
;; effects
(re-frame/reg-fx
@@ -148,7 +147,7 @@
(when-not (string/blank? input-text)
(let [{:keys [message-id]}
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])
preferred-name (get-in db [:profile/profile :preferred-name])
preferred-name (get-in db [:multiaccount :preferred-name])
emoji? (message-content/emoji-only-content? {:text input-text
:response-to message-id})]
{:chat-id current-chat-id
@@ -170,7 +169,7 @@
{:chat-id chat-id
:album-id album-id
:content-type constants/content-type-image
:image-path (utils.string/safe-replace resized-uri #"file://" "")
:image-path (utils/safe-replace resized-uri #"file://" "")
:image-width width
:image-height height
:text input-text
+2 -2
View File
@@ -83,7 +83,7 @@
[{db :db} chat-id]
{:db (mark-chat-all-read db chat-id)
:clear-message-notifications [[chat-id]
(get-in db [:profile/profile :remote-push-notifications-enabled?])]
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
:json-rpc/call [{:method "wakuext_markAllRead"
:params [chat-id]
:on-success #(re-frame/dispatch [::mark-all-read-successful])}]})
@@ -94,7 +94,7 @@
(let [community-chat-ids (map #(str community-id %)
(keys (get-in db [:communities community-id :chats])))]
{:clear-message-notifications [community-chat-ids
(get-in db [:profile/profile :remote-push-notifications-enabled?])]
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
:json-rpc/call [{:method "wakuext_markAllReadInCommunity"
:params [community-id]
:on-success #(re-frame/dispatch
+1 -1
View File
@@ -9,7 +9,7 @@
{:db (assoc db
:commands/select-account
{:message message
:from (ethereum/get-default-account (:profile/wallet-accounts db))})
:from (ethereum/get-default-account (:multiaccount/accounts db))})
:show-select-acc-sheet nil})
(rf/defn set-selected-account
+6 -6
View File
@@ -11,7 +11,7 @@
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im2.common.toasts.events :as toasts]
[status-im2.constants :as constants]
[status-im2.contexts.shell.activity-center.events :as activity-center]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
@@ -102,7 +102,7 @@
(rf/defn handle-requests-to-join
[{:keys [db]} requests]
(let [my-public-key (get-in db [:profile/profile :public-key])]
(let [my-public-key (get-in db [:multiaccount :public-key])]
{:db (reduce (fn [db {:keys [public-key] :as request}]
(let [my-request? (= my-public-key public-key)]
(if my-request?
@@ -278,7 +278,7 @@
(let [community-chat-ids (map #(str community-id %)
(keys (get-in db [:communities community-id :chats])))]
{:clear-message-notifications [community-chat-ids
(get-in db [:profile/profile :remote-push-notifications-enabled?])]
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
:dispatch [:shell/close-switcher-card community-id]
:json-rpc/call [{:method "wakuext_leaveCommunity"
:params [community-id]
@@ -795,14 +795,14 @@
(rf/defn store-category-state
{:events [::store-category-state]}
[{:keys [db]} community-id category-id state-open?]
(let [public-key (get-in db [:profile/profile :public-key])
(let [public-key (get-in db [:multiaccount :public-key])
hash (category-hash public-key community-id category-id)]
{::async-storage/set! {hash state-open?}}))
(rf/defn update-category-states-in-db
{:events [::category-states-loaded]}
[{:keys [db]} community-id hashes states]
(let [public-key (get-in db [:profile/profile :public-key])
(let [public-key (get-in db [:multiaccount :public-key])
categories-old (get-in db [:communities community-id :categories])
categories (reduce (fn [acc [category-id category]]
(let [hash (get hashes category-id)
@@ -816,7 +816,7 @@
(rf/defn load-category-states
{:events [:communities/load-category-states]}
[{:keys [db]} community-id]
(let [public-key (get-in db [:profile/profile :public-key])
(let [public-key (get-in db [:multiaccount :public-key])
categories (get-in db [:communities community-id :categories])
{:keys [keys hashes]} (reduce (fn [acc category]
(let [category-id (get category 0)
+2 -2
View File
@@ -6,7 +6,7 @@
[status-im2.contexts.contacts.events :as contacts-store]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[status-im2.contexts.shell.activity-center.events :as activity-center]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.navigation.events :as navigation]))
(rf/defn clean-up-chat
@@ -49,7 +49,7 @@
(assoc-in [:contacts/contacts public-key :added?] false))
:dispatch [:shell/close-switcher-card public-key]
:clear-message-notifications
[[public-key] (get-in db [:profile/profile :remote-push-notifications-enabled?])]}
[[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
(activity-center/notifications-fetch-unread-count)
fxs)))
+1 -1
View File
@@ -5,7 +5,7 @@
(defn get-currency
[db]
(get-in db [:profile/profile :currency] :usd))
(get-in db [:multiaccount :currency] :usd))
(rf/defn set-currency
{:events [:wallet.settings.ui/currency-selected]}
+7 -9
View File
@@ -3,18 +3,16 @@
[status-im.currency.core :as models]))
(deftest get-currency
(is (= :usd (models/get-currency {:profile/profile {:currency :usd}})))
(is (= :usd (models/get-currency {:profile/profile {:not-empty "would throw an error if was empty"}})))
(is (= :aud (models/get-currency {:profile/profile {:currency :aud}}))))
(is (= :usd (models/get-currency {:multiaccount {:currency :usd}})))
(is (= :usd (models/get-currency {:multiaccount {:not-empty "would throw an error if was empty"}})))
(is (= :aud (models/get-currency {:multiaccount {:currency :aud}}))))
(deftest set-currency
(let [cofx (models/set-currency {:db {:profile/profile {:not-empty
"would throw an error if was empty"}}}
(let [cofx (models/set-currency {:db {:multiaccount {:not-empty "would throw an error if was empty"}}}
:usd)]
(is (= :usd (get-in cofx [:db :profile/profile :currency]))))
(is (= :usd (get-in cofx [:db :multiaccount :currency]))))
(is
(= :jpy
(get-in (models/set-currency {:db {:profile/profile {:not-empty
"would throw an error if was empty"}}}
(get-in (models/set-currency {:db {:multiaccount {:not-empty "would throw an error if was empty"}}}
:jpy)
[:db :profile/profile :currency]))))
[:db :multiaccount :currency]))))
+1 -1
View File
@@ -2,7 +2,7 @@
(:require [clojure.set :as set]
[status-im.data-store.messages :as messages]
[status-im2.constants :as constants]
[status-im2.contexts.shell.activity-center.notification-types :as notification-types]))
[status-im2.contexts.activity-center.notification-types :as notification-types]))
(defn mark-notifications-as-read
[notifications]
@@ -2,7 +2,7 @@
(:require [cljs.test :refer [deftest is testing]]
[status-im2.constants :as constants]
[status-im.data-store.activities :as store]
[status-im2.contexts.shell.activity-center.notification-types :as notification-types]))
[status-im2.contexts.activity-center.notification-types :as notification-types]))
(def chat-id
"0x04c66155")
+10 -10
View File
@@ -83,7 +83,7 @@
{:events [::save-username]}
[{:keys [db] :as cofx} custom-domain? username redirectToSummary]
(let [name (fullname custom-domain? username)
names (get-in db [:profile/profile :usernames] [])
names (get-in db [:multiaccount :usernames] [])
new-names (conj names name)]
(rf/merge cofx
(multiaccounts.update/multiaccount-update
@@ -102,7 +102,7 @@
[{:keys [db]}]
(let [{:keys [username address custom-domain?]} (:ens/registration db)
address (or address (ethereum/default-address db))
{:keys [public-key]} (:profile/profile db)
{:keys [public-key]} (:multiaccount db)
chain-id (ethereum/chain-id db)
username (fullname custom-domain? username)]
(ens/set-pub-key-prepare-tx
@@ -169,7 +169,7 @@
[{:keys [db]} address]
(let [{:keys [username]}
(:ens/registration db)
{:keys [public-key]} (:profile/profile db)
{:keys [public-key]} (:multiaccount db)
chain-id (ethereum/chain-id db)]
(ens/register-prepare-tx
chain-id
@@ -211,7 +211,7 @@
{:events [::set-username-candidate]}
[{:keys [db]} username]
(let [{:keys [custom-domain?]} (:ens/registration db)
usernames (into #{} (get-in db [:profile/profile :usernames]))
usernames (into #{} (get-in db [:multiaccount :usernames]))
state (state custom-domain? username usernames)]
(reset! resolve-last-id (random/id))
(merge
@@ -220,10 +220,10 @@
:username username
:state state)}
(when (= state :searching)
(let [{:profile/keys [profile]} db
{:keys [public-key]} profile
addresses (ethereum/addresses-without-watch db)
chain-id (ethereum/chain-id db)]
(let [{:keys [multiaccount]} db
{:keys [public-key]} multiaccount
addresses (ethereum/addresses-without-watch db)
chain-id (ethereum/chain-id db)]
{::resolve-owner [chain-id
(fullname custom-domain? username)
#(on-resolve-owner
@@ -323,8 +323,8 @@
(rf/defn remove-username
{:events [::remove-username]}
[{:keys [db] :as cofx} name]
(let [names (get-in db [:profile/profile :usernames] [])
preferred-name (get-in db [:profile/profile :preferred-name])
(let [names (get-in db [:multiaccount :usernames] [])
preferred-name (get-in db [:multiaccount :preferred-name])
new-names (remove #(= name %) names)]
(rf/merge cofx
(multiaccounts.update/multiaccount-update
+3 -3
View File
@@ -82,7 +82,7 @@
(defn current-address
[db]
(-> (get-in db [:profile/profile :address])
(-> (get-in db [:multiaccount :address])
normalized-hex))
(defn get-default-account
@@ -91,7 +91,7 @@
(defn default-address
[db]
(-> (get db :profile/wallet-accounts)
(-> (get db :multiaccount/accounts)
get-default-account
:address))
@@ -99,7 +99,7 @@
[db]
(into #{}
(remove #(= (:type %) :watch)
(map #(eip55/address->checksum (:address %)) (get db :profile/wallet-accounts)))))
(map #(eip55/address->checksum (:address %)) (get db :multiaccount/accounts)))))
(defn naked-address
[s]
@@ -401,5 +401,5 @@
[{:keys [db]}]
{:transactions/get-transfers
{:chain-tokens (:wallet/all-tokens db)
:addresses (map :address (get db :profile/wallet-accounts))
:addresses (map :address (get db :multiaccount/accounts))
:fetch-more? false}})
+8 -8
View File
@@ -52,8 +52,8 @@
status-im.wallet.choose-recipient.core
[status-im.wallet.core :as wallet]
status-im.wallet.custom-tokens.core
status-im2.contexts.shell.activity-center.events
status-im2.contexts.shell.activity-center.notification.contact-requests.events
status-im2.contexts.activity-center.events
status-im2.contexts.activity-center.notification.contact-requests.events
status-im2.contexts.shell.jump-to.events
status-im2.contexts.onboarding.events
status-im.chat.models.gaps
@@ -117,11 +117,11 @@
(rf/defn system-theme-mode-changed
{:events [:system-theme-mode-changed]}
[{:keys [db] :as cofx} _]
(let [current-theme-type (get-in cofx [:db :profile/profile :appearance])]
(let [current-theme-type (get-in cofx [:db :multiaccount :appearance])]
(when (and (multiaccounts.model/logged-in? db)
(= current-theme-type status-im2.constants/theme-type-system))
{:multiaccounts.ui/switch-theme-fx
[(get-in db [:profile/profile :appearance])
[(get-in db [:multiaccount :appearance])
(:view-id db) true]})))
(def authentication-options
@@ -146,7 +146,7 @@
[{:keys [db now] :as cofx}]
(let [new-account? (get db :onboarding-2/new-account?)
app-in-background-since (get db :app-in-background-since)
signed-up? (get-in db [:profile/profile :signed-up?])
signed-up? (get-in db [:multiaccount :signed-up?])
biometric-auth? (= (:auth-method db) "biometric")
requires-bio-auth (and
signed-up?
@@ -202,7 +202,7 @@
(cond
(= :chat view-id)
{::async-storage/set! {:chat-id (get-in cofx [:db :current-chat-id])
:key-uid (get-in cofx [:db :profile/profile :key-uid])}
:key-uid (get-in cofx [:db :multiaccount :key-uid])}
:db (assoc db :screens/was-focused-once? true)}
(= :login view-id)
@@ -291,7 +291,7 @@
(rf/defn close-information-box
{:events [:close-information-box]}
[{:keys [db]} id global?]
(let [public-key (get-in db [:profile/profile :public-key])
(let [public-key (get-in db [:multiaccount :public-key])
hash (information-box-id-hash id public-key global?)]
{::async-storage/set! {hash true}
:db (assoc-in db [:information-box-states id] true)}))
@@ -310,7 +310,7 @@
(rf/defn load-information-box-states
{:events [:load-information-box-states]}
[{:keys [db]}]
(let [public-key (get-in db [:profile/profile :public-key])
(let [public-key (get-in db [:multiaccount :public-key])
{:keys [keys hashes]} (reduce (fn [acc {:keys [id global?]}]
(let [hash (information-box-id-hash
id
+1 -1
View File
@@ -75,7 +75,7 @@
(rf/defn save
{:events [:fleet.ui/save-fleet-confirmed]}
[{:keys [db now] :as cofx} fleet]
(let [old-fleet (get-in db [:profile/profile :fleet])]
(let [old-fleet (get-in db [:multiaccount :fleet])]
(when (not= fleet old-fleet)
(rf/merge
cofx
+1 -1
View File
@@ -7,7 +7,7 @@
[re-frame.core :as re-frame]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.constants :as constants]
[status-im2.contexts.shell.activity-center.events :as activity-center]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.navigation.events :as navigation]
[utils.re-frame :as rf]))
+88 -27
View File
@@ -12,6 +12,7 @@
status-im2.navigation.core
status-im2.subs.root ; so integration tests can run independently
[taoensso.timbre :as log]
[utils.security.core :as security]
[status-im2.constants :as constants]))
(def password "testabc")
@@ -24,7 +25,7 @@
(defn initialize-app!
[]
(rf/dispatch [:app-started]))
(rf/dispatch [:setup/app-started]))
(defn generate-and-derive-addresses!
[]
@@ -36,8 +37,20 @@
(defn assert-app-initialized
[]
(let [app-state @(rf/subscribe [:app-state])]
(is (= "active" app-state))))
(let [app-state @(rf/subscribe [:app-state])
multiaccounts-loading? @(rf/subscribe [:multiaccounts/loading])]
(is (= "active" app-state))
(is (false? multiaccounts-loading?))))
(defn assert-logout
[]
(let [multiaccounts-loading? @(rf/subscribe [:multiaccounts/loading])]
(is multiaccounts-loading?)))
(defn assert-multiaccounts-generated
[]
(let [wizard-state @(rf/subscribe [:intro-wizard/choose-key])]
(is (= 5 (count (:multiaccounts wizard-state))))))
(defn messenger-started
[]
@@ -47,6 +60,10 @@
[]
(is (messenger-started)))
(defn assert-multiaccount-loaded
[]
(is (false? @(rf/subscribe [:multiaccounts/loading]))))
(defn assert-community-created
[]
(is (= @(rf/subscribe [:communities/create]) community)))
@@ -60,7 +77,7 @@
(defn assert-new-account-created
[]
(is (true? (some #(= (:name %) account-name)
@(rf/subscribe [:profile/wallet-accounts])))))
@(rf/subscribe [:multiaccount/accounts])))))
(defn logout!
[]
@@ -69,11 +86,11 @@
(deftest initialize-app-test
(log/info "========= initialize-app-test ==================")
(rf-test/run-test-async
(rf/dispatch [:app-started])
(rf/dispatch [:setup/app-started])
(rf-test/wait-for
;; use initialize-view because it has the longest avg. time and
;; is dispatched by initialize-multiaccounts (last non-view event)
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(assert-app-initialized))))
(deftest create-account-test
@@ -81,26 +98,29 @@
(rf-test/run-test-async
(initialize-app!) ; initialize app
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!) ; generate 5 new keys
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
(assert-multiaccount-loaded) ; assert keys are generated
(create-multiaccount!) ; create a multiaccount
(rf-test/wait-for ; wait for login
[::transport/messenger-started]
(assert-messenger-started)
(logout!)
(rf-test/wait-for [::logout/logout-method]))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout)))))))
(deftest create-community-test
(log/info "====== create-community-test ==================")
(rf-test/run-test-async
(initialize-app!) ; initialize app
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!) ; generate 5 new keys
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success]
(assert-multiaccount-loaded) ; assert keys are generated
(create-multiaccount!) ; create a multiaccount
(rf-test/wait-for ; wait for login
[::transport/messenger-started]
@@ -113,17 +133,19 @@
[:status-im.communities.core/community-created]
(assert-community-created)
(logout!)
(rf-test/wait-for [::logout/logout-method])))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))
(deftest create-wallet-account-test
(log/info "====== create-wallet-account-test ==================")
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!) ; generate 5 new keys
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success]
(assert-multiaccount-loaded) ; assert keys are generated
(create-multiaccount!) ; create a multiaccount
(rf-test/wait-for ; wait for login
[::transport/messenger-started]
@@ -133,28 +155,30 @@
[:wallet.accounts/account-stored]
(assert-new-account-created) ; assert account was created
(logout!)
(rf-test/wait-for [::logout/logout-method])))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))
(deftest back-up-seed-phrase-test
(log/info "========= back-up-seed-phrase-test ==================")
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!)
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success]
(assert-multiaccount-loaded)
(create-multiaccount!)
(rf-test/wait-for
[::transport/messenger-started]
(assert-messenger-started)
(rf/dispatch-sync [:set-in [:my-profile/seed :step] :12-words]) ; display seed phrase to user
(rf/dispatch-sync [:my-profile/enter-two-random-words]) ; begin prompting user for seed words
(let [{:keys [mnemonic]} @(rf/subscribe [:profile/profile])
seed @(rf/subscribe [:my-profile/seed])
word1 (second (:first-word seed))
word2 (second (:second-word seed))]
(is (= 12 (count (string/split mnemonic #" ")))) ; assert 12-word seed phrase
(let [ma @(rf/subscribe [:multiaccount])
seed @(rf/subscribe [:my-profile/seed])
word1 (second (:first-word seed))
word2 (second (:second-word seed))]
(is (= 12 (count (string/split (:mnemonic ma) #" ")))) ; assert 12-word seed phrase
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word1])
(rf/dispatch-sync [:my-profile/set-step :second-word])
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word2])
@@ -164,13 +188,42 @@
[:my-profile/finish-success]
(is (nil? @(rf/subscribe [:mnemonic]))) ; assert seed phrase has been removed
(logout!)
(rf-test/wait-for [::logout/logout-method]))))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout)))))))))
(def multiaccount-name "Narrow Frail Lemming")
(def multiaccount-mnemonic
"tattoo ramp health green tongue universe style vapor become tape lava reason")
(def multiaccount-key-uid "0x694b8229524820a3a00a6e211141561d61b251ad99d6b65daf82a73c9a57697b")
(deftest recover-multiaccount-test
(log/info "========= recover-multiaccount-test ==================")
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:setup/initialize-view]
(rf/dispatch-sync [:init-root :onboarding])
(rf/dispatch-sync [:multiaccounts.recover.ui/recover-multiaccount-button-pressed])
(rf/dispatch-sync [:status-im.multiaccounts.recover.core/enter-phrase-pressed])
(rf/dispatch-sync [:multiaccounts.recover/enter-phrase-input-changed
(security/mask-data multiaccount-mnemonic)])
(rf/dispatch [:multiaccounts.recover/enter-phrase-next-pressed])
(rf-test/wait-for
[:status-im.multiaccounts.recover.core/import-multiaccount-success]
(rf/dispatch-sync [:multiaccounts.recover/re-encrypt-pressed])
(rf/dispatch [:multiaccounts.recover/enter-password-next-pressed password])
(rf-test/wait-for
[:status-im.multiaccounts.recover.core/store-multiaccount-success]
(let [multiaccount @(rf/subscribe [:multiaccount])] ; assert multiaccount is recovered
(is (= multiaccount-key-uid (:key-uid multiaccount)))
(is (= multiaccount-name (:name multiaccount))))
(rf-test/wait-for ; wait for login
[::transport/messenger-started]
(assert-messenger-started)
(logout!)
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))
(def chat-id
"0x0402905bed83f0bbf993cee8239012ccb1a8bc86907ead834c1e38476a0eda71414eed0e25f525f270592a2eebb01c9119a4ed6429ba114e51f5cb0a28dae1adfd")
@@ -179,10 +232,11 @@
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!)
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
(assert-multiaccount-loaded)
(create-multiaccount!)
(rf-test/wait-for
[::transport/messenger-started]
@@ -193,17 +247,19 @@
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
(logout!)
(rf-test/wait-for [::logout/logout-method])))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))
(deftest delete-chat-test
(log/info "========= delete-chat-test ==================")
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!)
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
(assert-multiaccount-loaded)
(create-multiaccount!)
(rf-test/wait-for
[::transport/messenger-started]
@@ -217,17 +273,19 @@
(rf/dispatch-sync [:chat.ui/show-remove-confirmation chat-id])
(rf/dispatch-sync [:chat.ui/remove-chat chat-id])
(logout!)
(rf-test/wait-for [::logout/logout-method])))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))
(deftest mute-chat-test
(log/info "========= mute-chat-test ==================")
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!)
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
(assert-multiaccount-loaded)
(create-multiaccount!)
(rf-test/wait-for
[::transport/messenger-started]
@@ -247,7 +305,8 @@
[:chat/mute-successfully]
(is (not @(rf/subscribe [:chats/muted chat-id])))
(logout!)
(rf-test/wait-for [::logout/logout-method])))))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout))))))))))
(deftest add-contact-test
(log/info "========= add-contact-test ==================")
@@ -259,10 +318,11 @@
(rf-test/run-test-async
(initialize-app!)
(rf-test/wait-for
[:profile/get-profiles-overview-success]
[:setup/initialize-view]
(generate-and-derive-addresses!)
(rf-test/wait-for
[:multiaccount-generate-and-derive-addresses-success]
(assert-multiaccount-loaded)
(create-multiaccount!)
(rf-test/wait-for
[::transport/messenger-started]
@@ -283,4 +343,5 @@
(let [contact @(rf/subscribe [:contacts/current-contact])]
(is (= three-words-name (:primary-name contact))))
(logout!)
(rf-test/wait-for [::logout/logout-method]))))))))))
(rf-test/wait-for [::logout/logout-method]
(assert-logout)))))))))))
+3 -3
View File
@@ -17,7 +17,7 @@
(rf/merge cofx
{:db (-> db
(assoc-in [:keycard :creating-backup?] backup-type))}
(when (:profile/profile db)
(when (:multiaccount db)
(navigation/navigate-to :my-profile nil))
(navigation/navigate-to :seed-phrase nil)))
@@ -48,7 +48,7 @@
{:events [::start-keycard-backup]}
[{:keys [db] :as cofx}]
{::multiaccounts.recover/import-multiaccount {:passphrase (-> db
:profile/key-storage
:multiaccounts/key-storage
:seed-phrase
mnemonic/sanitize-passphrase)
:password nil
@@ -66,7 +66,7 @@
:recovering? true
:selected-storage-type :advanced)
(assoc-in [:keycard :flow] :recovery)
(update :profile/key-storage dissoc :seed-phrase))
(update :multiaccounts/key-storage dissoc :seed-phrase))
:dismiss-keyboard nil}
(common/listen-to-hardware-back-button)
(navigation/navigate-to :keycard-onboarding-intro nil)))
+1 -1
View File
@@ -152,7 +152,7 @@
(if puk-restore?
(navigation/navigate-to :multiaccounts nil)
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings]))
(when (:profile/login db)
(when (:multiaccounts/login db)
(common/get-keys-from-keycard)))))
(rf/defn on-change-puk-success
+14 -14
View File
@@ -52,7 +52,7 @@
:init
has-master-key?
:profile/profile
:multiaccount
(and (not paired?)
(zero? free-pairing-slots))
@@ -68,7 +68,7 @@
(defn find-multiaccount-by-keycard-instance-uid
[db keycard-instance-uid]
(when keycard-instance-uid
(->> (:profile/profiles-overview db)
(->> (:multiaccounts/multiaccounts db)
vals
(filter #(= keycard-instance-uid (:keycard-instance-uid %)))
first)))
@@ -76,7 +76,7 @@
(defn find-multiaccount-by-key-uid
[db key-uid]
(when key-uid
(->> (:profile/profiles-overview db)
(->> (:multiaccounts/multiaccounts db)
vals
(filter #(= (ethereum/normalized-hex key-uid) (:key-uid %)))
first)))
@@ -86,7 +86,7 @@
(get-pairing db (get-in db [:keycard :application-info :key-uid])))
([db key-uid]
(or
(get-in db [:profile/profile :keycard-pairing])
(get-in db [:multiaccount :keycard-pairing])
(get-in db [:keycard :secrets :pairing])
(when key-uid
(:keycard-pairing
@@ -324,7 +324,7 @@
(rf/defn get-keys-from-keycard
[{:keys [db]}]
(let [key-uid (get-in db [:profile/login :key-uid])
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
pin (string/join (get-in db [:keycard :pin :login]))]
(log/debug "[keycard] get-keys-from-keycard"
", not empty pin:"
@@ -339,11 +339,11 @@
(let [{:keys [key-uid encryption-public-key whisper-private-key]
:as account-data}
(js->clj data :keywordize-keys true)
{:keys [name]} (get-in db [:profile/profiles-overview key-uid])
{:keys [name]} (get-in db [:multiaccounts/multiaccounts key-uid])
key-uid (get-in db [:keycard :application-info :key-uid])
multiaccount-data (types/clj->json {:name name
:key-uid key-uid})
save-keys? (get-in db [:profile/login :save-password?])]
save-keys? (get-in db [:multiaccounts/login :save-password?])]
(rf/merge cofx
{:db
(-> db
@@ -353,13 +353,13 @@
assoc
:puk-retry-counter 5
:pin-retry-counter 3)
(assoc-in [:keycard :profile/profile]
(assoc-in [:keycard :multiaccount]
(update account-data :whisper-public-key ethereum/normalized-hex))
(assoc-in [:keycard :flow] nil)
(update :profile/login assoc
:password encryption-public-key
:key-uid key-uid
:name name))
(update :multiaccounts/login assoc
:password encryption-public-key
:key-uid key-uid
:name name))
:keycard/login-with-keycard {:multiaccount-data multiaccount-data
:password encryption-public-key
@@ -379,7 +379,7 @@
(hide-connection-sheet)
; do not try to display the popover if it is already open or
; we are in the login interface (which has a different handling)
(when-not (or (:profile/login db) (:popover/popover db))
(when-not (or (:multiaccounts/login db) (:popover/popover db))
(popover/show-popover {:view card-status}))))
(rf/defn blocked-keycard-popup
@@ -536,7 +536,7 @@
(defn keycard-multiaccount?
[db]
(boolean (get-in db [:profile/profile :keycard-pairing])))
(boolean (get-in db [:multiaccount :keycard-pairing])))
(rf/defn verify-pin
{:events [:keycard/verify-pin]}
+3 -3
View File
@@ -543,7 +543,7 @@
:not-paired :pair
:no-pairing-slots :no-slots
:init :card-ready
:profile/profile :import-multiaccount
:multiaccount :import-multiaccount
:begin))})
(rf/defn show-no-keycard-applet-alert
@@ -586,7 +586,7 @@
(common/clear-on-card-read)
(load-pin-screen)))))
(when (and (= card-state :profile/profile)
(when (and (= card-state :multiaccount)
(= flow :import))
(if (common/find-multiaccount-by-key-uid db key-uid)
(multiaccounts.recover/show-existing-multiaccount-alert key-uid)
@@ -599,7 +599,7 @@
(navigation/navigate-to :keycard-recovery-no-key nil)
(show-no-keycard-applet-alert)))
(when (and (= card-state :profile/profile)
(when (and (= card-state :multiaccount)
(#{:create :recovery} flow))
(show-keycard-has-multiaccount-alert)))))
+1 -1
View File
@@ -62,7 +62,7 @@
"04f2a432677a1b7c4f1bb22078135821d1d10fce23422297b5c808a545f2b61cdba38ee7394762172fc6ff5e9e28db7535e555efe2812905ffd4e0c25e82a98ae8"
"whisper-address" "87df2285f90b71221fab6267b7cb37532fedbb1f"
"wallet-address" "7e92236392a850980d00d0cd2a4b92886bd7fe7b"})
[:db :keycard :profile/profile])
[:db :keycard :multiaccount])
[:whisper-private-key
:whisper-public-key
:encryption-public-key
+1 -1
View File
@@ -11,7 +11,7 @@
(rf/defn delete-card
[{:keys [db] :as cofx}]
(let [key-uid (get-in db [:keycard :application-info :key-uid])
multiaccount-key-uid (get-in db [:profile/profile :key-uid])]
multiaccount-key-uid (get-in db [:multiaccount :key-uid])]
(if (and key-uid
(= key-uid multiaccount-key-uid))
{:keycard/delete nil}
+10 -10
View File
@@ -69,9 +69,9 @@
:error nil
:status nil))
:hide-popover nil})
(when (:profile/profile db)
(when (:multiaccount db)
(navigation/navigate-to :my-profile nil))
(when-not (:profile/login db)
(when-not (:multiaccounts/login db)
(if (:popover/popover db)
(navigation/navigate-replace :keycard-pin nil)
(navigation/navigate-to :keycard-pin nil)))))
@@ -94,7 +94,7 @@
key-uid (get-in db [:keycard :application-info :key-uid])
paired? (get-in db [:keycard :application-info :paired?])
multiaccount (get-in db
[:profile/profiles-overview (get-in db [:profile/login :key-uid])])
[:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :key-uid])])
multiaccount-key-uid (get multiaccount :key-uid)
multiaccount-mismatch? (or (nil? multiaccount)
(not= multiaccount-key-uid key-uid))]
@@ -151,7 +151,7 @@
:multiaccounts-stack
[:multiaccounts
:keycard-login-pin])
(let [{:keys [name]} (get-in db [:profile/profiles-overview key-uid])
(let [{:keys [name]} (get-in db [:multiaccounts/multiaccounts key-uid])
multiaccount-data (types/clj->json {:name name
:key-uid key-uid})
account-data {:key-uid key-uid
@@ -161,14 +161,14 @@
(-> db
(assoc-in [:keycard :pin :status] nil)
(assoc-in [:keycard :pin :login] [])
(assoc-in [:keycard :profile/profile]
(assoc-in [:keycard :multiaccount]
(update account-data :whisper-public-key ethereum/normalized-hex))
(assoc-in [:keycard :flow] nil)
(update :profile/login assoc
:password encryption-public-key
:key-uid key-uid
:name name
:save-password? true))
(update :multiaccounts/login assoc
:password encryption-public-key
:key-uid key-uid
:name name
:save-password? true))
:keycard/login-with-keycard
{:multiaccount-data multiaccount-data
:key-uid key-uid
+15 -16
View File
@@ -134,7 +134,7 @@
(rf/defn intro-wizard
{:events [:multiaccounts.create.ui/intro-wizard]}
[{:keys [db] :as cofx}]
(let [accs (get db :profile/profiles-overview)]
(let [accs (get db :multiaccounts/multiaccounts)]
(rf/merge cofx
{:db (-> db
(update :keycard dissoc :flow)
@@ -157,7 +157,7 @@
:interceptors [(re-frame/inject-cofx :random-guid-generator)
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
[{:keys [db] :as cofx}]
(let [{{:keys [secrets flow] :profile/keys [profile]} :keycard} db
(let [{{:keys [multiaccount secrets flow]} :keycard} db
{:keys [address
name
public-key
@@ -172,7 +172,7 @@
instance-uid
key-uid
recovered]}
profile
multiaccount
{:keys [pairing paired-on]} secrets
{:keys [name]}
(if (nil? name)
@@ -238,7 +238,7 @@
(multiaccounts.model/logged-in? db)
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])
(:profile/login db)
(:multiaccounts/login db)
(return-to-keycard-login)
:else
@@ -263,9 +263,9 @@
[{:keys [db] :as cofx}]
(let [pairing (get-in db [:keycard :secrets :pairing])
paired-on (get-in db [:keycard :secrets :paired-on])
instance-uid (get-in db [:keycard :profile/profile :instance-uid])
instance-uid (get-in db [:keycard :multiaccount :instance-uid])
account (-> db
:profile/login
:multiaccounts/login
(assoc :keycard-pairing pairing)
(assoc :save-password? false))
key-uid (-> account :key-uid)
@@ -275,15 +275,14 @@
password (ethereum/sha3 (security/safe-unmask-data (get-in db
[:keycard
:migration-password])))
encryption-pass (get-in db [:keycard :profile/profile :encryption-public-key])
encryption-pass (get-in db [:keycard :multiaccount :encryption-public-key])
login-params {:key-uid key-uid
:multiaccount-data (types/clj->json account)
:password encryption-pass
:chat-key (get-in db
[:keycard :profile/profile :whisper-private-key])}]
:chat-key (get-in db [:keycard :multiaccount :whisper-private-key])}]
{:db (-> db
(assoc-in [:profile/profiles-overview key-uid :keycard-pairing] pairing)
(assoc :profile/login account)
(assoc-in [:multiaccounts/multiaccounts key-uid :keycard-pairing] pairing)
(assoc :multiaccounts/login account)
(assoc :auth-method keychain/auth-method-none)
(update :keycard dissoc :flow :migration-password)
(dissoc :recovered-account?))
@@ -291,7 +290,7 @@
(rf/defn delete-multiaccount
[{:keys [db]}]
(let [key-uid (get-in db [:profile/login :key-uid])]
(let [key-uid (get-in db [:multiaccounts/login :key-uid])]
{:keycard/delete-multiaccount-before-migration
{:key-uid key-uid
:on-error #(re-frame/dispatch [::delete-multiaccount-error %])
@@ -314,7 +313,7 @@
cofx
{:db (-> db
(assoc-in
[:keycard :profile/profile]
[:keycard :multiaccount]
(-> account-data
(update :address ethereum/normalized-hex)
(update :whisper-address ethereum/normalized-hex)
@@ -324,7 +323,7 @@
(update :whisper-public-key ethereum/normalized-hex)
(update :wallet-public-key ethereum/normalized-hex)
(update :wallet-root-public-key ethereum/normalized-hex)
(update :instance-uid #(get-in db [:keycard :profile/profile :instance-uid] %))))
(update :instance-uid #(get-in db [:keycard :multiaccount :instance-uid] %))))
(assoc-in [:keycard :multiaccount-wallet-address] (:wallet-address account-data))
(assoc-in [:keycard :multiaccount-whisper-public-key] (:whisper-public-key account-data))
(assoc-in [:keycard :pin :status] nil)
@@ -363,7 +362,7 @@
pin (common/vector->string (get-in db [:keycard :pin :import-multiaccount]))]
(rf/merge cofx
{:db (-> db
(assoc-in [:keycard :profile/profile :instance-uid] instance-uid)
(assoc-in [:keycard :multiaccount :instance-uid] instance-uid)
(assoc-in [:keycard :pin :status] :verifying)
(assoc-in [:keycard :secrets]
{:pairing pairing'
@@ -388,7 +387,7 @@
(rf/merge
cofx
{:db (update-in db
[:keycard :profile/profile]
[:keycard :multiaccount]
(fn [multiacc]
(assoc multiacc
:recovered (get db :recovered-account?)
+2 -2
View File
@@ -12,7 +12,7 @@
{:events [:keycard/sign]}
[{:keys [db] :as cofx} hash on-success]
(let [card-connected? (get-in db [:keycard :card-connected?])
key-uid (get-in db [:profile/profile :key-uid])
key-uid (get-in db [:multiaccount :key-uid])
keycard-key-uid (get-in db [:keycard :application-info :key-uid])
keycard-pin-retries (get-in db [:keycard :application-info :pin-retry-counter])
keycard-match? (= key-uid keycard-key-uid)
@@ -28,7 +28,7 @@
(when (ethereum/address= from address)
(reduced path)))
nil
(:profile/wallet-accounts db))]
(:multiaccount/accounts db))]
(cond
(not keycard-match?)
(common/show-wrong-keycard-alert cofx)
+6 -6
View File
@@ -44,7 +44,7 @@
:initialized? true
:pin-retry-counter 3
:puk-retry-counter 5
:key-uid (get-in @re-frame.db/app-db [:profile/login :key-uid])})
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
(swap! state assoc :pin default-pin :puk default-puk :password kk1-password)
(connect-card))
@@ -389,11 +389,11 @@
pin
on-failure
#(let [{:keys [key-uid wallet-root-address]}
(get @re-frame.db/app-db :profile/profile)
accounts (get @re-frame.db/app-db :profile/wallet-accounts)
(get @re-frame.db/app-db :multiaccount)
accounts (get @re-frame.db/app-db :multiaccount/accounts)
hashed-password account-password
path-num (inc (get-in @re-frame.db/app-db
[:profile/profile :latest-derived-path]))
[:multiaccount :latest-derived-path]))
path (str "m/" path-num)]
(native-module/multiaccount-load-account
wallet-root-address
@@ -460,8 +460,8 @@
(when (= path (:path acc))
(reduced address)))
nil
(:profile/wallet-accounts @re-frame.db/app-db))
(-> (:profile/wallet-accounts @re-frame.db/app-db)
(:multiaccount/accounts @re-frame.db/app-db))
(-> (:multiaccount/accounts @re-frame.db/app-db)
first
:address))
password account-password]
+27 -27
View File
@@ -2,6 +2,7 @@
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.keycard.common :as common]
[status-im.multiaccounts.key-storage.core :as key-storage]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]
@@ -118,37 +119,36 @@
(defn handle-account-removal
[{:keys [db] :as cofx} keys-removed-from-card?]
(let [key-uid (get-in db [:profile/profile :key-uid])
(let [key-uid (get-in db [:multiaccount :key-uid])
instance-uid (get-in db [:keycard :application-info :instance-uid])
pairings (get-in db [:keycard :pairings])]
(rf/merge
cofx
{:db (-> db
(update :profile/profiles-overview dissoc key-uid)
(assoc-in [:keycard :secrets] nil)
(update-in [:keycard :pairings]
dissoc
(keyword instance-uid))
(update-in [:keycard :pairings] dissoc instance-uid)
(assoc-in [:keycard :whisper-public-key] nil)
(assoc-in [:keycard :wallet-address] nil)
(assoc-in [:keycard :application-info] nil)
(assoc-in [:keycard :pin]
{:status nil
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
:t/profile-deleted-title
:t/database-reset-title))
:content (i18n/label (if keys-removed-from-card?
:t/profile-deleted-keycard
:t/database-reset-content))
:on-dismiss #(re-frame/dispatch [:logout])}}
;;should be reimplemented
;;:key-storage/delete-profile {:key-uid key-uid
;;:on-success #(log/debug "[keycard] remove account ok")
;; :on-error #(log/warn "[keycard] remove account: " %)}
{:db (-> db
(update :multiaccounts/multiaccounts dissoc key-uid)
(assoc-in [:keycard :secrets] nil)
(update-in [:keycard :pairings]
dissoc
(keyword instance-uid))
(update-in [:keycard :pairings] dissoc instance-uid)
(assoc-in [:keycard :whisper-public-key] nil)
(assoc-in [:keycard :wallet-address] nil)
(assoc-in [:keycard :application-info] nil)
(assoc-in [:keycard :pin]
{:status nil
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
:t/profile-deleted-title
:t/database-reset-title))
:content (i18n/label (if keys-removed-from-card?
:t/profile-deleted-keycard
:t/database-reset-content))
:on-dismiss #(re-frame/dispatch [:logout])}
::key-storage/delete-multiaccount {:key-uid key-uid
:on-success #(log/debug "[keycard] remove account ok")
:on-error #(log/warn "[keycard] remove account: " %)}}
(common/clear-on-card-connected)
(common/hide-connection-sheet))))
+1 -1
View File
@@ -34,7 +34,7 @@
(rf/defn generate-new-keycard-account
{:events [:wallet.accounts/generate-new-keycard-account]}
[{:keys [db]}]
(let [path-num (inc (get-in db [:profile/profile :latest-derived-path]))
(let [path-num (inc (get-in db [:multiaccount :latest-derived-path]))
path (str constants/path-wallet-root "/" path-num)
pin (common/vector->string (get-in db [:keycard :pin :export-key]))]
{:db
+1 -1
View File
@@ -8,7 +8,7 @@
(rf/defn save-log-level
{:events [:log-level.ui/change-log-level-confirmed]}
[{:keys [db now] :as cofx} log-level]
(let [old-log-level (get-in db [:profile/profile :log-level])]
(let [old-log-level (get-in db [:multiaccount :log-level])]
(when (not= old-log-level log-level)
(rf/merge cofx
(multiaccounts.update/multiaccount-update
+9 -9
View File
@@ -36,7 +36,7 @@
(defn preferred-mailserver-id
[db]
(get-in db [:profile/profile :pinned-mailservers (node/current-fleet-key db)]))
(get-in db [:multiaccount :pinned-mailservers (node/current-fleet-key db)]))
(defn connection-error-dismissed
[db]
@@ -61,7 +61,7 @@
(defn fetch-use-mailservers?
[{:keys [db]}]
(get-in db [:profile/profile :use-mailservers?]))
(get-in db [:multiaccount :use-mailservers?]))
(defonce showing-connection-error-popup? (atom false))
@@ -105,7 +105,7 @@
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
error-dismissed? (connection-error-dismissed db)
pinned-mailserver (get-in db [:profile/profile :pinned-mailservers current-fleet])]
pinned-mailserver (get-in db [:multiaccount :pinned-mailservers current-fleet])]
(when (and pinned-mailserver
(not error-dismissed?)
(not @showing-connection-error-popup?))
@@ -266,9 +266,9 @@
(rf/defn upsert
{:events [:mailserver.ui/save-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{{:mailserver.edit/keys [mailserver] :profile/keys [profile] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
[{{:mailserver.edit/keys [mailserver] :keys [multiaccount] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
(let [{:keys [name url id]} mailserver
current-fleet (node/current-fleet-key db)]
@@ -364,7 +364,7 @@
{:events [:mailserver.ui/connect-confirmed]}
[{:keys [db] :as cofx} current-fleet mailserver-id]
(let [pinned-mailservers (-> db
(get-in [:profile/profile :pinned-mailservers])
(get-in [:multiaccount :pinned-mailservers])
(assoc current-fleet mailserver-id))]
(rf/merge cofx
{:db (assoc db :mailserver/current-id mailserver-id)
@@ -379,7 +379,7 @@
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
pinned-mailservers (-> db
(get-in [:profile/profile :pinned-mailservers])
(get-in [:multiaccount :pinned-mailservers])
(dissoc current-fleet))]
(rf/merge cofx
{:json-rpc/call [{:method "wakuext_setPinnedMailservers"
@@ -396,7 +396,7 @@
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
mailserver-id (:mailserver/current-id db)
pinned-mailservers (get-in db [:profile/profile :pinned-mailservers])]
pinned-mailservers (get-in db [:multiaccount :pinned-mailservers])]
(rf/merge cofx
(multiaccounts.update/multiaccount-update
:pinned-mailservers
+4 -4
View File
@@ -12,7 +12,7 @@
(rf/defn sheet-defaults
[{:keys [db]}]
(let [remember-choice? (get-in db [:profile/profile :remember-syncing-choice?])]
(let [remember-choice? (get-in db [:multiaccount :remember-syncing-choice?])]
{:db (assoc db
:mobile-network/remember-choice?
(or (nil? remember-choice?)
@@ -22,7 +22,7 @@
[{:keys [db] :as cofx}]
(let [initialized? (get db :network-status/initialized?)
logged-in? (multiaccounts.model/logged-in? db)
{:keys [remember-syncing-choice?]} (:profile/profile db)]
{:keys [remember-syncing-choice?]} (:multiaccount db)]
(apply
rf/merge
cofx
@@ -91,13 +91,13 @@
(rf/defn mobile-network-set-syncing
{:events [:mobile-network/set-syncing]}
[{:keys [db] :as cofx} syncing?]
(let [{:keys [remember-syncing-choice?]} (:profile/profile db)]
(let [{:keys [remember-syncing-choice?]} (:multiaccount db)]
((apply-settings syncing? remember-syncing-choice?) cofx)))
(rf/defn mobile-network-ask-on-mobile-network?
{:events [:mobile-network/ask-on-mobile-network?]}
[{:keys [db] :as cofx} ask?]
(let [{:keys [syncing-on-mobile-network?]} (:profile/profile db)]
(let [{:keys [syncing-on-mobile-network?]} (:multiaccount db)]
((apply-settings syncing-on-mobile-network? (not ask?)) cofx)))
(rf/defn mobile-network-restore-defaults
@@ -101,7 +101,7 @@
(.catch #(cb (generate-error-result %))))))
(re-frame/reg-fx
:biometric/get-supported-biometric-auth
:get-supported-biometric-auth
(fn []
(let [callback #(re-frame/dispatch [:init.callback/get-supported-biometric-auth-success %])]
;;NOTE: if we can't save user password, we can't support biometrics
@@ -149,8 +149,8 @@
(rf/defn update-biometric
[{db :db :as cofx} biometric-auth?]
(let [key-uid (or (get-in db [:profile/profile :key-uid])
(get-in db [:profile/login :key-uid]))]
(let [key-uid (or (get-in db [:multiaccount :key-uid])
(get-in db [:multiaccounts/login :key-uid]))]
(rf/merge cofx
(keychain/save-auth-method
key-uid
@@ -214,7 +214,7 @@
cofx
{:db (-> db
(assoc :auth-method keychain/auth-method-none)
(assoc-in [:profile/login :save-password?] false))}
(assoc-in [:multiaccounts/login :save-password?] false))}
(popover/hide-popover)))
(rf/defn setup-done
+6 -6
View File
@@ -120,7 +120,7 @@
(rf/defn switch-preview-privacy-mode-flag
[{:keys [db]}]
(let [private? (get-in db [:profile/profile :preview-privacy?])]
(let [private? (get-in db [:multiaccount :preview-privacy?])]
{::blank-preview-flag-changed private?}))
(re-frame/reg-fx
@@ -153,7 +153,7 @@
{:events [:multiaccounts.ui/switch-theme]}
[cofx theme view-id]
(let [theme (or theme
(get-in cofx [:db :profile/profile :appearance])
(get-in cofx [:db :multiaccount :appearance])
constants/theme-type-dark)]
{:multiaccounts.ui/switch-theme-fx [theme view-id false]}))
@@ -180,7 +180,7 @@
(rf/defn save-profile-picture
{:events [::save-profile-picture]}
[cofx path ax ay bx by]
(let [key-uid (get-in cofx [:db :profile/profile :key-uid])]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
(rf/merge cofx
{:json-rpc/call [{:method "multiaccounts_storeIdentityImage"
:params [key-uid (clean-path path) ax ay bx by]
@@ -191,7 +191,7 @@
(rf/defn save-profile-picture-from-url
{:events [::save-profile-picture-from-url]}
[cofx url]
(let [key-uid (get-in cofx [:db :profile/profile :key-uid])]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
(rf/merge cofx
{:json-rpc/call [{:method "multiaccounts_storeIdentityImageFromURL"
:params [key-uid url]
@@ -207,7 +207,7 @@
(rf/defn delete-profile-picture
{:events [::delete-profile-picture]}
[cofx name]
(let [key-uid (get-in cofx [:db :profile/profile :key-uid])]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
(rf/merge cofx
{:json-rpc/call [{:method "multiaccounts_deleteIdentityImage"
:params [key-uid]
@@ -219,7 +219,7 @@
(rf/defn get-profile-picture
[cofx]
(let [key-uid (get-in cofx [:db :profile/profile :key-uid])]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
{:json-rpc/call [{:method "multiaccounts_getIdentityImages"
:params [key-uid]
:on-success #(re-frame/dispatch [::update-local-picture %])}]}))
+3 -3
View File
@@ -225,13 +225,13 @@
:keycard-pairing keycard-pairing
:keycard-paired-on keycard-paired-on))
db (assoc db
:profile/login {:key-uid key-uid
:multiaccounts/login {:key-uid key-uid
:name name
:password password
:creating? true
:processing true}
:profile/profile new-multiaccount
:profile/wallet-accounts [wallet-account]
:multiaccount new-multiaccount
:multiaccount/accounts [wallet-account]
:networks/current-network config/default-network
:networks/networks (data-store.settings/rpc->networks config/default-networks))
settings (assoc new-multiaccount
@@ -1,13 +1,150 @@
(ns status-im.multiaccounts.key-storage.core
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.mnemonic :as mnemonic]
[utils.i18n :as i18n]
[status-im.keycard.backup-key :as keycard.backup]
[status-im.keycard.common :as common]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.logout.core :as multiaccounts.logout]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[status-im2.navigation.events :as navigation]
[utils.security.core :as security]))
(rf/defn key-and-storage-management-pressed
"This event can be dispatched before login and from profile and needs to redirect accordingly"
{:events [::key-and-storage-management-pressed]}
[{:keys [db] :as cofx}]
(navigation/navigate-to
cofx
(if (multiaccounts.model/logged-in? db)
:actions-logged-in
:actions-not-logged-in)
nil))
(rf/defn move-keystore-checked
{:events [::move-keystore-checked]}
[{:keys [db] :as cofx} checked?]
{:db (assoc-in db [:multiaccounts/key-storage :move-keystore-checked?] checked?)})
(rf/defn reset-db-checked
{:events [::reset-db-checked]}
[{:keys [db] :as cofx} checked?]
{:db (assoc-in db [:multiaccounts/key-storage :reset-db-checked?] checked?)})
(rf/defn navigate-back
{:events [::navigate-back]}
[{:keys [db] :as cofx}]
(rf/merge
cofx
{:db (-> db
(dissoc :recovered-account?)
(update :keycard
dissoc
:from-key-storage-and-migration?
:creating-backup?
:factory-reset-card?))}
(navigation/navigate-back)))
(rf/defn enter-seed-pressed
"User is logged out and probably wants to move multiaccount to Keycard. Navigate to enter seed phrase screen"
{:events [::enter-seed-pressed]}
[{:keys [db] :as cofx}]
(rf/merge
cofx
{:db (assoc db :recovered-account? true)}
(navigation/navigate-to :seed-phrase nil)))
(rf/defn seed-phrase-input-changed
{:events [::seed-phrase-input-changed]}
[{:keys [db] :as cofx} masked-seed-phrase]
(let [seed-phrase (security/safe-unmask-data masked-seed-phrase)]
{:db (update db
:multiaccounts/key-storage assoc
:seed-phrase (when seed-phrase
(string/lower-case seed-phrase))
:seed-shape-invalid? (or (empty? seed-phrase)
(not (mnemonic/valid-length? seed-phrase)))
:seed-word-count (mnemonic/words-count seed-phrase))}))
(rf/defn key-uid-seed-mismatch
{:events [::show-seed-key-uid-mismatch-error-popup]}
[cofx _]
(popover/show-popover cofx {:view :seed-key-uid-mismatch}))
(rf/defn key-uid-matches
{:events [::key-uid-matches]}
[{:keys [db] :as cofx} _]
(let [backup? (get-in db [:keycard :creating-backup?])]
(if backup?
(keycard.backup/start-keycard-backup cofx)
(navigation/navigate-to cofx :storage nil))))
(defn validate-seed-against-key-uid
"Check if the key-uid was generated with the given seed-phrase"
[{:keys [import-mnemonic-fn on-success on-error]} {:keys [seed-phrase key-uid]}]
(import-mnemonic-fn
(mnemonic/sanitize-passphrase seed-phrase)
nil
(fn [result]
(let [{:keys [keyUid]} (types/json->clj result)]
;; if the key-uid from app-db is same as the one returned by multiaccount import,
;; it means that this seed was used to generate this multiaccount
(if (= key-uid keyUid)
(on-success)
(on-error))))))
(re-frame/reg-fx
:key-storage/delete-imported-key
::validate-seed-against-key-uid
(partial validate-seed-against-key-uid
{:import-mnemonic-fn native-module/multiaccount-import-mnemonic
:on-success #(re-frame/dispatch [::key-uid-matches])
:on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])}))
(rf/defn seed-phrase-validated
{:events [::seed-phrase-validated]}
[{:keys [db] :as cofx} validation-error]
(let [error? (-> validation-error
types/json->clj
:error
string/blank?
not)
onboarding? (not (or (:multiaccounts/login db) (:multiaccount db)))]
(if error?
(popover/show-popover cofx {:view :custom-seed-phrase})
{::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase)
;; Unique key-uid of the account for which we are going to move
;; keys
:key-uid (or (-> db :multiaccounts/login :key-uid)
(-> db :multiaccount :key-uid)
(and onboarding?
(-> db
:keycard
:application-info
:key-uid)))}})))
(rf/defn choose-storage-pressed
{:events [::choose-storage-pressed]}
[{:keys [db] :as cofx}]
(let [{:keys [seed-phrase]} (:multiaccounts/key-storage db)]
{::multiaccounts/validate-mnemonic
[(mnemonic/sanitize-passphrase seed-phrase)
#(re-frame/dispatch [::seed-phrase-validated %])]}))
(rf/defn keycard-storage-pressed
{:events [::keycard-storage-pressed]}
[{:keys [db]} selected?]
{:db (assoc-in db [:multiaccounts/key-storage :keycard-storage-selected?] selected?)})
(re-frame/reg-fx
::delete-imported-key
(fn [{:keys [key-uid address password on-success on-error]}]
(let [hashed-pass (ethereum/sha3 (security/safe-unmask-data password))]
(native-module/delete-imported-key
@@ -19,3 +156,132 @@
(if-not (string/blank? error)
(on-error error)
(on-success))))))))
#_"Multiaccount has been deleted from device. We now need to emulate the restore seed phrase process, and make the user land on Keycard setup screen.
To ensure that keycard setup works, we need to:
1. Import multiaccount, derive required keys and save them at the correct location in app-db
2. Take the user to :keycard-onboarding-intro screen in :intro-login-stack
The exact events dispatched for this flow if consumed from the UI are:
:m.r/enter-phrase-input-changed
:m.r/enter-phrase-next-pressed
:m.r/re-encrypt-pressed
:i/on-key-storage-selected ([:intro-wizard :selected-storage-type] is set to :advanced)
:m.r/select-storage-next-pressed
We don't need to take the exact steps, just set the required state and redirect to correct screen
"
(rf/defn import-multiaccount
[{:keys [db] :as cofx}]
{:dispatch [:bottom-sheet/hide-old]
::multiaccounts.recover/import-multiaccount
{:passphrase (get-in db [:multiaccounts/key-storage :seed-phrase])
:password nil
:success-event ::import-multiaccount-success}})
(rf/defn delete-multiaccount-and-init-keycard-onboarding
{:events [::delete-multiaccount-and-init-keycard-onboarding]}
[{:keys [db] :as cofx}]
(rf/merge
{:dispatch [:bottom-sheet/hide-old]
:db (assoc-in db [:multiaccounts/key-storage :reset-db-checked?] true)}
(import-multiaccount)))
(rf/defn storage-selected
{:events [::storage-selected]}
[{:keys [db] :as cofx}]
(if (get-in db [:multiaccounts/key-storage :reset-db-checked?])
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning})
(bottom-sheet/hide-bottom-sheet-old cofx)))
(rf/defn skip-password-pressed
{:events [::skip-password-pressed]}
[cofx]
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning}))
(rf/defn password-changed
{:events [::password-changed]}
[{db :db} password]
(let [unmasked-pass (security/safe-unmask-data password)]
{:db (update db
:keycard assoc
:migration-password password
:migration-password-error nil
:migration-password-valid? (and unmasked-pass (> (count unmasked-pass) 5)))}))
(rf/defn verify-password-result
{:events [::verify-password-result]}
[{:keys [db] :as cofx} result]
(let [{:keys [error]} (types/json->clj result)]
(if (string/blank? error)
(rf/merge
cofx
{:db (update db :keycard dissoc :migration-password-error :migration-password-valid?)}
(import-multiaccount))
{:db (assoc-in db [:keycard :migration-password-error] (i18n/label :t/wrong-password))})))
(rf/defn verify-password
{:events [::verify-password]}
[{:keys [db] :as cofx}]
(native-module/verify-database-password
(get-in db [:multiaccounts/login :key-uid])
(ethereum/sha3 (security/safe-unmask-data (get-in db [:keycard :migration-password])))
#(re-frame/dispatch [::verify-password-result %])))
(rf/defn handle-multiaccount-import
{:events [::import-multiaccount-success]}
[{:keys [db] :as cofx} root-data derived-data]
(rf/merge cofx
{:db (-> db
(update :intro-wizard
assoc
:root-key root-data
:derived derived-data
:recovering? true
:selected-storage-type :advanced)
(assoc-in [:keycard :flow] :recovery)
(assoc-in [:keycard :from-key-storage-and-migration?] true)
(assoc-in [:keycard :converting-account?]
(not (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
(assoc-in [:keycard :delete-account?]
(true? (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
(dissoc :multiaccounts/key-storage))}
(popover/hide-popover)
(common/listen-to-hardware-back-button)
(navigation/navigate-to :keycard-onboarding-intro nil)))
(rf/defn goto-multiaccounts-screen
{:events [::hide-popover-and-goto-multiaccounts-screen]}
[cofx _]
(rf/merge cofx
(popover/hide-popover)
(navigation/navigate-to :multiaccounts nil)))
(rf/defn confirm-logout-and-goto-key-storage
{:events [::confirm-logout-and-goto-key-storage]}
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db (assoc db :goto-key-storage? true)}
(multiaccounts.logout/logout)))
(rf/defn logout-and-goto-key-storage
{:events [::logout-and-goto-key-storage]}
[_]
{:ui/show-confirmation
{:title (i18n/label :t/logout-title)
:content (i18n/label :t/logout-key-management)
:confirm-button-text (i18n/label :t/logout)
:on-accept #(re-frame/dispatch [::confirm-logout-and-goto-key-storage])
:on-cancel nil}})
(comment
;; check import mnemonic output
(native-module/multiaccount-import-mnemonic
"rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
nil
(fn [result]
(prn (types/json->clj result))))
;; check delete account output
(native-module/delete-multiaccount "0x3831d0f22996a65970a214f0a94bfa9a63a21dac235d8dadb91be8e32e7d3ab7"
(fn [result]
(prn ::--delete-account-res-> result))))

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