Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bbeac1ed5 |
+37
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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
-1
@@ -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
|
||||
|
||||
@@ -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 ];
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,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]))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
+117
-157
@@ -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"
|
||||
|
||||
@@ -121,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)
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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?))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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]}
|
||||
|
||||
@@ -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]))))
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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}})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]))
|
||||
|
||||
|
||||
@@ -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)))))))))))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]}
|
||||
|
||||
@@ -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)))))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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))))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 %])}]}))
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
(ns status-im.multiaccounts.key-storage.core-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[clojure.string :as string]
|
||||
[status-im.multiaccounts.key-storage.core :as models]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(deftest move-keystore-checked
|
||||
(testing "Checks checkbox on-press"
|
||||
(let [res (models/move-keystore-checked {:db {}} true)]
|
||||
(is (= true (get-in res [:db :multiaccounts/key-storage :move-keystore-checked?]))))))
|
||||
|
||||
(deftest seed-phrase-input-changed
|
||||
(testing "nil seed phrase shape is invalid"
|
||||
(let [res (models/seed-phrase-input-changed {:db {}} (security/mask-data nil))]
|
||||
(is (get-in res [:db :multiaccounts/key-storage :seed-shape-invalid?]))))
|
||||
|
||||
(let [sample-phrase "h h h h h h h h h h h H" ;; 12 characters
|
||||
res (models/seed-phrase-input-changed {:db {}} (security/mask-data sample-phrase))]
|
||||
(testing "Seed shape for 12 letter seed phrase is valid"
|
||||
(is (false? (get-in res [:db :multiaccounts/key-storage :seed-shape-invalid?]))))
|
||||
|
||||
(testing "Seed words counted correctly"
|
||||
(is (= 12 (get-in res [:db :multiaccounts/key-storage :seed-word-count]))))
|
||||
|
||||
(testing "Seed phrase is lowercased"
|
||||
(is (= (get-in res [:db :multiaccounts/key-storage :seed-phrase])
|
||||
(string/lower-case sample-phrase))))))
|
||||
|
||||
(def seed-key-uid-pair
|
||||
{:seed-phrase "rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
|
||||
:key-uid "0x3831d0f22996a65970a214f0a94bfa9a63a21dac235d8dadb91be8e32e7d3ab7"})
|
||||
|
||||
(defn mock-import-mnemonic-fn
|
||||
[_ _ _]
|
||||
;; return json with keyUid, the real world will have more info in the response
|
||||
(str "{\"keyUid\": \"" (:key-uid seed-key-uid-pair) "\"}"))
|
||||
|
||||
(deftest validate-seed-against-key-uid
|
||||
(testing "Success event is triggered if correct seed is entered for selected multiaccount (key-uid)"
|
||||
(models/validate-seed-against-key-uid
|
||||
{:import-mnemonic-fn mock-import-mnemonic-fn
|
||||
:on-success #(is true) ; this callback should be called
|
||||
:on-error #(is false)}
|
||||
{:seed-phrase (:seed-phrase seed-key-uid-pair)
|
||||
:key-uid (:key-uid seed-key-uid-pair)}))
|
||||
|
||||
(testing "Error event is triggered if incorrect seed is entered for selected multiaccount"
|
||||
(models/validate-seed-against-key-uid
|
||||
{:import-mnemonic-fn mock-import-mnemonic-fn
|
||||
:on-success #(is false)
|
||||
:on-error #(is true)}
|
||||
{:seed-phrase (:seed-phrase seed-key-uid-pair)
|
||||
:key-uid "0xInvalid-Will-make-the-function-fail"})))
|
||||
|
||||
(deftest handle-multiaccount-import
|
||||
(testing "Sets correct state for Keycard onboarding after multiaccounts seeds are derived"
|
||||
(let [res (models/handle-multiaccount-import {:db {}} :passed-root-data :passed-derived-data)]
|
||||
(is (= :passed-root-data (get-in res [:db :intro-wizard :root-key])))
|
||||
(is (= :passed-derived-data (get-in res [:db :intro-wizard :derived])))
|
||||
(is (= :advanced (get-in res [:db :intro-wizard :selected-storage-type]))) ; :advanced storage type
|
||||
; means Keycard
|
||||
(is (= :recovery (get-in res [:db :keycard :flow])))
|
||||
(is (get-in res [:db :keycard :from-key-storage-and-migration?])))))
|
||||
|
||||
(comment
|
||||
(security/safe-unmask-data (security/mask-data nil)))
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.keycard.common :as keycard.common]
|
||||
[status-im.mobile-sync-settings.core :as mobile-network]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
@@ -36,7 +37,7 @@
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.prices :as prices]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[status-im2.contexts.shell.activity-center.events :as activity-center]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[status-im2.contexts.contacts.events :as contacts]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
@@ -45,8 +46,7 @@
|
||||
[status-im2.common.log :as logging]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.contexts.shell.jump-to.utils :as shell.utils]
|
||||
[utils.security.core :as security]
|
||||
[status-im.keycard.common :as keycard.common]))
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::initialize-transactions-management-enabled
|
||||
@@ -146,7 +146,7 @@
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db
|
||||
:profile/wallet-accounts
|
||||
:multiaccount/accounts
|
||||
(rpc->accounts accounts))
|
||||
;; NOTE: Local notifications should be enabled only after wallet was started
|
||||
::enable-local-notifications nil}
|
||||
@@ -179,7 +179,7 @@
|
||||
(rf/defn login-local-paired-user
|
||||
{:events [:multiaccounts.login/local-paired-user]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid name password]} (get-in db [:syncing :profile/profile])]
|
||||
(let [{:keys [key-uid name password]} (get-in db [:syncing :multiaccount])]
|
||||
{::login [key-uid
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid})
|
||||
@@ -188,9 +188,9 @@
|
||||
(rf/defn login
|
||||
{:events [:multiaccounts.login.ui/password-input-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name]} (:profile/login db)]
|
||||
(let [{:keys [key-uid password name]} (:multiaccounts/login db)]
|
||||
{:db (-> db
|
||||
(assoc-in [:profile/login :processing] true)
|
||||
(assoc-in [:multiaccounts/login :processing] true)
|
||||
(dissoc :intro-wizard :recovered-account?)
|
||||
(update :keycard dissoc :flow))
|
||||
::login [key-uid
|
||||
@@ -201,7 +201,7 @@
|
||||
(rf/defn export-db-submitted
|
||||
{:events [:multiaccounts.login.ui/export-db-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name]} (:profile/login db)]
|
||||
(let [{:keys [key-uid password name]} (:multiaccounts/login db)]
|
||||
{::export-db [key-uid
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid})
|
||||
@@ -216,7 +216,7 @@
|
||||
(rf/defn import-db-submitted
|
||||
{:events [:multiaccounts.login.ui/import-db-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name]} (:profile/login db)]
|
||||
(let [{:keys [key-uid password name]} (:multiaccounts/login db)]
|
||||
{::import-db [key-uid
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid})
|
||||
@@ -394,7 +394,7 @@
|
||||
[{:keys [db] :as cofx} node-config-json]
|
||||
(let [node-config (types/json->clj node-config-json)]
|
||||
{:db (assoc-in db
|
||||
[:profile/profile :wakuv2-config]
|
||||
[:multiaccount :wakuv2-config]
|
||||
(get node-config :WakuV2Config))}))
|
||||
|
||||
(rf/defn get-node-config
|
||||
@@ -438,10 +438,10 @@
|
||||
merged-networks (merge networks config/default-networks-by-id)]
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :profile/login)
|
||||
(dissoc :multiaccounts/login)
|
||||
(assoc :networks/current-network current-network
|
||||
:networks/networks merged-networks
|
||||
:profile/profile multiaccount))}
|
||||
:multiaccount multiaccount))}
|
||||
(data-store.chats/fetch-chats-rpc
|
||||
{:on-success
|
||||
#(do (re-frame/dispatch [:chats-list/load-success %])
|
||||
@@ -476,29 +476,29 @@
|
||||
(rf/defn check-last-chat
|
||||
{:events [::check-last-chat]}
|
||||
[{:keys [db]}]
|
||||
{::open-last-chat (get-in db [:profile/profile :key-uid])})
|
||||
{::open-last-chat (get-in db [:multiaccount :key-uid])})
|
||||
|
||||
(rf/defn update-wallet-accounts
|
||||
[{:keys [db]} accounts]
|
||||
(let [existing-accounts (into {} (map #(vector (:address %1) %1) (:profile/wallet-accounts db)))
|
||||
(let [existing-accounts (into {} (map #(vector (:address %1) %1) (:multiaccount/accounts db)))
|
||||
reduce-fn (fn [existing-accs new-acc]
|
||||
(let [address (:address new-acc)]
|
||||
(if (:removed new-acc)
|
||||
(dissoc existing-accs address)
|
||||
(assoc existing-accs address new-acc))))
|
||||
new-accounts (reduce reduce-fn existing-accounts (rpc->accounts accounts))]
|
||||
{:db (assoc db :profile/wallet-accounts (vals new-accounts))}))
|
||||
{:db (assoc db :multiaccount/accounts (vals new-accounts))}))
|
||||
|
||||
(rf/defn get-chats-callback
|
||||
{:events [::get-chats-callback]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:networks/keys [current-network networks]} db
|
||||
notifications-enabled? (get-in db [:profile/profile :notifications-enabled?])
|
||||
notifications-enabled? (get-in db [:multiaccount :notifications-enabled?])
|
||||
current-network-config (get networks current-network)
|
||||
network-id (str (get-in networks
|
||||
[current-network :config :NetworkId]))
|
||||
remote-push-notifications-enabled?
|
||||
(get-in db [:profile/profile :remote-push-notifications-enabled?])]
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
(rf/merge cofx
|
||||
(cond-> {::eip1559/check-eip1559-activation
|
||||
{:network-id network-id
|
||||
@@ -510,7 +510,7 @@
|
||||
(fn [accounts tokens custom-tokens favourites]
|
||||
(re-frame/dispatch [::initialize-wallet
|
||||
accounts tokens custom-tokens favourites]))]
|
||||
::open-last-chat (get-in db [:profile/profile :key-uid])}
|
||||
::open-last-chat (get-in db [:multiaccount :key-uid])}
|
||||
(or notifications-enabled? remote-push-notifications-enabled?)
|
||||
(assoc ::notifications/enable remote-push-notifications-enabled?))
|
||||
(transport/start-messenger)
|
||||
@@ -555,21 +555,23 @@
|
||||
|
||||
(rf/defn create-only-events
|
||||
[{:keys [db] :as cofx} recovered-account?]
|
||||
(let [{:profile/keys [profile profiles-overview wallet-accounts]}
|
||||
(let [{:keys [multiaccount
|
||||
:multiaccounts/multiaccounts
|
||||
:multiaccount/accounts]}
|
||||
db
|
||||
{:keys [creating?]} (:profile/login db)
|
||||
first-account? (and creating? (empty? profiles-overview))
|
||||
{:keys [creating?]} (:multiaccounts/login db)
|
||||
first-account? (and creating?
|
||||
(empty? multiaccounts))
|
||||
tos-accepted? (get db :tos/accepted?)
|
||||
{:networks/keys [current-network networks]} db
|
||||
network-id (str (get-in networks [current-network :config :NetworkId]))]
|
||||
(shell.utils/change-selected-stack-id :communities-stack true nil)
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :profile/login)
|
||||
(dissoc :multiaccounts/login)
|
||||
(assoc :tos/next-root :enable-notifications :chats/loading? false)
|
||||
(assoc-in [:profile/profile :multiaccounts/first-account]
|
||||
first-account?))
|
||||
::get-tokens [network-id wallet-accounts recovered-account?]}
|
||||
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
|
||||
::get-tokens [network-id accounts recovered-account?]}
|
||||
(finish-keycard-setup)
|
||||
(transport/start-messenger)
|
||||
(communities/fetch)
|
||||
@@ -577,7 +579,7 @@
|
||||
{:on-success #(re-frame/dispatch [:chats-list/load-success %])})
|
||||
(multiaccounts/switch-preview-privacy-mode-flag)
|
||||
(link-preview/request-link-preview-whitelist)
|
||||
(logging/set-log-level (:log-level profile))
|
||||
(logging/set-log-level (:log-level multiaccount))
|
||||
(navigation/init-root :enable-notifications))))
|
||||
|
||||
(defn- keycard-setup?
|
||||
@@ -593,7 +595,7 @@
|
||||
:on-card-read
|
||||
:card-read-in-progress?
|
||||
:pin
|
||||
:profile/profile)
|
||||
:multiaccount)
|
||||
(assoc :tos-accept-next-root
|
||||
(if login-only?
|
||||
:shell-stack
|
||||
@@ -604,9 +606,9 @@
|
||||
(rf/defn multiaccount-login-success
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [{:keys [key-uid password save-password? creating?]}
|
||||
(:profile/login db)
|
||||
(:multiaccounts/login db)
|
||||
|
||||
multiaccounts (:profile/profiles-overview db)
|
||||
multiaccounts (:multiaccounts/multiaccounts db)
|
||||
recovered-account? (get db :recovered-account?)
|
||||
login-only? (not (or creating?
|
||||
recovered-account?
|
||||
@@ -636,12 +638,29 @@
|
||||
(login-only-events key-uid password save-password?)
|
||||
(create-only-events recovered-account?)))))
|
||||
|
||||
;; FIXME(Ferossgp): We should not copy keys as we denormalize the database,
|
||||
;; this create desync between actual accounts and the one on login causing broken state
|
||||
;; UPDATE(cammellos): This code is copying over some fields explicitly as some values
|
||||
;; are alreayd in `multiaccounts/login` and should not be overriden, as they come from
|
||||
;; the keychain (save-password), this is not very explicit and we should probably
|
||||
;; make it clearer
|
||||
(rf/defn open-login
|
||||
[{:keys [db]} override-multiaccount]
|
||||
{:db (-> db
|
||||
(update :multiaccounts/login
|
||||
merge
|
||||
override-multiaccount)
|
||||
(update :multiaccounts/login
|
||||
dissoc
|
||||
:error
|
||||
:password))})
|
||||
|
||||
(rf/defn open-login-callback
|
||||
{:events [:multiaccounts.login.callback/get-user-password-success]}
|
||||
[{:keys [db] :as cofx} password]
|
||||
(let [key-uid (get-in db [:profile/login :key-uid])
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
keycard-account? (boolean (get-in db
|
||||
[:profile/profiles-overview
|
||||
[:multiaccounts/multiaccounts
|
||||
key-uid
|
||||
:keycard-pairing]))
|
||||
goto-key-storage? (:goto-key-storage? db)]
|
||||
@@ -649,7 +668,7 @@
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db
|
||||
[:profile/login]
|
||||
[:multiaccounts/login]
|
||||
assoc
|
||||
:password password
|
||||
:save-password? true)
|
||||
@@ -671,7 +690,7 @@
|
||||
(rf/defn get-credentials
|
||||
[{:keys [db] :as cofx} key-uid]
|
||||
(let [keycard-multiaccount? (boolean (get-in db
|
||||
[:profile/profiles-overview key-uid :keycard-pairing]))]
|
||||
[:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
(log/debug "[login] get-credentials"
|
||||
"keycard-multiacc?"
|
||||
keycard-multiaccount?)
|
||||
@@ -683,8 +702,12 @@
|
||||
"Auth method: nil - not supported, \"none\" - not selected, \"password\", \"biometric\", \"biometric-prepare\""
|
||||
{:events [:multiaccounts.login/get-auth-method-success]}
|
||||
[{:keys [db] :as cofx} auth-method]
|
||||
(let [key-uid (get-in db [:profile/login :key-uid])
|
||||
keycard-profile? (boolean (get-in db [:profile/profiles-overview key-uid :keycard-pairing]))]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
keycard-multiaccount? (boolean (get-in db
|
||||
[:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
(log/debug "[login] get-auth-method-success"
|
||||
"auth-method" auth-method
|
||||
"keycard-multiacc?" keycard-multiaccount?)
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db :auth-method auth-method)}
|
||||
@@ -693,14 +716,15 @@
|
||||
(biometric/biometric-auth %)
|
||||
(= auth-method keychain/auth-method-password)
|
||||
(get-credentials % key-uid)
|
||||
(and keycard-profile? (get-in db [:keycard :card-connected?]))
|
||||
(and keycard-multiaccount?
|
||||
(get-in db [:keycard :card-connected?]))
|
||||
(keycard.common/get-application-info % nil))
|
||||
(open-login-callback nil))))
|
||||
|
||||
(rf/defn biometric-auth-done
|
||||
{:events [:biometric-auth-done]}
|
||||
[{:keys [db] :as cofx} {:keys [bioauth-success bioauth-message bioauth-code]}]
|
||||
(let [key-uid (get-in db [:profile/login :key-uid])
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
auth-method (get db :auth-method)]
|
||||
(log/debug "[biometric] biometric-auth-done"
|
||||
"bioauth-success" bioauth-success
|
||||
@@ -710,7 +734,7 @@
|
||||
(get-credentials cofx key-uid)
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:profile/login :save-password?]
|
||||
[:multiaccounts/login :save-password?]
|
||||
(= auth-method keychain/auth-method-biometric))}
|
||||
(when-not (= auth-method keychain/auth-method-biometric)
|
||||
(keychain/save-auth-method key-uid keychain/auth-method-none))
|
||||
@@ -737,7 +761,7 @@
|
||||
(and (not save-password?)
|
||||
bioauth-supported?
|
||||
(= previous-auth-method keychain/auth-method-none)))
|
||||
(assoc-in [:profile/login :save-password?] save-password?))}
|
||||
(assoc-in [:multiaccounts/login :save-password?] save-password?))}
|
||||
(when bioauth-supported?
|
||||
(if save-password?
|
||||
(popover/show-popover {:view :secure-with-biometric})
|
||||
@@ -749,6 +773,21 @@
|
||||
[_]
|
||||
{:set-root :shell-stack})
|
||||
|
||||
(rf/defn multiaccount-selected
|
||||
{:events [:multiaccounts.login.ui/multiaccount-selected]}
|
||||
[{:keys [db] :as cofx} key-uid]
|
||||
;; We specifically pass a bunch of fields instead of the whole multiaccount
|
||||
;; as we want store some fields in multiaccount that are not here
|
||||
(let [multiaccount (get-in db [:multiaccounts/multiaccounts key-uid])
|
||||
keycard-multiaccount? (boolean (:keycard-pairing multiaccount))]
|
||||
(rf/merge
|
||||
cofx
|
||||
(merge
|
||||
{:db (update db :keycard dissoc :application-info)}
|
||||
(when keycard-multiaccount? {:navigate-to :keycard-login-pin}))
|
||||
(open-login (select-keys multiaccount
|
||||
[:key-uid :name :public-key :images :customization-color])))))
|
||||
|
||||
(rf/defn hide-keycard-banner
|
||||
{:events [:hide-keycard-banner]}
|
||||
[{:keys [db]}]
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
:supported-biometric-auth false}}
|
||||
{:keys [db]} (login/save-password initial-cofx true)]
|
||||
(test/is (= false (contains? db :popover/popover)))
|
||||
(test/is (= true (get-in db [:profile/login :save-password?])))
|
||||
(test/is (= true (get-in db [:multiaccounts/login :save-password?])))
|
||||
(test/testing "uncheck save password"
|
||||
(let [{:keys [db]} (login/save-password {:db db} false)]
|
||||
(test/is (= false (contains? db :popover/popover)))
|
||||
(test/is (= false (get-in db [:profile/login :save-password?])))))))
|
||||
(test/is (= false (get-in db [:multiaccounts/login :save-password?])))))))
|
||||
(test/testing "check save password, biometric available"
|
||||
(let [initial-cofx {:db {:auth-method keychain/auth-method-none
|
||||
:supported-biometric-auth true}}
|
||||
{:keys [db]} (login/save-password initial-cofx true)]
|
||||
(test/is (= true (get-in db [:profile/login :save-password?])))
|
||||
(test/is (= true (get-in db [:multiaccounts/login :save-password?])))
|
||||
(test/testing "enable biometric auth"
|
||||
(let [{:keys [db] :as res} (biometric/enable {:db db})]
|
||||
(test/is (contains? res :biometric-auth/authenticate))
|
||||
@@ -53,10 +53,10 @@
|
||||
:bioauth-message nil
|
||||
:bioauth-code nil}))
|
||||
false)]
|
||||
(test/is (= true (get-in db [:profile/login :save-password?])))
|
||||
(test/is (= true (get-in db [:multiaccounts/login :save-password?])))
|
||||
;; case 2 from https://github.com/status-im/status-mobile/issues/9573
|
||||
(test/is (= keychain/auth-method-biometric-prepare (:auth-method db)))
|
||||
(test/testing "disable biometric"
|
||||
(let [{:keys [db]} (biometric/disable {:db db})]
|
||||
(test/is (= false (get-in db [:profile/login :save-password?])))
|
||||
(test/is (= false (get-in db [:multiaccounts/login :save-password?])))
|
||||
(test/is (= keychain/auth-method-none (:auth-method db))))))))
|
||||
|
||||
@@ -10,28 +10,28 @@
|
||||
(deftest on-password-input-submitted
|
||||
(testing
|
||||
"handling :multiaccounts.login.ui/password-input-submitted event"
|
||||
(let [cofx {:db {:profile/login {:key-uid "key-uid"
|
||||
:password "password"
|
||||
:name "user"}}}
|
||||
(let [cofx {:db {:multiaccounts/login {:key-uid "key-uid"
|
||||
:password "password"
|
||||
:name "user"}}}
|
||||
efx (login.core/login cofx)]
|
||||
(testing "Change multiaccount."
|
||||
(is (= (::login.core/login efx)
|
||||
["key-uid" "{\"name\":\"user\",\"key-uid\":\"key-uid\"}"
|
||||
(ethereum/sha3 "password")])))
|
||||
(testing "start activity indicator"
|
||||
(is (= (get-in efx [:db :profile/login :processing]) true))))))
|
||||
(is (= (get-in efx [:db :multiaccounts/login :processing]) true))))))
|
||||
|
||||
(deftest login-success
|
||||
(testing ":accounts.login.callback/login-success event received."
|
||||
(let [db {:profile/login {:address "address"
|
||||
:password "password"}
|
||||
:profile/profile data/multiaccount}
|
||||
(let [db {:multiaccounts/login {:address "address"
|
||||
:password "password"}
|
||||
:multiaccount data/multiaccount}
|
||||
cofx {:db db}
|
||||
efx (login.core/multiaccount-login-success cofx)
|
||||
json-rpc (into #{} (map :method (:json-rpc/call efx)))]
|
||||
;; TODO: Account is now cleared only after all sign in fx are executed.
|
||||
;; (testing ":accounts/login cleared."
|
||||
;; (is (not (contains? new-db :profile/login))))
|
||||
;; (is (not (contains? new-db :multiaccounts/login))))
|
||||
(testing "Check the rest of effects."
|
||||
(is (json-rpc "web3_clientVersion"))))))
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"04f43da85ff1c333f3e7277b9ac4df92c9120fbb251f1dede7d41286e8c055acfeb845f6d2654821afca25da119daff9043530b296ee0e28e202ba92ec5842d617"
|
||||
db
|
||||
{:keycard
|
||||
{:profile/profile
|
||||
{:multiaccount
|
||||
{:encryption-public-key epk
|
||||
:whisper-private-key wpk
|
||||
:wallet-address "83278851e290d2488b6add2a257259f5741a3b7d"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
(rf/defn logout-method
|
||||
{:events [::logout-method]}
|
||||
[{:keys [db] :as cofx} {:keys [auth-method logout?]}]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])]
|
||||
(rf/merge cofx
|
||||
{:set-root :progress
|
||||
:chat.ui/clear-inputs nil
|
||||
@@ -21,9 +21,8 @@
|
||||
::logout nil
|
||||
::multiaccounts/webview-debug-changed false
|
||||
:keychain/clear-user-password key-uid
|
||||
:profile/get-profiles-overview #(re-frame/dispatch
|
||||
[:profile/get-profiles-overview-success
|
||||
%])}
|
||||
:setup/open-multiaccounts #(re-frame/dispatch [:setup/initialize-multiaccounts
|
||||
% {:logout? logout?}])}
|
||||
(keychain/save-auth-method key-uid auth-method)
|
||||
(wallet/clear-timeouts)
|
||||
(init/initialize-app-db))))
|
||||
@@ -57,7 +56,7 @@
|
||||
(logout-method {:auth-method keychain/auth-method-biometric-prepare
|
||||
:logout? false})
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:profile/login :save-password?] true)})))
|
||||
{:db (assoc-in db [:multiaccounts/login :save-password?] true)})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::logout
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
(ns status-im.multiaccounts.model)
|
||||
|
||||
(defn logged-in?
|
||||
[{:keys [profile/profile]}]
|
||||
(boolean profile))
|
||||
[{:keys [multiaccount]}]
|
||||
(boolean multiaccount))
|
||||
|
||||
(defn credentials
|
||||
[cofx]
|
||||
(select-keys (get-in cofx [:db :multiaccounts/login]) [:key-uid :password :save-password?]))
|
||||
|
||||
(defn current-public-key
|
||||
[cofx]
|
||||
(get-in cofx [:db :multiaccount :public-key]))
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
|
||||
(deftest logged-in-test
|
||||
(testing "multiaccount is defined"
|
||||
(is (multiaccounts.model/logged-in? {:profile/profile {}})))
|
||||
(is (multiaccounts.model/logged-in? {:multiaccount {}})))
|
||||
(testing "multiaccount is not there"
|
||||
(is (not (multiaccounts.model/logged-in? {})))))
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.mnemonic :as mnemonic]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.multiaccounts.create.core :as multiaccounts.create]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.popover.core :as popover]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.security.core :as security]))
|
||||
@@ -29,12 +31,13 @@
|
||||
{:events [:multiaccounts.recover/passphrase-input-changed]}
|
||||
[{:keys [db]} masked-recovery-phrase]
|
||||
(let [recovery-phrase (security/safe-unmask-data masked-recovery-phrase)]
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? (or (empty? recovery-phrase)
|
||||
(not (mnemonic/valid-length? recovery-phrase))))}))
|
||||
(rf/merge
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? (or (empty? recovery-phrase)
|
||||
(not (mnemonic/valid-length? recovery-phrase))))})))
|
||||
|
||||
(rf/defn validate-phrase-for-warnings
|
||||
[{:keys [db]}]
|
||||
@@ -55,7 +58,7 @@
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
|
||||
(let [{:keys [key-uid] :as multiaccount} (get-in db [:intro-wizard :root-key])
|
||||
keycard-multiaccount? (boolean (get-in db
|
||||
[:profile/profiles-overview key-uid
|
||||
[:multiaccounts/multiaccounts key-uid
|
||||
:keycard-pairing]))]
|
||||
(if keycard-multiaccount?
|
||||
;; trying to recover multiaccount created with keycard
|
||||
@@ -119,13 +122,13 @@
|
||||
:on-accept #(do
|
||||
(re-frame/dispatch [:pop-to-root :multiaccounts])
|
||||
(re-frame/dispatch
|
||||
[:profile/profile-selected key-uid]))
|
||||
[:multiaccounts.login.ui/multiaccount-selected key-uid]))
|
||||
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}})
|
||||
|
||||
(rf/defn on-import-multiaccount-success
|
||||
{:events [::import-multiaccount-success]}
|
||||
[{:keys [db] :as cofx} {:keys [key-uid] :as root-data} derived-data]
|
||||
(let [multiaccounts (:profile/profiles-overview db)]
|
||||
(let [multiaccounts (:multiaccounts/multiaccounts db)]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update db
|
||||
@@ -175,3 +178,106 @@
|
||||
{::multiaccounts/validate-mnemonic [passphrase
|
||||
#(re-frame/dispatch [:multiaccounts.recover/phrase-validated
|
||||
%])]}))
|
||||
|
||||
(rf/defn continue-to-import-mnemonic
|
||||
{:events [::continue-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [password passphrase]} (:multiaccounts/recover db)]
|
||||
(rf/merge cofx
|
||||
{::import-multiaccount {:passphrase passphrase
|
||||
:password password
|
||||
:success-event ::import-multiaccount-success}}
|
||||
(popover/hide-popover))))
|
||||
|
||||
(rf/defn dec-step
|
||||
{:events [:multiaccounts.recover/dec-step]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [step (get-in db [:intro-wizard :step])]
|
||||
(if (= step :enter-phrase)
|
||||
{:db (dissoc db :intro-wizard)}
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:step
|
||||
(case step
|
||||
:recovery-success :enter-phrase
|
||||
:select-key-storage :recovery-success
|
||||
:create-code :select-key-storage)
|
||||
:confirm-failure? false
|
||||
:key-code nil)})))
|
||||
|
||||
(rf/defn cancel-pressed
|
||||
{:events [:multiaccounts.recover/cancel-pressed]}
|
||||
[{:keys [db] :as cofx} skip-alert?]
|
||||
;; Workaround for multiple Cancel button clicks
|
||||
;; that can break navigation tree
|
||||
(let [step (get-in db [:intro-wizard :step])]
|
||||
(when-not (#{:multiaccounts :login} (:view-id db))
|
||||
(if (and (= step :select-key-storage) (not skip-alert?))
|
||||
(utils/show-question
|
||||
(i18n/label :t/are-you-sure-to-cancel)
|
||||
(i18n/label :t/you-will-start-from-scratch)
|
||||
#(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true]))
|
||||
(rf/merge cofx
|
||||
dec-step
|
||||
navigation/navigate-back)))))
|
||||
|
||||
(rf/defn select-storage-next-pressed
|
||||
{:events [:multiaccounts.recover/select-storage-next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [storage-type (get-in db [:intro-wizard :selected-storage-type])]
|
||||
(if (= storage-type :advanced)
|
||||
;;TODO: fix circular dependency to remove dispatch here
|
||||
{:dispatch [:recovery.ui/keycard-option-pressed]}
|
||||
(rf/merge cofx
|
||||
{:db (update db :intro-wizard assoc :step :create-code)}
|
||||
(navigation/navigate-to :create-password nil)))))
|
||||
|
||||
(rf/defn re-encrypt-pressed
|
||||
{:events [:multiaccounts.recover/re-encrypt-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (update db
|
||||
:intro-wizard
|
||||
assoc
|
||||
:step :select-key-storage
|
||||
:selected-storage-type :default)}
|
||||
(if (nfc/nfc-supported?)
|
||||
(navigation/navigate-to :select-key-storage nil)
|
||||
(select-storage-next-pressed))))
|
||||
|
||||
(rf/defn confirm-password-next-button-pressed
|
||||
{:events [:multiaccounts.recover/enter-password-next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[cofx key-code]
|
||||
(store-multiaccount cofx key-code))
|
||||
|
||||
(rf/defn count-words
|
||||
[{:keys [db]}]
|
||||
(let [passphrase (get-in db [:intro-wizard :passphrase])]
|
||||
{:db (assoc-in db
|
||||
[:intro-wizard :passphrase-word-count]
|
||||
(mnemonic/words-count passphrase))}))
|
||||
|
||||
(rf/defn run-validation
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [passphrase (get-in db [:intro-wizard :passphrase])]
|
||||
(when (= (last passphrase) " ")
|
||||
(rf/merge cofx
|
||||
(validate-phrase-for-warnings)))))
|
||||
|
||||
(rf/defn enter-phrase-input-changed
|
||||
{:events [:multiaccounts.recover/enter-phrase-input-changed]}
|
||||
[cofx input]
|
||||
(rf/merge cofx
|
||||
(set-phrase input)
|
||||
(count-words)
|
||||
(run-validation)))
|
||||
|
||||
(rf/defn enter-passphrase-input-changed
|
||||
{:events [:multiaccounts.recover/enter-passphrase-input-changed]}
|
||||
[{:keys [db]} masked-passphrase]
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:password masked-passphrase
|
||||
:password-error nil)})
|
||||
|
||||
@@ -73,13 +73,13 @@
|
||||
(deftest on-import-multiaccount-success
|
||||
(testing "importing a new multiaccount"
|
||||
(let [res (models/on-import-multiaccount-success
|
||||
{:db {:profile/profiles-overview {:acc1 {}}}}
|
||||
{:db {:multiaccounts/multiaccounts {:acc1 {}}}}
|
||||
{:key-uid :acc2}
|
||||
nil)]
|
||||
(is (nil? (:utils/show-confirmation res)))))
|
||||
(testing "importing an existing multiaccount"
|
||||
(let [res (models/on-import-multiaccount-success
|
||||
{:db {:profile/profiles-overview {:acc1 {}}}}
|
||||
{:db {:multiaccounts/multiaccounts {:acc1 {}}}}
|
||||
{:key-uid :acc1}
|
||||
nil)]
|
||||
(is (contains? res :utils/show-confirmation)))))
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
(rf/defn password-reset-success
|
||||
{:events [::password-reset-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [key-uid]} (:profile/profile db)
|
||||
(let [{:keys [key-uid]} (:multiaccount db)
|
||||
auth-method (get db :auth-method keychain/auth-method-none)
|
||||
new-password (get-in db [:multiaccount/reset-password-form-vals :new-password])]
|
||||
(rf/merge cofx
|
||||
@@ -68,7 +68,7 @@
|
||||
(rf/defn handle-verification-success
|
||||
{:events [::handle-verification-success]}
|
||||
[{:keys [db] :as cofx} form-vals]
|
||||
(let [{:keys [key-uid name]} (:profile/profile db)]
|
||||
(let [{:keys [key-uid name]} (:multiaccount db)]
|
||||
(rf/merge cofx
|
||||
{::change-db-password [key-uid form-vals]
|
||||
:db (assoc db
|
||||
@@ -98,4 +98,4 @@
|
||||
{::validate-current-password-and-reset
|
||||
(assoc form-vals
|
||||
:address
|
||||
(get-in db [:profile/profile :wallet-root-address]))})
|
||||
(get-in db [:multiaccount :wallet-root-address]))})
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
(rf/defn send-contact-update
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [name preferred-name display-name address]} (:profile/profile db)]
|
||||
(let [{:keys [name preferred-name display-name address]} (:multiaccount db)]
|
||||
{:json-rpc/call [{:method "wakuext_sendContactUpdates"
|
||||
:params [(or preferred-name display-name name) ""]
|
||||
:on-success #(log/debug "sent contact update")}]}))
|
||||
@@ -16,7 +16,7 @@
|
||||
{:events [:multiaccounts.ui/update-name]}
|
||||
[{:keys [db] :as cofx} raw-multiaccounts-from-status-go]
|
||||
(let [{:keys [key-uid name preferred-name
|
||||
display-name]} (:profile/profile db)
|
||||
display-name]} (:multiaccount db)
|
||||
account (some #(and (= (:key-uid %) key-uid) %) raw-multiaccounts-from-status-go)]
|
||||
(when-let [new-name (and account (or preferred-name display-name name))]
|
||||
(rf/merge cofx
|
||||
@@ -30,7 +30,7 @@
|
||||
[{:keys [db] :as cofx}
|
||||
setting setting-value
|
||||
{:keys [dont-sync? on-success] :or {on-success #()}}]
|
||||
(let [current-multiaccount (:profile/profile db)]
|
||||
(let [current-multiaccount (:multiaccount db)]
|
||||
(if (empty? current-multiaccount)
|
||||
;; NOTE: this should never happen, but if it does this is a critical error
|
||||
;; and it is better to crash than risk having an unstable state
|
||||
@@ -40,15 +40,15 @@
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (if setting-value
|
||||
(assoc-in db [:profile/profile setting] setting-value)
|
||||
(update db :profile/profile dissoc setting))
|
||||
(assoc-in db [:multiaccount setting] setting-value)
|
||||
(update db :multiaccount dissoc setting))
|
||||
:json-rpc/call
|
||||
[{:method "settings_saveSetting"
|
||||
:params [setting setting-value]
|
||||
:on-success on-success}]}
|
||||
|
||||
(when (#{:name :preferred-name} setting)
|
||||
(constantly {:profile/get-profiles-overview #(rf/dispatch [:multiaccounts.ui/update-name %])}))
|
||||
(constantly {:setup/open-multiaccounts #(rf/dispatch [:multiaccounts.ui/update-name %])}))
|
||||
|
||||
(when (and (not dont-sync?) (#{:name :preferred-name} setting))
|
||||
(send-contact-update))))))
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
(rf/defn optimistic
|
||||
[{:keys [db] :as cofx} setting setting-value]
|
||||
(let [current-multiaccount (:profile/profile db)
|
||||
(let [current-multiaccount (:multiaccount db)
|
||||
setting-value (if (= :currency setting)
|
||||
(keyword setting-value)
|
||||
setting-value)
|
||||
@@ -97,8 +97,8 @@
|
||||
(assoc db :stickers/recent-stickers recent-stickers-from-remote))
|
||||
db)]
|
||||
{:db (if setting-value
|
||||
(assoc-in db [:profile/profile setting] setting-value)
|
||||
(update db :profile/profile dissoc setting))}))
|
||||
(assoc-in db [:multiaccount setting] setting-value)
|
||||
(update db :multiaccount dissoc setting))}))
|
||||
|
||||
(rf/defn set-many-js
|
||||
[cofx settings-js]
|
||||
@@ -119,7 +119,7 @@
|
||||
{:events [::toggle-opensea-nfts-visiblity]}
|
||||
[cofx visible?]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in (:db cofx) [:profile/profile :opensea-enabled?] visible?)
|
||||
{:db (assoc-in (:db cofx) [:multiaccount :opensea-enabled?] visible?)
|
||||
;; need to add fully qualified namespace to counter circular deps
|
||||
:dispatch [:status-im.wallet.core/fetch-collectibles-collection]}
|
||||
(multiaccount-update :opensea-enabled? visible? {})))
|
||||
|
||||
@@ -6,27 +6,27 @@
|
||||
;;TODO this test case actually shows that we are doing a needless rpc call when
|
||||
;;there is no changes, but it is an edge case that shouldn't really happen
|
||||
(let [efx (multiaccounts.update/multiaccount-update
|
||||
{:db {:profile/profile {:not-empty "would throw an error if was empty"}}}
|
||||
{:db {:multiaccount {:not-empty "would throw an error if was empty"}}}
|
||||
nil
|
||||
nil
|
||||
{})
|
||||
json-rpc (into #{} (map :method (:json-rpc/call efx)))]
|
||||
(is (json-rpc "settings_saveSetting"))
|
||||
(is (= (get-in efx [:db :profile/profile]) {:not-empty "would throw an error if was empty"}))))
|
||||
(is (= (get-in efx [:db :multiaccount]) {:not-empty "would throw an error if was empty"}))))
|
||||
|
||||
(deftest test-clean-seed-phrase
|
||||
(let [efx (multiaccounts.update/clean-seed-phrase
|
||||
{:db {:profile/profile {:mnemonic "lalalala"}}}
|
||||
{:db {:multiaccount {:mnemonic "lalalala"}}}
|
||||
{})
|
||||
json-rpc (into #{} (map :method (:json-rpc/call efx)))]
|
||||
(is (json-rpc "settings_saveSetting"))
|
||||
(is (nil? (get-in efx [:db :profile/profile :mnemonic])))))
|
||||
(is (nil? (get-in efx [:db :multiaccount :mnemonic])))))
|
||||
|
||||
(deftest test-update-multiaccount-account-name
|
||||
(let [cofx {:db {:profile/profile {:key-uid 1
|
||||
:name "name"
|
||||
:preferred-name "preferred-name"
|
||||
:display-name "display-name"}}}
|
||||
(let [cofx {:db {:multiaccount {:key-uid 1
|
||||
:name "name"
|
||||
:preferred-name "preferred-name"
|
||||
:display-name "display-name"}}}
|
||||
raw-multiaccounts-from-status-go [{:key-uid 1 :name "old-name"}]]
|
||||
(testing "wrong account"
|
||||
(is (nil? (multiaccounts.update/update-multiaccount-account-name cofx []))))
|
||||
@@ -46,11 +46,11 @@
|
||||
"preferred-name"))
|
||||
(is (new-account-name=
|
||||
(multiaccounts.update/update-multiaccount-account-name
|
||||
(update-in cofx [:db :profile/profile] dissoc :preferred-name)
|
||||
(update-in cofx [:db :multiaccount] dissoc :preferred-name)
|
||||
raw-multiaccounts-from-status-go)
|
||||
"display-name"))
|
||||
(is (new-account-name=
|
||||
(multiaccounts.update/update-multiaccount-account-name
|
||||
(update-in cofx [:db :profile/profile] dissoc :preferred-name :display-name)
|
||||
(update-in cofx [:db :multiaccount] dissoc :preferred-name :display-name)
|
||||
raw-multiaccounts-from-status-go)
|
||||
"name"))))))
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
:db {:networks/manage {:url {:value "wrong"}
|
||||
:chain {:value "1"}
|
||||
:name {:value "empty"}}
|
||||
:profile/profile {}}})))))
|
||||
:multiaccount {}}})))))
|
||||
|
||||
(deftest save-valid-network
|
||||
(testing "save a valid network"
|
||||
@@ -133,7 +133,7 @@
|
||||
:chain {:value :mainnet}
|
||||
:symbol {:value "symbol"}
|
||||
:name {:value "valid"}}
|
||||
:profile/profile {}
|
||||
:multiaccount {}
|
||||
:networks/networks {"random2"
|
||||
{:id "random2"
|
||||
:name "network-name"
|
||||
@@ -156,7 +156,7 @@
|
||||
:chain {:value :custom}
|
||||
:name {:value "valid"}
|
||||
:network-id {:value 1}}
|
||||
:profile/profile {}
|
||||
:multiaccount {}
|
||||
:networks/networks {"random"
|
||||
{:id "random"
|
||||
:name "network-name"
|
||||
@@ -176,7 +176,7 @@
|
||||
:name {:value "valid"}
|
||||
:symbol {:value "symbol"}
|
||||
:network-id {:value 5}}
|
||||
:profile/profile {}
|
||||
:multiaccount {}
|
||||
:networks/networks {"randomid"
|
||||
{:id "randomid"
|
||||
:name "network-name"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
{:db (assoc db :network-status (if is-connected? :online :offline))}
|
||||
(when (and is-connected?
|
||||
(or (not= (count (get-in db [:wallet :accounts]))
|
||||
(count (get db :profile/wallet-accounts)))
|
||||
(count (get db :multiaccount/accounts)))
|
||||
(wallet/has-empty-balances? db)))
|
||||
(wallet/update-balances nil nil))))
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
(defn current-fleet-key
|
||||
[db]
|
||||
(keyword (get-in db
|
||||
[:profile/profile :fleet]
|
||||
[:multiaccount :fleet]
|
||||
config/fleet)))
|
||||
|
||||
(defn get-current-fleet
|
||||
@@ -116,9 +116,9 @@
|
||||
(some #(string/includes? (str %) "waku") ks)))
|
||||
|
||||
(defn get-multiaccount-node-config
|
||||
[{:keys [profile/profile :networks/networks :networks/current-network]
|
||||
[{:keys [multiaccount :networks/networks :networks/current-network]
|
||||
:as db}]
|
||||
(let [wakuv2-config (get profile :wakuv2-config {})
|
||||
(let [wakuv2-config (get multiaccount :wakuv2-config {})
|
||||
current-fleet-key (current-fleet-key db)
|
||||
current-fleet (get-current-fleet db)
|
||||
wakuv2-enabled (wakuv2-enabled? current-fleet)
|
||||
@@ -127,7 +127,7 @@
|
||||
{:keys [installation-id log-level
|
||||
waku-bloom-filter-mode
|
||||
custom-bootnodes custom-bootnodes-enabled?]}
|
||||
profile
|
||||
multiaccount
|
||||
use-custom-bootnodes (get custom-bootnodes-enabled? current-network)]
|
||||
(cond-> (get-in networks [current-network :config])
|
||||
:always
|
||||
@@ -212,7 +212,7 @@ app-db"
|
||||
(rf/defn prepare-new-config
|
||||
"Use this function to apply settings to the current account node config"
|
||||
[{:keys [db]} {:keys [on-success]}]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])]
|
||||
{::prepare-new-config [key-uid
|
||||
(get-new-config db)
|
||||
#(re-frame/dispatch
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
(= view-id :chat)))
|
||||
|
||||
(defn show-message-pn?
|
||||
[{{:keys [app-state profile/profile]} :db :as cofx}
|
||||
[{{:keys [app-state multiaccount]} :db :as cofx}
|
||||
notification]
|
||||
(let [chat-id (get-in notification [:body :chat :id])
|
||||
notification-author (get-in notification [:notificationAuthor :id])]
|
||||
(and
|
||||
(not= notification-author (:public-key profile))
|
||||
(not= notification-author (:public-key multiaccount))
|
||||
(or (= app-state "background")
|
||||
(not (foreground-chat? cofx chat-id))))))
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"Set the name of the device"
|
||||
{:events [:pairing.ui/set-name-pressed]}
|
||||
[{:keys [db]} installation-name]
|
||||
(let [our-installation-id (get-in db [:profile/profile :installation-id])]
|
||||
(let [our-installation-id (get-in db [:multiaccount :installation-id])]
|
||||
{:pairing/set-installation-metadata [our-installation-id
|
||||
{:name installation-name
|
||||
:deviceType utils.platform/os}]}))
|
||||
@@ -195,7 +195,7 @@
|
||||
(rf/defn send-installation-messages
|
||||
{:events [:pairing.ui/synchronize-installation-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [multiaccount (:profile/profile db)
|
||||
(let [multiaccount (:multiaccount db)
|
||||
{:keys [name preferred-name]} multiaccount]
|
||||
{:json-rpc/call [{:method "wakuext_syncDevices"
|
||||
:params [(or preferred-name name)]
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
(rf/defn enter-two-random-words
|
||||
{:events [:my-profile/enter-two-random-words]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [mnemonic]} (:profile/profile db)
|
||||
(let [{:keys [mnemonic]} (:multiaccount db)
|
||||
shuffled-mnemonic (shuffle (map-indexed vector (string/split mnemonic #" ")))]
|
||||
{:db (assoc db
|
||||
:my-profile/seed
|
||||
@@ -88,7 +88,7 @@
|
||||
(rf/defn show-profile
|
||||
{:events [:chat.ui/show-profile]}
|
||||
[{:keys [db]} identity ens-name]
|
||||
(let [my-public-key (get-in db [:profile/profile :public-key])]
|
||||
(let [my-public-key (get-in db [:multiaccount :public-key])]
|
||||
(if (not= my-public-key identity)
|
||||
{:db (-> db
|
||||
(assoc :contacts/identity identity)
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(defn own-public-key?
|
||||
[{:keys [profile/profile]} public-key]
|
||||
(= (:public-key profile) public-key))
|
||||
[{:keys [multiaccount]} public-key]
|
||||
(= (:public-key multiaccount) public-key))
|
||||
|
||||
(rf/defn handle-private-chat
|
||||
[{:keys [db] :as cofx} {:keys [chat-id]}]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user