Compare commits

..
Author SHA1 Message Date
Omar Basem b14ae6318d fix 2023-07-07 17:38:26 +04:00
Omar Basem 541e67ec69 fix 2023-07-07 17:30:33 +04:00
Omar Basem 9e865c6a59 fix 2023-07-05 14:06:26 +04:00
Tetiana Churikova c52bf965f7 e2e: more groups (#16483) 2023-07-05 11:55:40 +02:00
Ulises Manuel Cárdenas e260187cf5 [#16073] Password info box
* Refactor: Remove use of f-component

* Fix documentation drawer styles

* Refactor: move title styles to style ns

* Fix StaticSafeAreaInsets not being defined on component tests

* Fix bottom sheet height on Android
2023-07-04 17:08:47 -06:00
Ulises Manuel Cárdenas ca0915c940 #16111 - Toast animation & dismiss gesture
* Enable toast animations and refactor

* Add gesture-handler-root-HOC to detect toast's gestures on Android

* Add comment about flex 0 style
2023-07-04 16:25:08 -06:00
Ulises Manuel Cárdenas 2b4b357c32 [#16378] Fix channel unread counter space
* Makes `divider-label` styles more lenient

* Small refactor to `list-items.channel` component

* Fix styles for `channel-list-component`
  - Refactor `channel-list-component`
  - Add some missing `:style` keys in `status-im2.contexts.communities.overview.view`
  - Fix a warning related to using a `deref` in a `lazy-seq`

* Changes icon keyword namespace from `:main-icons` to `:i`
2023-07-04 16:11:56 -06:00
Icaro Motta 19ca8e28a5 Lint and fix missing trailing newlines (#16445)
Apply the Clojure Style Guide recommendation to end files with proper lines
(having a trailing newline character). See
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206
2023-07-04 19:40:13 +00:00
Yevheniia Berdnyk 8978e92042 e2e: nightly fixes 2023-07-04 20:26:05 +03:00
Brian Sztamfater c2c79cc1ac feat: implement onboarding modal transition for sign in screen (#16167) 2023-07-04 12:43:08 -03:00
Parvesh Monu affd2a5e76 Implement static loading skeleton (#16474) 2023-07-04 16:55:22 +05:30
Yevheniia Berdnyk ef99bf2ad6 e2e: tests for reactions in community and group chats 2023-07-04 13:17:48 +03:00
Jamie Caprani 1f6f907d57 feat: add markdown list component to quo2 (#16411) 2023-07-03 13:08:19 -07:00
Jamie Caprani 97b254c514 chore: update use of theme in page-nav component (#16424) 2023-07-03 08:37:31 -07:00
Yevheniia Berdnyk ca2ed9d37e e2e: fixes for backup users and unread indicator tests 2023-07-03 15:55:05 +03:00
Jamie Caprani e64ff76e0b update theming for profile-input, empty state and predictive keyboard components (#16423)
* chore: remove override-prop from empty-state component

* chore: remove override-prop from profile-input and title-input components

* chore: remove override-prop from predictive-keyboard component
2023-07-03 04:26:33 -07:00
Mohamed Javid 88884064b1 Update Bottom sheet screen to use theme context (#16429)
This commit updates the `bottom-sheet-screen` component (which used `override-theme` from `screen-params` subs) to use the theme from the context provider.

The bottom sheet screen will pick the theme specified in the screen options (to override) as expected. If it's not specified, then it will fall back to the user's theme.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-07-03 13:00:41 +05:30
Anton Iakimov a6e6716311 ci: add shebang to jenkinsfiles 2023-07-02 09:11:54 +02:00
Anton Iakimov 07d037f2e1 nix: downgrade watchman to 4.9.0
watchman was upgraded significantly during the last #14944 (4.9.0 (Aug 16, 2017) to 2023.01.30.00 - 6 years between):
status-im/nixpkgs@4e9c02b

Probably causing developers to have "too many files open" issue #16341

This PR is an attempt to fix the issue by downgrading the watchman

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-07-02 08:46:28 +02:00
Andrea Maria Piana 36a72f2d63 Set nameserver on login 2023-07-01 08:39:12 +01:00
Jamie Caprani 4c0a8d9f6d chore: use with theme for step component (#16399) 2023-06-30 09:02:46 -07:00
Brian Sztamfater 2d860c363a feat: allow navigation inside different stacks (#16419)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-06-30 11:48:35 -03:00
Icaro Motta 186ac482ee Comment time bomb test out (#16452) 2023-06-30 12:47:24 +00:00
Andrea Maria Piana f015eb929a [Fixes: #16203] Fix delete for me replies images
https://github.com/status-im/status-go/compare/09c5223d...b058ab41
2023-06-30 11:14:49 +01:00
Volodymyr Kozieiev bca7ab7925 Use only counter (no unread indicator) for chats bottom bar tab (#16417) 2023-06-29 16:42:08 +01:00
Yevheniia Berdnyk 5f441dfa93 e2e: Reactions in 1-1 chats 2023-06-29 17:49:15 +03:00
Parvesh Monu 5d0aa6a2f7 fix App crashes when jump-to has group chat card (#16431) 2023-06-29 18:10:58 +05:30
flexsurfer d9f7510d13 key-storage cleanup (#16427) 2023-06-29 14:29:39 +02:00
Roman Volosovskyi b953ddb5af [#15944] Set installation name on account creation 2023-06-29 14:06:23 +02:00
Tetiana Churikova 3058ebe018 e2e: small adjustments (#16439) 2023-06-29 14:05:13 +02:00
frank a7ddda40c4 fix: ROW_NUMBER() not work on ios for some reason (#16426)
* fix: ROW_NUMBER() not work on ios for some reason

* update status-go-version.json

* update status-go-version.json

* update status-go-version.json
2023-06-29 19:11:15 +08:00
Tetiana Churikova ba8c08650b e2e: updated wait_to (#16416) 2023-06-28 14:27:57 +02:00
flexsurfer c5a7bf39d7 multiaccounts refactoring part1 (#16414) 2023-06-28 13:48:34 +02:00
Ibrahem Khalil e0a0c6331f [16352] [Bugfix] New message indicator not showing on bottom navigation for unmuted chats and another bug (#16380) 2023-06-27 19:44:28 +04:00
Parvesh Monu b5a96a254a Implement Swipe navigation for floating screen (#16390) 2023-06-27 21:02:54 +05:30
Rahul Pratap 6b0a51720e Update animation for onboarding carousel. (#16294)
* Update animation for onboarding carousel.

* Fixed issues with long press while swipe.

* Fixed issues after generating keys.
2023-06-27 20:45:13 +05:30
Jamie Caprani e0e693791f chore: small refactor to remove some uses of status-im in status-im2 (#16358) 2023-06-27 07:11:07 -07:00
watson cebc50d409 Adjust identifiers page to do highlighting (#15752) 2023-06-27 14:45:10 +01:00
jakub 1503f6b250 nix: use Darwin stat command explicitly
Otherwise if in Nix context we can accidentally use GNU stat which
results in a different output due to different command line flags:
```
[nix-shell:~/status-mobile]$ stat -Lf "%Sg" "/nix/store"
stat: cannot read file system information for '%Sg': No such file or directory
  File: "/nix/store"
    ID: 10000110000001a Namelen: ?       Type: apfs
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 242837545  Free: 199242283  Available: 199242283
Inodes: Total: 7971454780 Free: 7969691320
```
And it should be just owner group name or ID. Which in turn results in:
```
Unknown Nix installtion type!
```

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-06-27 13:25:41 +02:00
Jamie Caprani 46182ad308 chore: move activity centre and share into shell namespace (#16395) 2023-06-27 03:48:23 -07:00
Jamie Caprani fa698dbc30 feat: add parallax to biometrics page for whitelisted devices (#16296) 2023-06-27 02:50:27 -07:00
Ibrahem Khalil 79151ee85d Disable image description in lightbox (#16405) 2023-06-27 12:15:04 +03:00
Ibrahem Khalil 4c8671caa0 [15902] BUGFIX - Resolve public keys into the user's name in the confirmation drawer and image description (#16176) 2023-06-27 10:42:01 +03:00
Omar Basem 86219dbad8 feat: save image (#16268)
* feat: save image
2023-06-27 11:03:29 +04:00
Yevheniia Berdnyk cd32806c96 e2e: Updated error message in 702783 2023-06-27 02:52:28 +03:00
frank ab16ca34dd improve: enable collect logs before login (#16392) 2023-06-27 07:42:53 +08:00
Ulises Manuel Cárdenas e2b7a299b4 [#16322] Add carousel tap gesture
* Add tap gesture to carousel

* Updates uses of carousel

* Gestures only detected on carousel content instead of full screen on Android
2023-06-26 14:19:09 -06:00
Anton Iakimov 5dcd64c478 nix: fix Android SDK on Darwin with nixpkgs system override
Android SDK in nixpkg doesn't support `aarch64-darwin`, for details see
https://github.com/status-im/status-mobile/issues/12794

The workaround was to run terminal application with Rosetta or make with `aarch` tool.

This PR overrides system architecture to always be `x86_64` for Android shell and build targets ran by make.
CI is not affected as it runs `nix` directly.

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-06-26 17:33:44 +02:00
Brian Sztamfater 6d6e6b1eff fix: calibrate duration of recorded audio (#15543)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-06-26 11:02:13 -03:00
Brian Sztamfater 60a8b944d9 fix: send user to settings if audio permission is rejected (#16049) 2023-06-26 10:35:13 -03:00
Brian Sztamfater 437cfa9a77 feat: add blur effect on scroll for buttons inside gallery view (#16319)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-06-26 10:19:54 -03:00
Andrea Maria Piana 36aefd0e5a Fix race condition on sending messages
https://github.com/status-im/status-go/compare/d3e650d5...f23cb406
2023-06-26 13:37:20 +01:00
Mohamed Javid ce82e87cd0 Update broken Status development link in ide-setup.md (#16391)
This commit updates the broken link of `Status development` in the `Start and connect the REPL` section of `ide-setup.md`.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-06-26 16:43:58 +05:30
Parvesh Monu 8f21cecf81 fix deleted message remains in preview at Jump to section (#16385) 2023-06-26 16:19:32 +05:30
Parvesh Monu 4a4974b541 Animate floating screen border radius (#16384) 2023-06-26 15:59:43 +05:30
Anton Iakimov 43ef6db7b9 js: remove unused visual tests and detox package #16372
After the nixpkgs upgrade we started to have Xcode command line tools installation popup on each make test, dtrace-provider was failing meanwhile: #16356

It appeared, that it was failing before the upgrade with different issue: #16356

dtrace-provider is a dependency for detox, which was added for visiual tests in #14329
These tests don't run.

This build issues didn't cause any problems, because it was not obligatary.
See NODE_DTRACE_PROVIDER_REQUIRE option, which can enforce this requirement.

See #16356 for more details.

In this PR we disable detox dependency for now.
And also Visual Tests.
2023-06-26 11:59:15 +02:00
Mohamed Javid 6f0d375e8a Refactor "How to pair" screen and add "Find sync code" screen (#16364)
This commit refactors the "How to pair" bottom screen (introduced in #15710) on Syncing page, to be reused in "Sign In" and "Sync new device" screens by moving the UI rendering functions to the common place.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-06-26 15:27:59 +05:30
386 changed files with 4804 additions and 3764 deletions
-37
View File
@@ -1,37 +0,0 @@
module.exports = {
testRunner: 'jest',
testRegex: '\\.visual\\.js$',
'runner-config': 'visual-test/config.json',
devices: {
simulator: {
type: 'ios.simulator',
device: {
type: 'iPhone 11 Pro',
},
},
},
apps: {
'ios.release': {
name: 'StatusIm',
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/StatusIm.app',
build: 'make release-ios',
},
'ios.debug': {
name: 'StatusIm',
type: 'ios.app',
binaryPath: process.env.TEST_BINARY_PATH,
build: "make run-ios SIMULATOR='iPhone 11 Pro'",
},
},
configurations: {
'ios.sim.release': {
device: 'simulator',
app: 'ios.release',
},
'ios.sim.debug': {
device: 'simulator',
app: 'ios.debug',
},
},
};
+1 -1
View File
@@ -43,4 +43,4 @@ As a <user|developer|...>, I want to <task> so that <goal>.
[comment]: # (if on Android please replicate bug whilst running adb logcat)
```
...
```
```
+13 -20
View File
@@ -14,17 +14,17 @@ WHITE := $(shell tput -Txterm setaf 7)
YELLOW := $(shell tput -Txterm setaf 3)
RESET := $(shell tput -Txterm sgr0)
HELP_FUN = \
%help; \
while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
print "Usage: make [target]\n\nSee STARTING_GUIDE.md for more info.\n\n"; \
for (sort keys %help) { \
print "${WHITE}$$_:${RESET}\n"; \
for (@{$$help{$$_}}) { \
$$sep = " " x (32 - length $$_->[0]); \
print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \
}; \
print "\n"; \
}
%help; \
while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
print "Usage: make [target]\n\nSee STARTING_GUIDE.md for more info.\n\n"; \
for (sort keys %help) { \
print "${WHITE}$$_:${RESET}\n"; \
for (@{$$help{$$_}}) { \
$$sep = " " x (32 - length $$_->[0]); \
print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \
}; \
print "\n"; \
}
HOST_OS := $(shell uname | tr '[:upper:]' '[:lower:]')
# This can come from Jenkins
@@ -307,6 +307,7 @@ lint: ##@test Run code style checks
clj-kondo --config .clj-kondo/config.edn --cache false --lint src && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint-trailing-newline.sh && \
yarn prettier
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
@@ -315,9 +316,9 @@ lint-fix: ##@test Run code style checks and fix issues
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
sh scripts/lint-trailing-newline.sh --fix && \
yarn prettier
shadow-server: export TARGET := clojure
shadow-server:##@ Start shadow-cljs in server mode for watching
yarn shadow-cljs server
@@ -343,14 +344,6 @@ test: ##@test Run tests once in NodeJS
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js target/test/test.js
run-visual-test-ios: export TARGET := clojure
run-visual-test-ios: XCODE_DERIVED_DATA := $(HOME)/Library/Developer/Xcode/DerivedData
run-visual-test-ios: APPLICATION_NAME := 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
View File
@@ -1,4 +1,4 @@
{
"name": "StatusIm",
"displayName": "StatusIm"
}
}
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
/**
* This job runs daily and executes `pod repo update` on MacOS
* This is done to avoid issues with out of date repo causing errors like:
+1
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1 -1
View File
@@ -45,4 +45,4 @@ The `State` field in the Pivotal story is used to track the progress of a Pivota
| 5 points | 2 - 3 days |
| 8 points | ~1 week |
We should avoid 8 point stories by breaking them down into smaller stories as much as possible.
We should avoid 8 point stories by breaking them down into smaller stories as much as possible.
+1 -1
View File
@@ -169,7 +169,7 @@ For VS Code users.
### Start and connect the REPL
1. Open the `status-mobile` folder.
1. Start [Status development](STARTING_GUIDE.md#development) (Starting the `run-clojure` and `run-metro` jobs in split view in the VS Code integrated terminal works great.)
1. Start [Status development](starting-guide.md#development) (Starting the `run-clojure` and `run-metro` jobs in split view in the VS Code integrated terminal works great.)
1. Run the VS Code command: **Calva: Connect to a running REPL Server in the project**
1. Select the project type `shadow-cljs`
1. Accept the suggested connection `host:port`
+1 -1
View File
@@ -3,4 +3,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
@@ -1156,23 +1156,7 @@ RCT_EXPORT_METHOD(deactivateKeepAwake)
- (NSString*) deviceName
{
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;
return [[UIDevice currentDevice] name];;
}
- (NSDictionary *)constantsToExport
+1 -1
View File
@@ -18,4 +18,4 @@
"url": "https://github.com/status-im/react-native-status/issues"
},
"homepage": "https://github.com/status-im/react-native-status#readme"
}
}
+6
View File
@@ -49,6 +49,12 @@ in {
doCheck = false;
});
# Downgrade watchman in attempt to fix "too many files open issue"
watchman = callPackage ./pkgs/watchman {
inherit (super.darwin.apple_sdk.frameworks) CoreServices;
autoconf = super.buildPackages.autoconf269;
};
# Package version adjustments
gradle = super.gradle_7;
nodejs = super.nodejs-18_x;
+11
View File
@@ -17,9 +17,20 @@ 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 ];
}
+4 -1
View File
@@ -3,7 +3,10 @@
# for the Android development environment.
#
{ androidenv }:
{ androidenv, lib, stdenv }:
assert lib.assertMsg (stdenv.system != "aarch64-darwin")
"aarch64-darwin not supported for Android SDK. Use: NIXPKGS_SYSTEM_OVERRIDE=x86_64-darwin";
# The "android-sdk-license" license is accepted
# by setting android_sdk.accept_license = true.
+23
View File
@@ -0,0 +1,23 @@
# Issue
`watchman` was upgraded significantly during the last nixpkgs upgrade (`4.9.0` (Aug 16, 2017) to `2023.01.30.00` - 6 years between):
- https://github.com/status-im/status-mobile/pull/14944
- https://github.com/status-im/nixpkgs/commit/4e9c02bcc709fe1737a746add0e8e0109133d808
Probably causing developers to have "too many files open" issue:
https://github.com/status-im/status-mobile/issues/16341
```
Error: A non-recoverable condition has triggered. Watchman needs your help!
The triggering condition was at timestamp=1687286390: opendir(/Users/javid/Projects/status-mobile/node_modules/metro-core/node_modules/jest-regex-util/build) -> Too many open files
All requests will continue to fail with this message until you resolve
the underlying problem. You will find more information on fixing this at
https://facebook.github.io/watchman/docs/troubleshooting.html#poison-opendir
```
# Fix
This is an attempt to fix the issue by downgrading the watchman
# Upgrade
When upgrading in the future, please read the comments:
https://github.com/status-im/status-mobile/issues/16341
+48
View File
@@ -0,0 +1,48 @@
{ stdenv, lib, config, fetchFromGitHub, autoconf, automake, pcre
, libtool, pkg-config, openssl
, confFile ? config.watchman.confFile or null
, withApple ? stdenv.isDarwin, CoreServices
}:
stdenv.mkDerivation rec {
pname = "watchman";
version = "4.9.0";
src = fetchFromGitHub {
owner = "facebook";
repo = "watchman";
rev = "v${version}";
sha256 = "0fdaj5pmicm6j17d5q7px800m5rmam1a400x3hv1iiifnmhgnkal";
};
nativeBuildInputs = [ autoconf automake pkg-config libtool ];
buildInputs = [ pcre openssl ]
#++ lib.optionals withApple [ CoreServices ];
++ lib.optionals stdenv.isDarwin [ CoreServices ];
configureFlags = [
"--enable-lenient"
"--enable-conffile=${if confFile == null then "no" else confFile}"
"--with-pcre=yes"
# For security considerations re: --disable-statedir, see:
# https://github.com/facebook/watchman/issues/178
"--disable-statedir"
];
prePatch = ''
patchShebangs .
'';
preConfigure = ''
./autogen.sh
'';
meta = with lib; {
description = "Watches files and takes action when they change";
homepage = "https://facebook.github.io/watchman";
maintainers = with maintainers; [ cstrahan ];
platforms = with platforms; linux ++ darwin;
license = licenses.asl20;
};
}
+7 -1
View File
@@ -25,7 +25,7 @@ cleanup() {
# If you want to clean after every build set _NIX_CLEAN=true
if [[ -n "${_NIX_CLEAN}" ]]; then
trap cleanup EXIT ERR INT QUIT
trap cleanup EXIT ERR INT QUIT
fi
# build output will end up under /nix, we have to extract it
@@ -44,6 +44,12 @@ 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=(
+2 -1
View File
@@ -8,7 +8,8 @@ file_group() {
if [[ "${UNAME}" == "Linux" ]]; then
stat -Lc "%G" "${1}" 2>/dev/null
elif [[ "${UNAME}" == "Darwin" ]]; then
stat -Lf "%Sg" "${1}" 2>/dev/null
# Avoid using Nix GNU stat when in Nix shell.
/usr/bin/stat -Lf "%Sg" "${1}" 2>/dev/null
fi
}
+6 -1
View File
@@ -1,6 +1,5 @@
#!/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.
@@ -64,6 +63,12 @@ if [[ -n "${_NIX_PURE}" ]]; then
pureDesc='pure '
fi
# Hack fix for missing Android SDK for aarch64 on Darwin. See systemOverride in `nix/pkgs.nix`.
if [[ "${TARGET}" =~ ^(android-sdk|android|gradle|keytool|status-go)$ ]]; then
os=$(uname -s | tr '[:upper:]' '[:lower:]')
export NIXPKGS_SYSTEM_OVERRIDE="x86_64-${os}"
fi
echo -e "${GRN}Configuring ${pureDesc}Nix shell for target '${TARGET}'...${RST}" 1>&2
# Save derivation from being garbage collected
-1
View File
@@ -90,7 +90,6 @@
"@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",
+1 -1
View File
@@ -194,4 +194,4 @@
}
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 593 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -eof pipefail
FILES=$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep --ignore-case -E '\.(java|cpp|nix|json|sh|md|js|clj|cljs|cljc|edn)$')
N_FILES=$(echo "$FILES" | wc -l)
LINT_SHOULD_FIX=0
if [[ -n $1 && $1 != '--fix' ]]; then
echo "Unknown option '$1'" >&2
exit 1
elif [[ $1 == '--fix' ]]; then
LINT_SHOULD_FIX=1
fi
echo "Checking ${N_FILES} files for missing trailing newlines."
# Do not process the whole file and only check the last character. Ignore empty
# files. Taken from https://stackoverflow.com/a/10082466.
for file in $FILES; do
if [ -s "$file" ] && [ "$(tail -c1 "$file"; echo x)" != $'\nx' ]; then
if [[ $LINT_SHOULD_FIX -eq 1 ]]; then
echo "" >>"$file"
else
LINT_ERROR=1
echo "No trailing newline: $file" >&2
fi
fi
done
if [[ $LINT_ERROR -eq 1 ]]; then
exit 1
fi
@@ -0,0 +1,92 @@
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 };
}
});
}
+9 -21
View File
@@ -1,6 +1,8 @@
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300;
const totalPages = 4;
const pageSize = 100 / totalPages;
const easeOut = {
duration: slideAnimationDuration,
@@ -15,29 +17,15 @@ export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
});
}
export function carouselLeftPosition(windowWidth, progress) {
export function carouselLeftPosition(windowWidth, progress, isDragging, dragAmount) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
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;
}
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);
});
}
+1
View File
@@ -13,6 +13,7 @@ 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';
+59 -1
View File
@@ -1,4 +1,4 @@
import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated';
import { useDerivedValue, withTiming, withSequence, withDelay, Easing, runOnJS } from 'react-native-reanimated';
import * as constants from './constants';
// Derived Values
@@ -88,3 +88,61 @@ 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);
}
};
}
+75 -73
View File
@@ -364,77 +364,79 @@ 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 {}
"./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 {}
"../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"))
nil))
+10 -1
View File
@@ -4,7 +4,8 @@
[taoensso.timbre :as log]
[react-native.platform :as platform]
[react-native.core :as rn]
[utils.transforms :as types]))
[utils.transforms :as types]
[clojure.string :as string]))
(defn status
[]
@@ -387,6 +388,14 @@
: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")
+1 -1
View File
@@ -11,4 +11,4 @@
(for [i (keys icons/icons)]
[rn/view {:flex-direction :row}
[icons/icon (keyword i)]
[rn/text i]])])
[rn/text i]])])
+66 -18
View File
@@ -4,7 +4,9 @@
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[react-native.core :as rn]
[reagent.core :as reagent]))
[react-native.blur :as blur]
[reagent.core :as reagent]
[quo2.components.buttons.style :as style]))
(defn themes
[customization-color]
@@ -66,6 +68,16 @@
: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
@@ -135,6 +147,16 @@
: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
@@ -157,12 +179,11 @@
24 8))})
(defn style-container
[type size disabled background-color border-color icon above width before after]
[type size disabled background-color border-color icon above width before after blur-active?]
(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
@@ -192,7 +213,11 @@
56 0
40 9
32 5
24 4))}
24 4))
:overflow :hidden}
(when (or (and (= type :blurred) (not blur-active?))
(not= type :blurred))
{:background-color background-color})
(shape-style-container type icon size)
(when width
{:width width})
@@ -224,18 +249,23 @@
(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]
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?]
:or {type :primary
size 40
customization-color :primary}}
customization-color :primary
blur-active? true}}
children]
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color]}
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color blur-type
blur-overlay-color icon-background-color]}
(get-in (themes customization-color)
[theme type])
state (cond disabled :disabled
(or @pressed-in pressed) :pressed
:else :default)
icon-size (when (= 24 size) 12)
blur-state (if blur-active? :blurred :default)
icon-size (or icon-size (when (= 24 size) 12))
icon-secondary-color (or icon-secondary-color icon-color)]
[rn/touchable-without-feedback
(merge {:test-ID test-ID
@@ -264,9 +294,17 @@
above
width
before
after)
after
blur-active?)
(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
@@ -275,11 +313,16 @@
: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
{:container-style {:margin-left (if (= size 40) 12 8)
:margin-right 4}
:color icon-secondary-color
:size icon-size}]])
{:color icon-secondary-color
:size icon-size}]])
[rn/view
(cond
(or icon icon-no-color)
@@ -301,11 +344,16 @@
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
{: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}]])]]]))))
{:no-color icon-secondary-no-color
:color icon-secondary-color
:size icon-size}]])]]]))))
(def button (theme/with-theme button-internal))
@@ -2,6 +2,7 @@
(:require [react-native.core :as rn]
[quo2.components.buttons.predictive-keyboard.style :as style]
[quo2.components.info.info-message :as info-message]
[quo2.theme :as theme]
[react-native.linear-gradient :as linear-gradient]
[quo2.foundations.colors :as colors]
[quo2.components.buttons.button :as button]))
@@ -12,32 +13,33 @@
:blur [colors/white-opa-5 colors/white-opa-0]})
(defn- word-component
[word _ _ {:keys [blur? on-press]}]
[word _ _ {:keys [on-press]}]
[button/button
(merge {:type :blur-bg
:size 32
:on-press #(on-press word)}
(when blur? {:override-theme :dark}))
{:type :blur-bg
:size 32
:on-press #(on-press word)}
word])
(defn- separator
[]
[rn/view {:style {:width 8}}])
(defn view
(defn- view-internal
"Options
- `type` `:words`/`:error`/`:info`/`:empty`.
- `blur?` Boolean to enable blur background support.
- `text` error/info text.
- `words` List of words to display in the keyboard.
- `on-press` Callback called when a word is pressed `(fn [word])`."
[{:keys [type blur? text words on-press]}]
- `on-press` Callback called when a word is pressed `(fn [word])`
- `theme` :light or :dark, received from with-theme HOC."
[{:keys [type blur? text words on-press theme]}]
[linear-gradient/linear-gradient
{:style {:flex-direction :row}
:accessibility-label :predictive-keyboard
:colors (if blur?
(gradients :blur)
(colors/theme-colors (gradients :light) (gradients :dark)))}
(colors/theme-colors (gradients :light) (gradients :dark) theme))}
[rn/view {:style (style/wrapper type)}
(case type
:words
@@ -46,8 +48,7 @@
:data words
:content-container-style style/word-list
:render-fn word-component
:render-data {:blur? blur?
:on-press on-press}
:render-data {:on-press on-press}
:shows-horizontal-scroll-indicator false
:separator [separator]
:horizontal true
@@ -70,3 +71,5 @@
:icon-color colors/white-opa-70}))
text]
nil)]])
(def view (theme/with-theme view-internal))
+42
View File
@@ -0,0 +1,42 @@
(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)})))
+11 -11
View File
@@ -9,33 +9,33 @@
:height 20})
(defn neutral-border-color
[in-blur-view? override-theme]
[in-blur-view? theme]
(if in-blur-view?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-10 override-theme)
(colors/theme-colors colors/neutral-20 colors/neutral-80 override-theme)))
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-10 theme)
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)))
(def active-background-color (colors/custom-color :blue 50 10))
(def complete-background-color (colors/custom-color :blue 50))
(defn active-background-color [customization-color] (colors/custom-color customization-color 50 10))
(defn complete-background-color [customization-color] (colors/custom-color customization-color 50))
(defn container
[size type in-blur-view? override-theme]
[{:keys [size type in-blur-view? theme customization-color]}]
(cond-> container-base
(#{1 2} size) (assoc :width 20)
(= size 3) (assoc :width 28)
(= type :neutral)
(assoc :border-width 1
:border-color (neutral-border-color in-blur-view? override-theme))
:border-color (neutral-border-color in-blur-view? theme))
(= type :active)
(assoc :background-color active-background-color)
(assoc :background-color (active-background-color customization-color))
(= type :complete)
(assoc :background-color complete-background-color)))
(assoc :background-color (complete-background-color customization-color))))
(defn text-color
([type] (text-color type nil))
([type override-theme]
([type theme]
(case type
(:neutral :active) (colors/theme-colors colors/neutral-100-opa-100 colors/white override-theme)
(:neutral :active) (colors/theme-colors colors/neutral-100-opa-100 colors/white theme)
:complete colors/white)))
+11 -4
View File
@@ -2,11 +2,12 @@
(:require
[quo2.components.counter.step.style :as style]
[quo2.components.markdown.text :as text]
[quo2.theme :as theme]
[react-native.core :as rn]
[utils.number]))
(defn step
[{:keys [type accessibility-label override-theme in-blur-view?]} value]
(defn step-internal
[{:keys [type accessibility-label theme in-blur-view? customization-color]} value]
(let [type (or type :neutral)
value (utils.number/parse-int value)
label (str value)
@@ -14,8 +15,14 @@
[rn/view
{:accessible true
:accessibility-label (or accessibility-label :step-counter)
:style (style/container size type in-blur-view? override-theme)}
:style (style/container {:size size
:type type
:in-blur-view? in-blur-view?
:theme theme
:customization-color customization-color})}
[text/text
{:weight :medium
:size :label
:style {:color (style/text-color type override-theme)}} label]]))
:style {:color (style/text-color type theme)}} label]]))
(def step (theme/with-theme step-internal))
+11 -11
View File
@@ -1,8 +1,8 @@
(ns quo2.components.dividers.divider-label
(:require [quo2.theme :as theme]
[quo2.components.icon :as icons]
(:require [quo2.components.icon :as icons]
[quo2.components.markdown.text :as markdown.text]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[react-native.core :as rn]))
(def chevron-icon-container-width 20)
@@ -36,18 +36,18 @@
padding-top (if increase-padding-top? 16 8)
text-and-icon-color (if dark? colors/neutral-40 colors/neutral-50)
counter-text-color (if dark? colors/white colors/neutral-100)]
[rn/touchable-without-feedback
{:on-press on-press}
[rn/touchable-without-feedback {:on-press on-press}
[rn/view
{:accessible true
:accessibility-label :divider-label
:style (merge {:border-top-width 1
:border-top-color border-and-counter-bg-color
:padding-top padding-top
:padding-bottom padding-bottom
:padding-horizontal 16
:align-items :center
:flex-direction :row}
:style (merge {:border-top-width 1
:border-top-color border-and-counter-bg-color
:padding-top padding-top
:padding-bottom padding-bottom
:padding-left 16
:padding-right 16
:align-items :center
:flex-direction :row}
container-style)}
(when (= chevron-position :left)
[rn/view
@@ -1,4 +1,10 @@
(ns quo2.components.drawers.documentation-drawers.style)
(ns quo2.components.drawers.documentation-drawers.style
(:require [quo2.foundations.colors :as colors]
[react-native.safe-area :as safe-area]))
(def outer-container
;; Margin negative to fill the bottom-sheet container where this component is used
{:margin-bottom (- (+ (safe-area/get-bottom) 8))})
(def container
{:align-items :flex-start
@@ -6,4 +12,10 @@
(def content
{:margin-top 8
:margin-bottom 16})
:margin-bottom (+ (safe-area/get-bottom) 8)})
(defn title
[shell?]
{:color (colors/theme-colors colors/neutral-100
colors/white
(when shell? :dark))})
@@ -1,10 +1,9 @@
(ns quo2.components.drawers.documentation-drawers.view
(:require [quo2.components.markdown.text :as text]
(:require [quo2.components.buttons.button :as button]
[quo2.components.drawers.documentation-drawers.style :as style]
[quo2.components.markdown.text :as text]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[quo2.components.buttons.button :as button]
[quo2.foundations.colors :as colors]))
[react-native.gesture :as gesture]))
(defn view
"Options
@@ -14,18 +13,18 @@
- `button-icon` button icon
- `on-press-button` On press handler for the button
- `shell?` use shell theme
`content` Content of the drawer
"
[{:keys [title show-button? on-press-button button-label button-icon shell?]} content]
[gesture/scroll-view
{:style style/outer-container
:always-bounce-vertical false
:content-inset-adjustment-behavior :never}
[rn/view {:style style/container}
[text/text
{:size :heading-2
:accessibility-label :documentation-drawer-title
:style {:color (colors/theme-colors colors/neutral-100
colors/white
(when shell? :dark))}
:style (style/title shell?)
:weight :semi-bold}
title]
[rn/view {:style style/content :accessibility-label :documentation-drawer-content}
@@ -1,9 +1,19 @@
(ns quo2.components.drawers.drawer-buttons.component-spec
(:require [quo2.components.drawers.drawer-buttons.view :as drawer-buttons]
[react-native.core :as rn]
[test-helpers.component :as h]))
[test-helpers.component :as h]
[react-native.safe-area :as safe-area]))
(h/describe "drawer-buttons"
(h/before-each
(fn []
(h/use-fake-timers)))
(h/after-each
(fn []
(h/clear-all-timers)
(h/use-real-timers)))
(h/test "the top heading and subheading render"
(h/render [drawer-buttons/view
{:top-card {:heading :top-heading}
@@ -29,15 +39,16 @@
(h/test "it clicks the top card"
(let [event (h/mock-fn)]
(h/render [drawer-buttons/view
{:top-card {:on-press event
:heading :top-heading}
:bottom-card {:heading :bottom-heading}}
:top-sub-heading
:bottom-sub-heading])
(h/fire-event :press (h/get-by-text "top-heading"))
(-> (js/expect event)
(.toHaveBeenCalled))))
(with-redefs [safe-area/get-top (fn [] 10)]
(h/render [drawer-buttons/view
{:top-card {:on-press event
:heading :top-heading}
:bottom-card {:heading :bottom-heading}}
:top-sub-heading
:bottom-sub-heading])
(h/fire-event :press (h/get-by-text "top-heading"))
(-> (js/expect event)
(.toHaveBeenCalled)))))
(h/test "it clicks the bottom card"
(let [event (h/mock-fn)]
@@ -1,11 +1,20 @@
(ns quo2.components.drawers.drawer-buttons.style
(:require [quo2.foundations.colors :as colors]))
(:require [quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(def outer-container
{:height 216
:border-top-left-radius 20
:border-top-right-radius 20
:overflow :hidden})
(defn outer-container
[height border-radius container-style]
(reanimated/apply-animations-to-style
{:height height
:border-top-left-radius border-radius
:border-top-right-radius border-radius}
(assoc
container-style
:position :absolute
:left 0
:right 0
:bottom 0
:overflow :hidden)))
(def top-card
{:flex 1
@@ -17,7 +26,6 @@
(def bottom-card
{:position :absolute
:top 80
:left 0
:right 0
:bottom 0
@@ -41,6 +49,20 @@
:align-items :center
:border-color colors/white-opa-5})
(def blur-view-style
{:flex 1
:border-top-left-radius 20
:border-top-right-radius 20})
(def blur-content-style
{:flex 1
:background-color :transparent
:position :absolute
:top 0
:left 0
:right 0
:bottom 0})
(def bottom-text
{:flex 1
:color colors/white-70-blur})
@@ -51,4 +73,4 @@
(defn heading-text
[gap]
{:color colors/white
:margin-bottom gap})
:margin-bottom gap})
@@ -4,7 +4,12 @@
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[quo2.components.drawers.drawer-buttons.style :as style]))
[quo2.components.drawers.drawer-buttons.style :as style]
[react-native.reanimated :as reanimated]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]))
(def default-height 216)
(defn render-bottom
[children]
@@ -29,35 +34,74 @@
children]]
[render-bottom children]))
(defn render-children-top
[children]
(if (label? children)
[text/text
{:size :paragraph-2
:style style/top-text
:weight :semi-bold}
children]
children))
(defn- f-render-children-top
[children top-children-opacity]
(let [scale (reanimated/interpolate top-children-opacity [1 0] [1 1.1])
padding-left (reanimated/interpolate scale [1 1.1] [0 14])]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity top-children-opacity
:transform [{:scale scale}
{:translate-x padding-left}]}
{})}
(if (label? children)
[text/text
{:size :paragraph-2
:style style/top-text
:weight :semi-bold}
children]
children)]))
(defn card
[{:keys [on-press style heading gap accessibility-label top?]} children]
(defn- f-card
[{:keys [on-press default-on-press style heading gap accessibility-label top? top-title-opacity
top-children-opacity
animated-heading]
:or {top-title-opacity (reanimated/use-shared-value 1)}}
children]
[rn/touchable-highlight
{:accessibility-label accessibility-label
:on-press on-press
:on-press (fn []
(when on-press
(on-press))
(when default-on-press
(default-on-press)))
:border-radius 20
:style style
:underlay-color (:background-color style)}
[rn/view
[text/text
{:size :heading-1
:style (style/heading-text gap)
:weight :semi-bold}
heading]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity top-title-opacity}
{})}
[text/text
{:size :heading-1
:style (style/heading-text gap)
:weight :semi-bold}
heading]]
(when animated-heading
(let [animated-heading-opacity (reanimated/interpolate top-children-opacity [1 0] [0 1])]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity top-title-opacity}
{:position :absolute})}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity animated-heading-opacity}
{})}
[text/text
{:size :heading-1
:style (style/heading-text gap)
:weight :semi-bold}
animated-heading]]]))
(if top?
[render-children-top children]
[:f> f-render-children-top children top-children-opacity]
[render-children-bottom children])]])
(defn view
(defn card
[props children]
[:f> f-card props children])
(defn f-view
"[view opts]
opts
{:container-style style-object
@@ -70,29 +114,101 @@
child-1 string, keyword or hiccup
child-2 string, keyword or hiccup
"
[{:keys [container-style top-card bottom-card]} child-1 child-2]
[rn/view
{:style (merge container-style style/outer-container)}
[blur/view
{:blur-type :dark
:blur-amount 10
:style {:flex 1
:border-top-left-radius 20
:border-top-right-radius 20}}]
[rn/view
{:style {:flex 1
:background-color :transparent
:position :absolute
:top 0
:left 0
:right 0
:bottom 0}}
[card
(merge {:gap 4
:top? true
:style style/top-card}
top-card) child-1]
[card
(merge {:style style/bottom-card
:gap 20}
bottom-card) child-2]]])
[{:keys [container-style top-card bottom-card on-init animations-duration animations-delay]}
child-1
child-2]
(let [max-height (+ (:height (rn/get-window)) (if platform/android? (safe-area/get-top) 0))
height (reanimated/use-shared-value default-height)
top-padding (reanimated/use-shared-value 12)
border-radius (reanimated/use-shared-value 20)
bottom-view-top (reanimated/use-shared-value 80)
top-title-opacity (reanimated/use-shared-value 1)
top-children-opacity (reanimated/use-shared-value 1)
animations-delay (/ animations-delay 1.4)
start-top-animation (fn []
(reanimated/animate-shared-value-with-delay bottom-view-top
(:height (rn/get-screen))
animations-duration
:easing4
animations-delay)
(reanimated/animate-shared-value-with-delay
height
max-height
animations-duration
:easing4
animations-delay)
(reanimated/animate-shared-value-with-delay
top-padding
(+ 68 (safe-area/get-top))
animations-duration
:easing4
animations-delay)
(reanimated/animate-shared-value-with-delay
top-children-opacity
0
animations-duration
:easing4 animations-delay)
(reanimated/animate-shared-value-with-delay
top-title-opacity
0
0
:linear
(+ animations-delay animations-duration 500)))
reset-top-animation (fn []
(reanimated/set-shared-value top-title-opacity 1)
(reanimated/animate-shared-value-with-delay bottom-view-top
80
animations-duration
:easing4
50)
(reanimated/animate-shared-value-with-timing
height
default-height
animations-duration
:easing4)
(reanimated/animate-shared-value-with-timing
top-padding
12
animations-duration
:easing4)
(reanimated/animate-shared-value-with-timing
top-children-opacity
1
animations-duration
:easing4))]
(rn/use-effect (fn []
(when on-init
(on-init reset-top-animation))))
[reanimated/view {:style (style/outer-container height border-radius container-style)}
[blur/view
{:blur-type :dark
:blur-amount 10
:style style/blur-view-style}
[rn/view
{:style style/blur-content-style}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:padding-top top-padding}
style/top-card)}
[card
(merge {:gap 4
:top? true
:style {:flex 1}
:top-children-opacity top-children-opacity
:top-title-opacity top-title-opacity
:default-on-press start-top-animation}
top-card)
child-1]]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:top bottom-view-top}
style/bottom-card)}
[card
(merge {:style {:flex 1}
:gap 10}
bottom-card)
child-2]]]]]))
(defn view
[props child-1 child-2]
[:f> f-view props child-1 child-2])
+6 -2
View File
@@ -7,8 +7,12 @@
[button/button
(merge
opts
{:after (if selected :i/pullup :i/dropdown)
:icon-secondary-no-color true
{: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}
:pressed selected
:on-press #(when on-change (on-change selected))})
children]))
@@ -3,9 +3,10 @@
[quo2.components.empty-state.empty-state.styles :as styles]
[quo2.components.markdown.text :as text]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]))
[react-native.fast-image :as fast-image]
[quo2.theme :as theme]))
(defn empty-state
(defn- empty-state-internal
[{:keys [customization-color image title description blur?]
upper-button :upper-button
lower-button :lower-button
@@ -32,19 +33,18 @@
upper-button-on-press :on-press} upper-button]
[rn/view {:style styles/button-container}
[button/button
(cond-> {:type :primary
:size 32
:override-background-color (styles/upper-button-color customization-color)
:on-press upper-button-on-press}
blur? (assoc :override-theme :dark))
{:type :primary
:size 32
:override-background-color (styles/upper-button-color customization-color)
:on-press upper-button-on-press}
upper-button-text]
(when-let [{lower-button-text :text
lower-button-on-press :on-press} lower-button]
[button/button
(cond-> {:style {:margin-top 12}
:size 32
:type :blur-bg
:on-press lower-button-on-press}
blur? (assoc :override-theme :dark))
{:style {:margin-top 12}
:size 32
:type :blur-bg
:on-press lower-button-on-press}
lower-button-text])])])
(def empty-state (theme/with-theme empty-state-internal))
@@ -37,7 +37,6 @@
[buttons/button
{:accessibility-label :select-profile-picture-button
:type :grey
:override-theme :dark
:override-background-color (colors/alpha colors/white 0.05)
:on-press on-press
:icon-size 20
@@ -50,6 +49,5 @@
[title-input/title-input
(merge title-input-props
{:blur? true
:override-theme :dark
:placeholder placeholder
:customization-color customization-color})]]])
@@ -3,50 +3,50 @@
[react-native.platform :as platform]))
(defn get-focused-placeholder-color
[blur? override-theme]
[blur? theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 override-theme)
(colors/theme-colors colors/neutral-30 colors/neutral-60 override-theme))
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme))
)
(defn get-placeholder-color
[blur? override-theme]
[blur? theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 override-theme)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 theme)
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
(defn- get-disabled-color
[blur? override-theme]
[blur? theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
(defn- get-char-count-color
[blur? override-theme]
[blur? theme]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
(defn get-selection-color
[customization-color blur? override-theme]
[customization-color blur? theme]
(colors/alpha (if blur?
(colors/theme-colors colors/neutral-100 colors/white override-theme)
(colors/theme-colors colors/neutral-100 colors/white theme)
(colors/custom-color customization-color
(if (or (= :dark override-theme) colors/dark?) 60 50)))
(if (or (= :dark theme) colors/dark?) 60 50)))
(if platform/ios? 1 0.2)))
(def text-input-container {:flex 1})
(defn title-text
[disabled? blur? override-theme]
[disabled? blur? theme]
{:text-align-vertical :bottom
:color (if disabled?
(get-disabled-color blur? override-theme)
(colors/theme-colors colors/neutral-100 colors/white override-theme))})
(get-disabled-color blur? theme)
(colors/theme-colors colors/neutral-100 colors/white theme))})
(defn char-count
[blur? override-theme]
{:color (get-char-count-color blur? override-theme)})
[blur? theme]
{:color (get-char-count-color blur? theme)})
(def container
{:flex-direction :row
@@ -12,14 +12,14 @@
(str 0 value)
value))
(defn title-input
(defn- title-input-internal
[{:keys [blur?
on-change-text
auto-focus
placeholder
max-length
default-value
override-theme]
theme]
:or {max-length 0
auto-focus false
default-value ""}}]
@@ -38,10 +38,10 @@
(text/text-style
{:size :heading-2
:weight :semi-bold
:style (style/title-text disabled? blur? override-theme)})
:style (style/title-text disabled? blur? theme)})
:default-value default-value
:accessibility-label :profile-title-input
:keyboard-appearance (theme/theme-value :light :dark override-theme)
:keyboard-appearance (theme/theme-value :light :dark theme)
:on-focus #(swap! focused? (constantly true))
:on-blur #(swap! focused? (constantly false))
:auto-focus auto-focus
@@ -50,22 +50,24 @@
:editable (not disabled?)
:max-length max-length
:placeholder placeholder
:selection-color (style/get-selection-color customization-color blur? override-theme)
:selection-color (style/get-selection-color customization-color blur? theme)
:placeholder-text-color (if @focused?
(style/get-focused-placeholder-color blur? override-theme)
(style/get-placeholder-color blur? override-theme))}]]
(style/get-focused-placeholder-color blur? theme)
(style/get-placeholder-color blur? theme))}]]
[rn/view
{:style style/counter-container}
[text/text
[text/text
{:style (style/char-count blur? override-theme)
{:style (style/char-count blur? theme)
:size :paragraph-2}
(pad-0
(str
(count @value)))]
[text/text
{:style (style/char-count blur? override-theme)
{:style (style/char-count blur? theme)
:size :paragraph-2}
(str "/"
(pad-0
(str max-length)))]]]])))
(def title-input (theme/with-theme title-input-internal))
+36 -42
View File
@@ -1,12 +1,11 @@
(ns quo2.components.list-items.channel
(:require [quo2.components.avatars.channel-avatar :as channel-avatar]
[quo2.components.common.unread-grey-dot.view :refer [unread-grey-dot]]
[quo2.components.counter.counter :as quo2.counter]
[quo2.components.icon :as quo2.icons]
[quo2.components.markdown.text :as quo2.text]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[react-native.core :as rn]
[quo2.components.common.unread-grey-dot.view :refer [unread-grey-dot]]))
[react-native.core :as rn]))
(def ^:private custom-props
[:name :locked? :mentions-count :unread-messages?
@@ -21,22 +20,20 @@
name-text (:name props)]
[rn/touchable-opacity standard-props
[rn/view
{:style (merge {:height 48
:display :flex
:border-radius 12
:flex-direction :row
:justify-content :space-between
:align-items :center
:width "100%"
:padding-left 12
:padding-right 12}
(when is-active-channel?
{:background-color (colors/theme-alpha channel-color 0.05 0.05)}))}
{:style (cond-> {:height 48
:border-radius 12
:flex-direction :row
:justify-content :space-between
:align-items :center
:width "100%"
:padding-left 12
:padding-right 12}
is-active-channel? (assoc :background-color
(colors/theme-alpha channel-color 0.05 0.05)))}
[rn/view
{:display :flex
:flex-direction :row
:justify-content :flex-start
:align-items :center
{:style {:flex-direction :row
:justify-content :flex-start
:align-items :center}
:accessible true
:accessibility-label :chat-name-text}
[channel-avatar/channel-avatar
@@ -45,28 +42,25 @@
:emoji-background-color (colors/theme-alpha channel-color 0.1 0.1)
:emoji emoji}]
[quo2.text/text
{:style (merge {:margin-left 12}
(when (and (not locked?) muted?)
{:color (if (theme/dark?) colors/neutral-60 colors/neutral-40)}))
{:style (cond-> {:margin-left 12}
(and (not locked?) muted?)
(assoc :color (colors/theme-colors colors/neutral-40 colors/neutral-60)))
:weight :medium
:size :paragraph-1} (str "# " name-text)]]
[rn/view
{:style {:height 20
:justify-content :center}}
(when (and (not locked?)
muted?)
[quo2.icons/icon :i/muted
{:size 20
:color colors/neutral-40}])
(when (and (not locked?)
(not muted?)
(pos? (int mentions-count)))
[rn/view
{:style {:margin-right 2
:margin-top 2}}
[quo2.counter/counter {:override-bg-color channel-color} mentions-count]])
(when (and (not locked?)
(not muted?)
(not (pos? (int mentions-count)))
unread-messages?)
[unread-grey-dot :unviewed-messages-public])]]]))
:size :paragraph-1}
(str "# " name-text)]]
(when-not locked?
[rn/view {:style {:height 20 :justify-content :center}}
(cond
muted?
[quo2.icons/icon :i/muted
{:size 20
:color colors/neutral-40
:container-style {:margin-right 1 :margin-top 2}}]
(pos? (int mentions-count))
[rn/view {:style {:margin-right 2 :margin-top 2}}
[quo2.counter/counter {:override-bg-color channel-color}
mentions-count]]
unread-messages?
[unread-grey-dot :unviewed-messages-public])])]]))
@@ -0,0 +1,95 @@
(ns quo2.components.loaders.skeleton.constants)
(def ^:const layout-dimensions
{:messages {:height 56
:padding-top 12}
:list-items {:height 56
:padding-top 12}
:notifications {:height 90
:padding-top 8}})
(def ^:const content-dimensions
{:messages {0 {:author {:width 112
:height 8
:margin-bottom 8}
:message {:width 144
:height 16
:margin-bottom 0}}
1 {:author {:width 96
:height 8
:margin-bottom 8}
:message {:width 212
:height 16
:margin-bottom 0}}
2 {:author {:width 80
:height 8
:margin-bottom 8}
:message {:width 249
:height 16
:margin-bottom 0}}
3 {:author {:width 124
:height 8
:margin-bottom 8}
:message {:width 156
:height 16
:margin-bottom 0}}}
:list-items {0 {:author {:width 112
:height 8
:margin-bottom 0}
:message {:width 144
:height 16
:margin-bottom 8}}
1 {:author {:width 96
:height 8
:margin-bottom 0}
:message {:width 212
:height 16
:margin-bottom 8}}
2 {:author {:width 80
:height 8
:margin-bottom 0}
:message {:width 249
:height 16
:margin-bottom 8}}
3 {:author {:width 124
:height 8
:margin-bottom 0}
:message {:width 156
:height 16
:margin-bottom 8}}}
:notifications {0 {:author {:width 109
:height 8
:margin-bottom 8}
:message {:width 167
:height 16
:margin-bottom 8}
:message2 {:width 242
:height 30
:margin-bottom 0}}
1 {:author {:width 165
:height 8
:margin-bottom 8}
:message {:width 112
:height 16
:margin-bottom 8}
:message2 {:width 294
:height 30
:margin-bottom 0}}
2 {:author {:width 136
:height 8
:margin-bottom 8}
:message {:width 178
:height 16
:margin-bottom 8}
:message2 {:width 178
:height 30
:margin-bottom 0}}
3 {:author {:width 136
:height 8
:margin-bottom 8}
:message {:width 166
:height 16
:margin-bottom 8}
:message2 {:width 256
:height 30
:margin-bottom 0}}}})
@@ -0,0 +1,29 @@
(ns quo2.components.loaders.skeleton.style
(:require [quo2.components.loaders.skeleton.constants :as constants]))
(defn container
[content]
{:flex-direction :row
:padding 12
:padding-top (get-in constants/layout-dimensions [content :padding-top])
:height (get-in constants/layout-dimensions [content :height])})
(defn avatar
[color]
{:height 32
:width 32
:border-radius 16
:background-color color})
(def content-container
{:padding-left 8})
(defn content-view
[{:keys [type index content color]}]
(let [{:keys [width height margin-bottom]}
(get-in constants/content-dimensions [content index type])]
{:height height
:width width
:border-radius 6
:background-color color
:margin-bottom margin-bottom}))
@@ -0,0 +1,46 @@
(ns quo2.components.loaders.skeleton.view
(:require [quo2.theme :as theme]
[react-native.core :as rn]
[quo2.foundations.colors :as colors]
[quo2.components.loaders.skeleton.style :as style]
[quo2.components.loaders.skeleton.constants :as constants]))
(defn- skeleton-item
[index content color]
[rn/view {:style (style/container content)}
[rn/view {:style (style/avatar color)}]
[rn/view {:style style/content-container}
[rn/view
{:style (style/content-view
{:type (if (= content :list-items) :message :author)
:index index
:content content
:color color})}]
[rn/view
{:style (style/content-view
{:type (if (= content :list-items) :author :message)
:index index
:content content
:color color})}]
(when (= content :notifications)
[rn/view
{:style (style/content-view {:type :message2
:index index
:content content
:color color})}])]])
(defn- internal-view
[{:keys [content theme blur? parent-height]}]
(let [number-of-skeletons (int (Math/floor (/ parent-height
(get-in constants/layout-dimensions [content :height]))))
color (cond
blur? colors/white-opa-5
(= theme :dark) colors/neutral-90
:else colors/neutral-5)]
[rn/view {:style {:padding 8}}
(doall
(for [index (range number-of-skeletons)]
^{:key index}
[skeleton-item (mod index 4) content color]))]))
(def view (theme/with-theme internal-view))
@@ -0,0 +1,38 @@
(ns quo2.components.markdown.list.component-spec
(:require [quo2.components.markdown.list.view :as list]
[test-helpers.component :as h]))
(h/describe "tests for markdown/list component"
(h/test "renders component with title"
(h/render [list/view {:title "test title"}])
(h/is-truthy (h/get-by-text "test title")))
(h/test "renders component with description"
(h/render [list/view
{:title "test title"
:description "test description"}])
(h/is-truthy (h/get-by-text "test description")))
(h/test "renders component with title and description"
(h/render [list/view
{:title "test title"
:description "test description"}])
(h/is-truthy (h/get-by-text "test title"))
(h/is-truthy (h/get-by-text "test description")))
(h/test "renders step component when step-number is valid and type is step"
(h/render [list/view
{:type :step
:step-number 1}])
(h/is-truthy (h/get-by-label-text :step-counter)))
(h/test "renders decription with a context tag component and description after the tag"
(h/render [list/view
{:step-number 1
:description "Lorem ipsum "
:tag-name "dolor"
:description-after-tag "text after tag"}])
(h/is-truthy (h/get-by-text "Lorem ipsum"))
(h/is-truthy (h/get-by-label-text :user-avatar))
(h/is-truthy (h/get-by-text "dolor"))
(h/is-truthy (h/get-by-text "text after tag"))))
@@ -0,0 +1,15 @@
(ns quo2.components.markdown.list.style)
(defn container
[container-style]
(merge container-style
{:flex-direction :row
:flex 1
:align-items :flex-start}))
(def index
{:margin-left 5})
(def text-container
{:margin-left 8
:flex 1})
@@ -0,0 +1,65 @@
(ns quo2.components.markdown.list.view
(:require [react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.counter.step.view :as step]
[quo2.components.markdown.list.style :as style]
[quo2.components.icon :as icon]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[quo2.components.tags.context-tag.view :as context-tag]))
(defn get-colors
[theme blur?]
(cond (and blur? (= theme :dark)) colors/white-opa-40
(= theme :dark) colors/neutral-50
:else colors/neutral-40))
(defn description-text
[{:keys [description tag-name tag-picture description-after-tag blur?]}]
(if-not tag-name
[text/text
{:accessibility-label :list-item-description
:size :paragraph-2}
description]
[rn/view {:style {:flex-direction :row :align-items :center}}
[text/text
{:accessibility-label :list-item-description
:size :paragraph-2}
description]
[rn/view {:style {:margin-left 4}}
[context-tag/context-tag {:blur? blur?} tag-picture tag-name]]
[text/text
{:style {:margin-left 4}
:accessibility-label :list-item-description-after-tag
:size :paragraph-2}
description-after-tag]]))
(defn- internal-view
[{:keys [theme title description tag-picture tag-name description-after-tag step-number
customization-color type blur? container-style]
:or {type :bullet}}]
[rn/view {:style (style/container container-style)}
[rn/view {:style style/index}
(if (= type :step)
[step/step
{:in-blur-view? blur?
:customization-color customization-color
:type (if customization-color :complete :neutral)} step-number]
[icon/icon :i/bullet {:color (get-colors theme blur?)}])]
[rn/view {:style style/text-container}
(when title
[text/text
{:accessibility-label :list-item-title
:weight :semi-bold
:size :paragraph-2}
title])
(when description
[rn/view (when title {:style {:margin-top 0}})
[description-text
{:description description
:tag-name tag-name
:tag-picture tag-picture
:description-after-tag description-after-tag
:blur? blur?}]])]])
(def view (theme/with-theme internal-view))
+14 -12
View File
@@ -5,7 +5,8 @@
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]))
[react-native.core :as rn]
[quo2.theme :as theme]))
(def ^:private centrify-style
{:display :flex
@@ -30,7 +31,7 @@
{:no-color true})))
(defn left-section-view
[{:keys [on-press icon accessibility-label type icon-background-color icon-override-theme]
[{:keys [on-press icon accessibility-label type icon-background-color]
:or {type :grey}}
put-middle-section-on-left?]
[rn/view {:style (when put-middle-section-on-left? {:margin-right 5})}
@@ -40,7 +41,6 @@
:type type
:size 32
:accessibility-label accessibility-label
:override-theme icon-override-theme
:override-background-color icon-background-color}
icon]])
@@ -87,10 +87,10 @@
(defn- mid-section-view
[{:keys [horizontal-description? one-icon-align-left? type left-align?
main-text right-icon main-text-icon-color left-icon on-press avatar]
main-text right-icon main-text-icon-color left-icon on-press avatar theme]
:as props}]
(let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95)
text-secondary-color (if (colors/dark?) colors/neutral-40 colors/neutral-50)
(let [text-color (colors/theme-colors colors/neutral-95 colors/neutral-5 theme)
text-secondary-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
component-instance [mid-section-comp (assoc props :text-secondary-color text-secondary-color)]]
[rn/touchable-opacity {:on-press on-press}
[rn/view
@@ -152,7 +152,7 @@
:justify-content :flex-end)}
(let [last-icon-index (-> right-section-buttons count dec)]
(map-indexed (fn [index
{:keys [icon on-press type style icon-override-theme icon-background-color
{:keys [icon on-press type style icon-background-color
accessibility-label label]
:or {type :grey}}]
^{:key index}
@@ -168,12 +168,11 @@
:type type
:before (when label icon)
:size 32
:override-theme icon-override-theme
:override-background-color icon-background-color}
(if label label icon)]])
right-section-buttons))])
(defn page-nav
(defn- page-nav-internal
"[page-nav opts]
opts
{ :one-icon-align-left? true/false
@@ -198,25 +197,26 @@
{:type button-type
:on-press event
:icon icon
:icon-override-theme :light/:dark
}
:right-section-buttons vector of
{:type button-type
:on-press event
:icon icon
:icon-override-theme :light/:dark
}
:theme :light or :dark
}
"
[{:keys [container-style one-icon-align-left? horizontal-description?
align-mid? page-nav-color page-nav-background-uri
mid-section
left-section
right-section-buttons]}]
right-section-buttons
theme]}]
(let [put-middle-section-on-left? (or align-mid?
(> (count right-section-buttons) 1))
mid-section-props
{:type (:type mid-section)
:theme theme
:horizontal-description? horizontal-description?
:description-img (:description-img mid-section)
:main-text (:main-text mid-section)
@@ -258,3 +258,5 @@
(not put-middle-section-on-left?)
[mid-section-view mid-section-props]))]
[right-section-view right-section-buttons]]))
(def page-nav (theme/with-theme page-nav-internal))
@@ -21,8 +21,7 @@
(defn toast-undo-action
[duration on-press override-theme]
[toast-action-container
{:on-press on-press :accessibility-label :toast-undo-action}
[toast-action-container {:on-press on-press :accessibility-label :toast-undo-action}
[rn/view {:style {:margin-right 5}}
[count-down-circle/circle-timer {:duration duration}]]
[text/text
@@ -31,17 +30,17 @@
(defn- toast-container
[{:keys [left title text right container-style override-theme]}]
[rn/view
{:style (merge style/box-container container-style)}
[rn/view {:style (merge style/box-container container-style)}
[blur/view
{:style style/blur-container
:blur-amount 13
:blur-radius 10
:blur-type :transparent
:overlay-color :transparent}]
[rn/view
{:style (style/content-container override-theme)}
[rn/view {:style style/left-side-container} left]
[rn/view {:style (style/content-container override-theme)}
[rn/view {:style style/left-side-container}
left]
[rn/view {:style style/right-side-container}
(when title
[text/text
@@ -57,7 +56,7 @@
:style (style/text override-theme)
:accessibility-label :toast-content}
text])]
(when right right)]])
right]])
(defn toast
[{:keys [icon icon-color title text action undo-duration undo-on-press container-style
@@ -1,7 +1,9 @@
(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]))
[test-helpers.component :as h]
[reagent.core :as reagent]
[utils.datetime :as datetime]))
(h/describe "record audio component"
(h/before-each
@@ -34,12 +36,16 @@
(.toHaveBeenCalledTimes 1))))
(h/test "record-audio on-reviewing-audio works"
(let [event (js/jest.fn)]
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(h/render [record-audio/record-audio
{:on-reviewing-audio event
:record-audio-permission-granted true}])
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
(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))
audio/get-recorder-file-path (fn [] "file-path")]
(h/fire-event
:on-start-should-set-responder
@@ -48,25 +54,30 @@
: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 70
:locationY 70
:timestamp 200
:identifier 0}})
(h/advance-timers-by-time 250)
(-> (h/expect event)
(.toHaveBeenCalledTimes 1)))))
(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/test "record-audio on-send works after reviewing audio"
(let [event (js/jest.fn)]
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(h/render [record-audio/record-audio
{:on-send event
:record-audio-permission-granted true}])
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
(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))
audio/get-recorder-file-path (fn [] "audio-file-path")
audio/get-player-duration (fn [] 5000)]
(h/fire-event
@@ -76,46 +87,57 @@
: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 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})))))
(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/test "record-audio on-send works after sliding to the send button"
(let [event (js/jest.fn)]
(let [event (js/jest.fn)
on-meter (reagent/atom nil)
last-now-ms (atom nil)
duration-ms (atom nil)]
(h/render [record-audio/record-audio
{:on-send event
:record-audio-permission-granted true}])
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
(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))
audio/stop-recording (fn [_ on-stop _]
(on-stop))
audio/get-recorder-file-path (fn [] "audio-file-path")]
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))]
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
@@ -123,36 +145,46 @@
:locationY 70
:timestamp 0
:identifier 0}})
(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})))))
(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/test "record-audio on-cancel works after reviewing audio"
(let [event (js/jest.fn)]
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(h/render [record-audio/record-audio
{:on-cancel event
:record-audio-permission-granted true}])
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))]
(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))]
(h/fire-event
:on-start-should-set-responder
(h/get-by-test-id "record-audio")
@@ -160,32 +192,37 @@
: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 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)))))
(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/test "cord-audio on-cancel works after sliding to the cancel button"
(let [event (js/jest.fn)]
(h/test "record-audio on-cancel works after sliding to the cancel button"
(let [event (js/jest.fn)
on-meter (reagent/atom nil)]
(h/render [record-audio/record-audio
{:on-cancel event
:record-audio-permission-granted true}])
(with-redefs [audio/start-recording (fn [_ on-start _]
(on-start))
(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))
audio/stop-recording (fn [_ on-stop _]
(on-stop))]
(h/fire-event
@@ -195,22 +232,25 @@
:locationY 70
:timestamp 0
:identifier 0}})
(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))))))
(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)))))))
@@ -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-timer recording-length-ms
record-button-at-initial-position? locked? reviewing-audio? 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,7 +82,6 @@
(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,11 +15,13 @@
[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]))
[clojure.string :as string]
[utils.datetime :as datetime]
[react-native.platform :as platform]))
(def ^:private min-audio-duration-ms 500)
(def ^:private max-audio-duration-ms 120000)
(def ^:private metering-interval 100)
(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 base-filename "am")
(def ^:private default-format ".aac")
@@ -108,7 +110,7 @@
time-str]]))
(defn- f-play-button
[playing-audio? player-ref playing-timer audio-current-time-ms seeking-audio?]
[playing-audio? player-ref playing-timer audio-current-time-ms seeking-audio? max-duration-ms]
(let [on-play (fn []
(reset! playing-audio? true)
(reset! playing-timer
@@ -117,8 +119,22 @@
(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))
(reset! audio-current-time-ms current-time))))
(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: " %)))))
100)))
on-pause (fn []
(reset! playing-audio? false)
@@ -143,7 +159,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]}]
audio-file on-lock max-duration-ms]}]
[:f>
;; TODO we need to refactor this, and use :f> with defined function, currenly state is reseted each
;; time parent component
@@ -160,6 +176,7 @@
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)
@@ -167,7 +184,6 @@
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)
@@ -178,7 +194,7 @@
rec-options
(merge
audio/default-recorder-options
{:filename (str base-filename (.now js/Date) default-format)
{:filename (str base-filename (datetime/timestamp) default-format)
:meteringInterval metering-interval})
destroy-player
(fn []
@@ -209,13 +225,44 @@
(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
#(log/debug "[record-audio] new recorder - on meter")
recorder-on-meter
#(log/debug "[record-audio] new recorder - on ended"))))
reset-recorder
(fn []
@@ -238,9 +285,6 @@
(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))
@@ -258,7 +302,7 @@
record-button-area)
new-recorder (audio/new-recorder
rec-options
#(log/debug "[record-audio] new recorder - on meter")
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"))
@@ -269,44 +313,13 @@
(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
@@ -424,7 +437,8 @@
(reset! force-show-controls? false)
(when on-send
(on-send {:file-path @output-file
:duration (int (audio/get-player-duration @player-ref))}))
:duration (min max-audio-duration-ms
(int (audio/get-player-duration @player-ref)))}))
(when @player-ref
(audio/stop-playing
@player-ref
@@ -475,8 +489,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?))
@@ -501,8 +515,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: " %)))
@@ -532,11 +546,12 @@
(when @reviewing-audio?
[:<>
[:f> f-play-button playing-audio? player-ref playing-timer audio-current-time-ms
seeking-audio?]
seeking-audio? max-duration-ms]
[:f> soundtrack/f-soundtrack
{:audio-current-time-ms audio-current-time-ms
:player-ref @player-ref
:seeking-audio? seeking-audio?}]])
:seeking-audio? seeking-audio?
:max-audio-duration-ms max-duration-ms}]])
(when (or @recording? @reviewing-audio?)
[:f> f-time-counter @recording? @recording-length-ms @ready-to-delete? @reviewing-audio?
@audio-current-time-ms])
@@ -567,7 +582,6 @@
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?]}]
(let [audio-duration-ms (audio/get-player-duration player-ref)]
[{: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))]
[:<>
[slider/slider
{:test-ID "soundtrack"
@@ -26,4 +26,4 @@
{:data [{:id 1
:label "Item 1"}
]} types/tab])
(h/is-truthy (h/get-by-text "Item 1"))))
(h/is-truthy (h/get-by-text "Item 1"))))
+16 -4
View File
@@ -49,6 +49,8 @@
quo2.components.list-items.preview-list
quo2.components.list-items.user-list
quo2.components.loaders.skeleton
quo2.components.loaders.skeleton.view
quo2.components.markdown.list.view
quo2.components.markdown.text
quo2.components.messages.author.view
quo2.components.messages.gap
@@ -91,7 +93,6 @@
quo2.components.settings.reorder-item.view
quo2.components.community.channel-actions))
(def text quo2.components.markdown.text/text)
(def icon quo2.components.icon/icon)
(def separator quo2.components.separator/separator)
(def header quo2.components.header/header)
@@ -107,12 +108,11 @@
(def group-avatar-tag quo2.components.tags.context-tag.view/group-avatar-tag)
(def audio-tag quo2.components.tags.context-tag.view/audio-tag)
(def community-tag quo2.components.tags.context-tag.view/community-tag)
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
(def page-nav quo2.components.navigation.page-nav/page-nav)
(def disclaimer quo2.components.selectors.disclaimer.view/view)
(def checkbox quo2.components.selectors.selectors.view/checkbox)
(def filter quo2.components.selectors.filter.view/view)
(def skeleton quo2.components.loaders.skeleton/skeleton)
(def author quo2.components.messages.author.view/author)
;;;; SELECTORS
@@ -190,6 +190,18 @@
(def preview-list quo2.components.list-items.preview-list/preview-list)
(def user-list quo2.components.list-items.user-list/user-list)
;;;; LOADERS
(def skeleton quo2.components.loaders.skeleton/skeleton)
(def static-skeleton quo2.components.loaders.skeleton.view/view)
;;;; NAVIGATION
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
(def page-nav quo2.components.navigation.page-nav/page-nav)
;;;; MARKDOWN
(def markdown-list quo2.components.markdown.list.view/view)
(def text quo2.components.markdown.text/text)
;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-log.view/view)
(def info-count quo2.components.notifications.info-count/info-count)
+1
View File
@@ -23,6 +23,7 @@
[quo2.components.links.url-preview-list.component-spec]
[quo2.components.links.url-preview.component-spec]
[quo2.components.markdown.--tests--.text-component-spec]
[quo2.components.markdown.list.component-spec]
[quo2.components.notifications.notification.component-spec]
[quo2.components.onboarding.small-option-card.component-spec]
[quo2.components.password.tips.component-spec]
+4
View File
@@ -121,7 +121,11 @@
(def white-70-blur (alpha white 0.7))
(def neutral-80-opa-1-blur (alpha "#192438" 0.1))
(def neutral-5-opa-70-blur (alpha neutral-5 0.7))
(def neutral-10-opa-10-blur (alpha neutral-10 0.1))
(def neutral-10-opa-40-blur (alpha neutral-10 0.4))
(def neutral-80-opa-80-blur (alpha "#192438" 0.8))
(def neutral-90-opa-10-blur (alpha neutral-90 0.1))
(def neutral-90-opa-40-blur (alpha neutral-90 0.4))
(def neutral-90-opa-70-blur (alpha neutral-90 0.7))
(def neutral-95-opa-70-blur neutral-95-opa-70)
(def neutral-100-opa-70-blur neutral-100-opa-70)
+7
View File
@@ -1,5 +1,6 @@
(ns react-native.cameraroll
(:require ["@react-native-community/cameraroll" :as CameraRoll]
[react-native.fs :as fs]
[utils.transforms :as transforms]
[taoensso.timbre :as log]))
@@ -14,3 +15,9 @@
(-> (.getAlbums CameraRoll (clj->js opts))
(.then #(callback (transforms/js->clj %)))
(.catch #(log/warn "could not get camera roll albums" %))))
(defn save-image
[path]
(-> (.save CameraRoll (clj->js path))
(.then #(fs/unlink path))
(.catch #(fs/unlink path))))
+4
View File
@@ -68,6 +68,10 @@
(fn []
(js->clj (.get (.-Dimensions ^js react-native) "screen") :keywordize-keys true))))
(def small-screen?
(let [height (:height (get-screen))]
(< height 700)))
(defn hw-back-add-listener
[callback]
(.addEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback))
+6
View File
@@ -19,6 +19,8 @@
(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))
@@ -35,6 +37,10 @@
(defn min-distance [gesture dist] (.minDistance ^js gesture dist))
(defn fail-offset-x [gesture offset] (.failOffsetX ^js gesture offset))
(defn hit-slop [gesture settings] (.hitSlop ^js gesture settings))
(defn number-of-taps [gesture count] (.numberOfTaps ^js gesture count))
(defn enabled [gesture enabled?] (.enabled ^js gesture enabled?))
+4
View File
@@ -33,6 +33,10 @@
[comp]
(.showOverlay Navigation (clj->js comp)))
(defn pop-to
[comp]
(.popTo Navigation (clj->js comp)))
(defn pop-to-root
[tab]
(.popToRoot Navigation (clj->js tab)))
+3 -1
View File
@@ -1,5 +1,5 @@
(ns react-native.permissions
(:require ["react-native-permissions" :refer (check requestMultiple PERMISSIONS RESULTS)]
(:require ["react-native-permissions" :refer (check openSettings requestMultiple PERMISSIONS RESULTS)]
[react-native.platform :as platform]))
(def permissions-map
@@ -38,3 +38,5 @@
(-> (check (get permissions-map permission))
(.then #(on-result (not (#{(.-BLOCKED RESULTS) (.-DENIED RESULTS)} %))))
(.catch #(on-error %))))
(def open-settings openSettings)
+3 -1
View File
@@ -34,6 +34,7 @@
(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)))
@@ -80,7 +81,8 @@
{:linear (bezier 0 0 1 1)
:easing1 (bezier 0.25 0.1 0.25 1)
:easing2 (bezier 0 0.3 0.6 0.9)
:easing3 (bezier 0.3 0.3 0.3 0.9)})
:easing3 (bezier 0.3 0.3 0.3 0.9)
:easing4 (bezier 0.3 0.3 1 1)})
;; Helper functions
(defn get-shared-value
+4 -3
View File
@@ -10,7 +10,8 @@
(defn- get-static-bottom
[]
(oops/oget StaticSafeAreaInsets "safeAreaInsetsBottom"))
(some-> StaticSafeAreaInsets
(oops/oget "safeAreaInsetsBottom")))
(defn get-top
[]
@@ -20,8 +21,8 @@
(defn get-bottom
[]
(if platform/ios?
(get-static-bottom)
(if-let [bottom (and platform/ios? (get-static-bottom))]
bottom
0))
(defn get-insets
+12 -12
View File
@@ -22,7 +22,7 @@
(rf/defn fetch
[cofx id]
(let [network (get-in cofx [:db :networks/current-network])]
(get-in cofx [:db :multiaccount :custom-bootnodes network id])))
(get-in cofx [:db :profile/profile :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 [:multiaccount :custom-bootnodes-enabled? network])))
(get-in db [:profile/profile :custom-bootnodes-enabled? network])))
(rf/defn delete
[{{:keys [multiaccount] :as db} :db :as cofx} id]
(let [network (:networks/current-network db)
new-multiaccount (update-in multiaccount [:custom-bootnodes network] dissoc id)]
[{{: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)]
(rf/merge cofx
{:db (assoc db :multiaccount new-multiaccount)}
{:db (assoc db :profile/profile new-profile)}
(multiaccounts.update/multiaccount-update
:custom-bootnodes
(:custom-bootnodes new-multiaccount)
(:custom-bootnodes new-profile)
{: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] :keys [multiaccount] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
[{{:bootnodes/keys [manage] :profile/keys [profile] :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 multiaccount)
(:custom-bootnodes profile)
[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 [:multiaccount :custom-bootnodes-enabled?])]
bootnodes-settings (get-in db [:profile/profile :custom-bootnodes-enabled?])]
(multiaccounts.update/multiaccount-update
cofx
:custom-bootnodes-enabled?
+11 -11
View File
@@ -20,9 +20,9 @@
{:random-id-generator (constantly "some-id")
:db {:bootnodes/manage new-bootnode
:networks/current-network "mainnet_rpc"
:multiaccount {:not-empty
"would throw an error if was empty"}}})]
(is (= expected (get-in actual [:db :multiaccount :custom-bootnodes])))))
:profile/profile {:not-empty
"would throw an error if was empty"}}})]
(is (= expected (get-in actual [:db :profile/profile :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"
:multiaccount {:custom-bootnodes
:profile/profile {:custom-bootnodes
{"mainnet_rpc"
{"a" {:name "name"
:address "url"
:chain "mainnet_rpc"
:id "a"}}}}}})]
(is (= expected (get-in actual [:db :multiaccount :custom-bootnodes]))))))
(is (= expected (get-in actual [:db :profile/profile :custom-bootnodes]))))))
(deftest set-input-bootnode
(testing "it validates names"
@@ -72,7 +72,7 @@
(deftest edit-bootnode
(let [db {:networks/current-network "mainnet_rpc"
:multiaccount
:profile/profile
{: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"
:multiaccount {:custom-bootnodes
:profile/profile {: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"
:multiaccount {:custom-bootnodes-enabled?
:profile/profile {: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"
:multiaccount {:custom-bootnodes-enabled?
:profile/profile {:custom-bootnodes-enabled?
{"mainnnet_rpc" true}}}}))))))
(deftest delete-bootnode
(testing "non existing bootnode"
(let [cofx {:db {:networks/current-network "mainnet_rpc"
:multiaccount {:custom-bootnodes
:profile/profile {: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"
:multiaccount {:custom-bootnodes
:profile/profile {:custom-bootnodes
{"mainnet_rpc"
{"a" {:id "a"
:name "name"
+1 -1
View File
@@ -385,7 +385,7 @@
(rf/defn web3-send-async
[cofx dapp-name {:keys [method params id] :as payload} message-id]
(let [message? (web3-sign-message? method)
dapps-address (get-in cofx [:db :multiaccount :dapps-address])
dapps-address (get-in cofx [:db :profile/profile :dapps-address])
typed? (and (not= constants/web3-personal-sign method)
(not= constants/web3-eth-sign method))]
(if (or message? (= constants/web3-send-transaction method))
+1 -1
View File
@@ -42,7 +42,7 @@
(defn get-permission-data
[cofx allowed-permission]
(let [multiaccount (get-in cofx [:db :multiaccount])]
(let [multiaccount (get-in cofx [:db :profile/profile])]
(get {constants/dapp-permission-contact-code (:public-key multiaccount)
constants/dapp-permission-web3 [(:dapps-address multiaccount)]}
allowed-permission)))
+1 -1
View File
@@ -9,7 +9,7 @@
(let [dapp-name "test.com"
dapp-name2 "test2.org"
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
[:multiaccount :public-key]
[:profile/profile :public-key]
"public-key")}
dapp-id (core.tests/get-dapp-id cofx dapp-name)]
(testing "dapps permissions are initialized"
+8 -23
View File
@@ -1,16 +1,13 @@
(ns status-im.chat.models.images
(:require ["@react-native-community/cameraroll" :as CameraRoll]
["react-native-blob-util" :default ReactNativeBlobUtil]
(:require ["react-native-blob-util" :default ReactNativeBlobUtil]
[re-frame.core :as re-frame]
[react-native.share :as share]
[utils.i18n :as i18n]
[react-native.permissions :as permissions]
[react-native.cameraroll :as cameraroll]
[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"))
@@ -22,7 +19,7 @@
:path temp-image-url}))
(.fetch "GET" base64-uri)
(.then #(on-success (.path %)))
(.catch #(log/error "could not save image"))))
(.catch #(log/error "could not download image" {:error %}))))
(defn share-image
[uri]
@@ -33,23 +30,11 @@
#(fs/unlink downloaded-url)
#(fs/unlink downloaded-url)))))
(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))}))))
(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" %)))))
(re-frame/reg-fx
::chat-open-image-picker-camera
+10 -9
View File
@@ -11,17 +11,18 @@
[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.re-frame :as rf]
[utils.string :as utils.string]))
(defn text->emoji
"Replaces emojis in a specified `text`"
[text]
(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))))
(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))))
;; effects
(re-frame/reg-fx
@@ -147,7 +148,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 [:multiaccount :preferred-name])
preferred-name (get-in db [:profile/profile :preferred-name])
emoji? (message-content/emoji-only-content? {:text input-text
:response-to message-id})]
{:chat-id current-chat-id
@@ -169,7 +170,7 @@
{:chat-id chat-id
:album-id album-id
:content-type constants/content-type-image
:image-path (utils/safe-replace resized-uri #"file://" "")
:image-path (utils.string/safe-replace resized-uri #"file://" "")
:image-width width
:image-height height
:text input-text
+2 -2
View File
@@ -83,7 +83,7 @@
[{db :db} chat-id]
{:db (mark-chat-all-read db chat-id)
:clear-message-notifications [[chat-id]
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
(get-in db [:profile/profile :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 [:multiaccount :remote-push-notifications-enabled?])]
(get-in db [:profile/profile :remote-push-notifications-enabled?])]
:json-rpc/call [{:method "wakuext_markAllReadInCommunity"
:params [community-id]
:on-success #(re-frame/dispatch
+1 -1
View File
@@ -9,7 +9,7 @@
{:db (assoc db
:commands/select-account
{:message message
:from (ethereum/get-default-account (:multiaccount/accounts db))})
:from (ethereum/get-default-account (:profile/wallet-accounts db))})
:show-select-acc-sheet nil})
(rf/defn set-selected-account
+6 -6
View File
@@ -11,7 +11,7 @@
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im2.common.toasts.events :as toasts]
[status-im2.constants :as constants]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.contexts.shell.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 [:multiaccount :public-key])]
(let [my-public-key (get-in db [:profile/profile :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 [:multiaccount :remote-push-notifications-enabled?])]
(get-in db [:profile/profile :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 [:multiaccount :public-key])
(let [public-key (get-in db [:profile/profile :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 [:multiaccount :public-key])
(let [public-key (get-in db [:profile/profile :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 [:multiaccount :public-key])
(let [public-key (get-in db [:profile/profile :public-key])
categories (get-in db [:communities community-id :categories])
{:keys [keys hashes]} (reduce (fn [acc category]
(let [category-id (get category 0)
+2 -2
View File
@@ -6,7 +6,7 @@
[status-im2.contexts.contacts.events :as contacts-store]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[status-im2.contexts.activity-center.events :as activity-center]
[status-im2.contexts.shell.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 [:multiaccount :remote-push-notifications-enabled?])]}
[[public-key] (get-in db [:profile/profile :remote-push-notifications-enabled?])]}
(activity-center/notifications-fetch-unread-count)
fxs)))

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