Compare commits

..
Author SHA1 Message Date
Omar Basem 502718440c draft 2023-03-21 14:09:06 +04:00
Omar Basem f0cbfd7155 updates 2023-03-21 13:40:14 +04:00
Omar Basem 9c49991bae draft 2023-03-21 13:26:12 +04:00
Omar Basem 1b4c65ea97 draft 2023-03-21 13:03:37 +04:00
Omar Basem 41547a70a5 draft 2023-03-21 12:49:00 +04:00
Omar Basem a030046401 draft 2023-03-21 12:32:56 +04:00
Omar Basem 7557e885d0 draft 2023-03-21 12:12:02 +04:00
Omar Basem 06fa981954 draft 2023-03-21 11:38:02 +04:00
Omar Basem 38522e5180 draft 2023-03-21 11:33:58 +04:00
Omar Basem ecba5ade66 lint 2023-03-21 10:54:53 +04:00
Omar Basem c94508e559 remove image delay 2023-03-21 09:05:33 +04:00
188 changed files with 1753 additions and 4638 deletions
+1 -1
View File
@@ -1 +1 @@
1.22.0
1.21.0
-51
View File
@@ -61,57 +61,6 @@ the source file. For a real example, see
[rn/view (do-something)]])
```
### Always add styles inside the `:style` key
Although when compiling ReactNative for mobile some components are able work with
their styles in the top-level of the properties map, prefer to add them inside the
`:style` key in order to separate styles from properties:
```clojure
;; bad
[rn/button {:flex 1
:padding-vertical 10
:padding-horizontal 20
:on-press #(js/alert "Hi!")
:title "Button"}]
;; good
[rn/button {:style {:flex 1
:padding-vertical 10
:padding-horizontal 20}
:on-press #(js/alert "Hi!")
:title "Button"}]
;; better
;; (define them in a style ns & place them inside `:style` key)
[rn/button {:style (style/button)
:on-press #(js/alert "Hi!")
:title "Button"}
]
```
### Always apply animated styles in the style file
When implementing styles for reanimated views, we should always define
them in the style file and apply animations with reanimated/apply-animations-to-style
in the style definition.
```clojure
;; bad
(defn circle
[]
(let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity opacity}
style/circle-container)}]))
;; good
(defn circle
[]
(let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style (style/circle-container opacity)}]))
```
### Don't use percents to define width/height
In ReactNative, all layouts use the [flexbox
-10
View File
@@ -35,16 +35,6 @@ abstract_target 'Status' do
target 'StatusImPR' do
end
post_install do |installer|
# some of libs wouldn't be build for x86_64 otherwise and that is
# necessary for ios simulators
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
end
end
end
use_native_modules!
end
@@ -149,15 +149,11 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
this.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("gethEvent", params);
}
private File getPublicStorageDirectory() {
private File getLogsFile() {
final Context context = this.getReactApplicationContext();
// Environment.getExternalStoragePublicDirectory doesn't work as expected on Android Q
// https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
}
private File getLogsFile() {
final File pubDirectory = this.getPublicStorageDirectory();
final File pubDirectory = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
final File logFile = new File(pubDirectory, gethLogFileName);
return logFile;
@@ -327,30 +323,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
callback.invoke(finalConfig);
}
@ReactMethod
public void createAccountAndLogin(final String createAccountRequest) {
Log.d(TAG, "createAccountAndLogin");
String result = Statusgo.createAccountAndLogin(createAccountRequest);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "createAccountAndLogin success: " + result);
Log.d(TAG, "Geth node started");
} else {
Log.e(TAG, "createAccountAndLogin failed: " + result);
}
}
@ReactMethod
public void restoreAccountAndLogin(final String restoreAccountRequest) {
Log.d(TAG, "restoreAccountAndLogin");
String result = Statusgo.restoreAccountAndLogin(restoreAccountRequest);
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "restoreAccountAndLogin success: " + result);
Log.d(TAG, "Geth node started");
} else {
Log.e(TAG, "restoreAccountAndLogin failed: " + result);
}
}
@ReactMethod
public void saveAccountAndLogin(final String multiaccountData, final String password, final String settings, final String config, final String accountsData) {
try {
@@ -548,8 +520,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
return;
}
Log.d(TAG, "[Opening accounts" + rootDir);
Runnable r = new Runnable() {
@Override
public void run() {
@@ -815,10 +785,9 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
@ReactMethod
public void getConnectionStringForBootstrappingAnotherDevice(final String configJSON, final Callback callback) throws JSONException {
final JSONObject jsonConfig = new JSONObject(configJSON);
final JSONObject senderConfig = jsonConfig.getJSONObject("senderConfig");
final String keyUID = senderConfig.getString("keyUID");
final String keyUID = jsonConfig.getString("keyUID");
final String keyStorePath = this.getKeyStorePath(keyUID);
senderConfig.put("keystorePath", keyStorePath);
jsonConfig.put("keystorePath", keyStorePath);
executeRunnableStatusGoMethod(() -> Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString()), callback);
}
@@ -826,10 +795,9 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
@ReactMethod
public void inputConnectionStringForBootstrapping(final String connectionString, final String configJSON, final Callback callback) throws JSONException {
final JSONObject jsonConfig = new JSONObject(configJSON);
final JSONObject receiverConfig = jsonConfig.getJSONObject("receiverConfig");
final String keyStorePath = pathCombine(this.getNoBackupDirectory(), "/keystore");
receiverConfig.put("keystorePath", keyStorePath);
receiverConfig.getJSONObject("nodeConfig").put("rootDataDir", this.getNoBackupDirectory());
jsonConfig.put("keystorePath", keyStorePath);
jsonConfig.put("rootDataDir", this.getNoBackupDirectory());
executeRunnableStatusGoMethod(() -> Statusgo.inputConnectionStringForBootstrapping(connectionString, jsonConfig.toString()), callback);
}
@@ -1161,23 +1129,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
executeRunnableStatusGoMethod(() -> Statusgo.deleteImportedKey(address, password, keyStoreDir), callback);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String keystoreDir() {
final String absRootDirPath = this.getNoBackupDirectory();
return pathCombine(absRootDirPath, "keystore");
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String backupDisabledDataDir() {
return this.getNoBackupDirectory();
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String logFileDirectory() {
return getPublicStorageDirectory().getAbsolutePath();
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String generateAlias(final String seed) {
return Statusgo.generateAlias(seed);
@@ -309,14 +309,12 @@ RCT_EXPORT_METHOD(getConnectionStringForBootstrappingAnotherDevice:(NSString *)c
callback:(RCTResponseSenderBlock)callback) {
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *senderConfig = configDict[@"senderConfig"];
NSString *keyUID = senderConfig[@"keyUID"];
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
NSString *keyUID = [configDict objectForKey:@"keyUID"];
NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID];
NSString *keystoreDir = multiaccountKeystoreDir.path;
[senderConfig setValue:keystoreDir forKey:@"keystorePath"];
[configDict setValue:keystoreDir forKey:@"keystorePath"];
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
NSString *result = StatusgoGetConnectionStringForBootstrappingAnotherDevice(modifiedConfigJSON);
@@ -328,20 +326,17 @@ RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs
callback:(RCTResponseSenderBlock)callback) {
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *receiverConfig = configDict[@"receiverConfig"];
NSMutableDictionary *nodeConfig = receiverConfig[@"nodeConfig"];
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *rootDataDir = rootUrl.path;
NSURL *multiaccountKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSString *keystoreDir = multiaccountKeystoreDir.path;
NSString *rootDataDir = rootUrl.path;
[receiverConfig setValue:keystoreDir forKey:@"keystorePath"];
[nodeConfig setValue:rootDataDir forKey:@"rootDataDir"];
[configDict setValue:keystoreDir forKey:@"keystorePath"];
[configDict setValue:rootDataDir forKey:@"rootDataDir"];
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
NSString *result = StatusgoInputConnectionStringForBootstrapping(cs, modifiedConfigJSON);
NSString *result = StatusgoInputConnectionStringForBootstrapping(cs,modifiedConfigJSON);
callback(@[result]);
}
@@ -862,34 +857,6 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(generateAlias:(NSString *)publicKey) {
return StatusgoGenerateAlias(publicKey);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(keystoreDir) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
return commonKeystoreDir.path;
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(backupDisabledDataDir) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
return rootUrl.path;
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(logFileDirectory) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager
URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]
lastObject];
return rootUrl.path;
}
RCT_EXPORT_METHOD(generateAliasAsync:(NSString *)publicKey
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
@@ -967,20 +934,6 @@ RCT_EXPORT_METHOD(identiconAsync:(NSString *)publicKey
callback(@[result]);
}
RCT_EXPORT_METHOD(createAccountAndLogin:(NSString *)request) {
#if DEBUG
NSLog(@"createAccountAndLogin() method called");
#endif
StatusgoCreateAccountAndLogin(request);
}
RCT_EXPORT_METHOD(restoreAccountAndLogin:(NSString *)request) {
#if DEBUG
NSLog(@"restoreAccountAndLogin() method called");
#endif
StatusgoRestoreAccountAndLogin(request);
}
RCT_EXPORT_METHOD(generateAliasAndIdenticonAsync:(NSString *)publicKey
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
+25 -25
View File
@@ -11572,57 +11572,57 @@
},
{
"path": "org/slf4j/jcl-over-slf4j/2.0.7",
"path": "org/slf4j/jcl-over-slf4j/2.0.6",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"jcl-over-slf4j-2.0.7.pom": {
"sha1": "15536e4a74a7aa317322a3d7814db8251de60d6f",
"sha256": "1rzjwbmzf2hb85j6c41mch803vqwqdq1rfrrirfhp1lfpfnzyd23"
"jcl-over-slf4j-2.0.6.pom": {
"sha1": "c9d9caedcca2a1564e47b55614960958c5f78773",
"sha256": "1swgy5hwv54b1i1117shn3wmwba3v78qvy6cnv8v243j7ac6vzqq"
},
"jcl-over-slf4j-2.0.7.jar": {
"sha1": "f127fe5ee53404a8b3697cdd032dd1dd6a29dd77",
"sha256": "0hhpc2qdl4aa9mb8dk89wzbd5vkna557vjmjdmfswvfjw5bng021"
"jcl-over-slf4j-2.0.6.jar": {
"sha1": "839ff57e112f2e28ef372e96d135696a6896b9ad",
"sha256": "0s9scdwkxwj3al87ihanj10rscrjh44kligr5asb7qpl28d1xvks"
}
}
},
{
"path": "org/slf4j/slf4j-api/2.0.7",
"path": "org/slf4j/slf4j-api/2.0.6",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"slf4j-api-2.0.7.pom": {
"sha1": "facf002401dbff2065d4257690651e3fa775e3f4",
"sha256": "10br4q2w50fn3mkvk1xji81wdpy86cm0wyv6m30xa0ha1v7kqh1d"
"slf4j-api-2.0.6.pom": {
"sha1": "2b93d5f66ad2ba259bf4b2c94da39f0d6c544400",
"sha256": "0dipzawn8rxikciij2z06c25rb2vdj83s8ga3a7n10r77p2qcklb"
},
"slf4j-api-2.0.7.jar": {
"sha1": "41eb7184ea9d556f23e18b5cb99cad1f8581fc00",
"sha256": "1x26v62ypzpp84yfad8mx53llbacq6580y34v8nc618r7awrhqjx"
"slf4j-api-2.0.6.jar": {
"sha1": "88c40d8b4f33326f19a7d3c0aaf2c7e8721d4953",
"sha256": "1nkv0z4dpkvp6pr9ph8087z5r691bv95xdv3gnfi6s5j23a94aig"
}
}
},
{
"path": "org/slf4j/slf4j-jdk14/2.0.7",
"path": "org/slf4j/slf4j-jdk14/2.0.6",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"slf4j-jdk14-2.0.7.pom": {
"sha1": "31039eac9f263c48bda14efd90aef0fb7a5a0e6a",
"sha256": "1vx1ziyx36zf2lrpkvvm4c75hp8pw8vjpiyr5120ss8nwpd33qal"
"slf4j-jdk14-2.0.6.pom": {
"sha1": "96ac9d6ab608e787d54892b35205bc6a560aa007",
"sha256": "0gnsyy1n5v8xqdy6a6p1752m5c4afihpw0n36n6aqw01y9l86q1h"
},
"slf4j-jdk14-2.0.7.jar": {
"sha1": "d91cd16b55ffbd5f46c60d0173fd4eeccacfee2d",
"sha256": "1xvphj12jpnvr1sw8zx42p49in4xi61mjvpxrkk3q3qpyad7017r"
"slf4j-jdk14-2.0.6.jar": {
"sha1": "13056cb341f2d8795120f8027766a058da874f85",
"sha256": "0jncm8a2ppliqpzkbqm26sn98mwif8c1nligc1zh4jbzr8mxyzhy"
}
}
},
{
"path": "org/slf4j/slf4j-parent/2.0.7",
"path": "org/slf4j/slf4j-parent/2.0.6",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"slf4j-parent-2.0.7.pom": {
"sha1": "3f97e066227cc2353d212b8c43440b0bf4c033f3",
"sha256": "1rs55v9gqda5lks89dd81frps5c9g3zgxk832qyckw9srlvbp0n1"
"slf4j-parent-2.0.6.pom": {
"sha1": "0f99f8426c64fc5e0c4b6749245e50484a16c372",
"sha256": "091il49sidk0lcmzdy0vl3a4l16kw6x1q0l9vk0hir1ipq66b0hl"
}
}
},
+4 -4
View File
@@ -802,9 +802,9 @@ https://repo.maven.apache.org/maven2/org/ow2/asm/asm/6.0/asm-6.0.pom
https://repo.maven.apache.org/maven2/org/ow2/asm/asm/9.4/asm-9.4.pom
https://repo.maven.apache.org/maven2/org/ow2/ow2/1.3/ow2-1.3.pom
https://repo.maven.apache.org/maven2/org/ow2/ow2/1.5.1/ow2-1.5.1.pom
https://repo.maven.apache.org/maven2/org/slf4j/jcl-over-slf4j/2.0.7/jcl-over-slf4j-2.0.7.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/2.0.7/slf4j-api-2.0.7.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-jdk14/2.0.7/slf4j-jdk14-2.0.7.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/2.0.7/slf4j-parent-2.0.7.pom
https://repo.maven.apache.org/maven2/org/slf4j/jcl-over-slf4j/2.0.6/jcl-over-slf4j-2.0.6.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/2.0.6/slf4j-api-2.0.6.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-jdk14/2.0.6/slf4j-jdk14-2.0.6.pom
https://repo.maven.apache.org/maven2/org/slf4j/slf4j-parent/2.0.6/slf4j-parent-2.0.6.pom
https://repo.maven.apache.org/maven2/org/sonatype/oss/oss-parent/7/oss-parent-7.pom
https://repo.maven.apache.org/maven2/org/sonatype/oss/oss-parent/9/oss-parent-9.pom
+3 -3
View File
@@ -29,17 +29,17 @@ function findPackage(line, regex) {
if (line ~ "com.facebook.react:react-native") { continue }
# Example: +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50
if (findPackage(line, "--- ([^ :]+):([^ :]+):([^ :]+)$")) {
if (findPackage(line, "--- ([^:]+):([^:]+):([^ ]+)$")) {
continue
}
# Example: +--- androidx.lifecycle:lifecycle-common:{strictly 2.0.0} -> 2.0.0 (c)
if (findPackage(line, "--- ([^ :]+):([^ :]+):[^:]+ -> ([^ :]+) ?(\\([*c]\\))?$")) {
if (findPackage(line, "--- ([^:]+):([^:]+):[^ ]+ -> ([^: ]+) ?(\\([*c]\\))?$")) {
continue
}
# Example: +--- com.android.support:appcompat-v7:28.0.0 -> androidx.appcompat:appcompat:1.0.2
if (findPackage(line, "--- [^ :]+:[^ :]+:[^ ]+ -> ([^ :]+):([^ :]+):([^ :]+)$")) {
if (findPackage(line, "--- [^:]+:[^:]+:[^ ]+ -> ([^:]+):([^:]+):([^ ]+)$")) {
continue
}
}
+2 -2
View File
@@ -46,8 +46,8 @@ in {
# Package version adjustments
gradle = super.gradle_5;
nodejs = super.nodejs-18_x;
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
nodejs = super.nodejs-16_x;
yarn = super.yarn.override { nodejs = super.nodejs-16_x; };
openjdk = super.openjdk8_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
version = "13.3";
+1 -8
View File
@@ -42,19 +42,12 @@ let
# for running gradle by hand
gradle = mkShell {
buildInputs = with pkgs; [ gradle maven goMavenResolver ];
inputsFrom = [ nodejs-sh ];
shellHook = ''
export STATUS_GO_ANDROID_LIBDIR="DUMMY"
export STATUS_NIX_MAVEN_REPO="${pkgs.deps.gradle}"
export ANDROID_SDK_ROOT="${pkgs.androidPkgs.sdk}"
export ANDROID_NDK_ROOT="${pkgs.androidPkgs.ndk}"
export STATUS_MOBILE_HOME=$(git rev-parse --show-toplevel)
# WARNING: Unpatched Node.js deps allow Gradle to use remote repos.
"$STATUS_MOBILE_HOME/nix/scripts/node_modules.sh" ${pkgs.deps.nodejs}
function restore_patched_modules() {
"$STATUS_MOBILE_HOME/nix/scripts/node_modules.sh" ${pkgs.deps.nodejs-patched}
}
trap restore_patched_modules EXIT
'';
};
+1 -1
View File
@@ -19,7 +19,7 @@
"@babel/preset-typescript": "^7.17.12",
"@react-native-async-storage/async-storage": "^1.17.9",
"@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#refs/tags/v2.0.3-status-v6",
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.2-status",
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.1-status",
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.0",
"@react-native-community/clipboard": "^1.2.2",
"@react-native-community/hooks": "^2.5.1",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 MiB

+1 -7
View File
@@ -45,13 +45,7 @@
:devtools {:autobuild #shadow/env ["SHADOW_AUTOBUILD_ENABLED" :default true :as :bool]}
:dev {:devtools {:after-load status-im2.setup.hot-reload/reload
:build-notify status-im2.setup.hot-reload/build-notify
:preloads [re-frisk-remote.preload
;; In order to use component test helpers in
;; the REPL we need to preload namespaces
;; that are not normally required by
;; production code, such as
;; @testing-library/react-native.
test-helpers.component]}
:preloads [re-frisk-remote.preload]}
:closure-defines
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"}
-47
View File
@@ -1,47 +0,0 @@
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300;
const easeOut = {
duration: slideAnimationDuration,
easing: Easing.bezier(0, 0, 0.58, 1),
}
// Derived Values
export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
return useDerivedValue(
function () {
'worklet'
return staticProgressBarWidth * (progress.value || 0) / 100;
}
);
}
export function carouselLeftPosition(windowWidth, progress) {
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;
}
});
}
+1 -6
View File
@@ -293,10 +293,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
:createNativeWrapper identity
:default #js {}})
(def react-native-redash
#js
{:clamp nil
:withPause (fn [])})
(def react-native-redash #js {:clamp nil})
(def react-native-languages
(clj->js {:default {:language "en"
@@ -373,7 +370,6 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
"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
@@ -411,7 +407,6 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
"../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 {}
"./fleets.js" default-fleets
"@walletconnect/client" wallet-connect-client
@@ -58,18 +58,6 @@
(h/test "Size :small"
(h/render (user-avatar-component :small))
(h/is-truthy (h/get-by-text "NU")))
(h/test "Two letters with excess whitespace"
(h/render [user-avatar/user-avatar
{:full-name "New User"
:size :big}])
(h/is-truthy (h/get-by-text "NU")))
(h/test "Two letters with leading whitespace"
(h/render [user-avatar/user-avatar
{:full-name " New User"
:size :big}])
(h/is-truthy (h/get-by-text "NU"))))
(h/describe "One letter"
@@ -5,18 +5,14 @@
[react-native.core :as rn]
[react-native.fast-image :as fast-image]))
(defn trim-whitespace [s] (string/join " " (string/split (string/trim s) #"\s+")))
(defn- extract-initials
[full-name amount-initials]
(let [upper-case-first-letter (comp string/upper-case first)
names-list (string/split (trim-whitespace full-name) " ")]
(if (= (first names-list) "")
""
(->> names-list
(map upper-case-first-letter)
(take amount-initials)
(string/join)))))
names-list (string/split full-name " ")]
(->> names-list
(map upper-case-first-letter)
(take amount-initials)
(string/join))))
(defn initials-avatar
[{:keys [full-name size draw-ring? customization-color]}]
+16 -14
View File
@@ -6,13 +6,12 @@
[react-native.core :as rn]
[reagent.core :as reagent]))
(defn themes
[customization-color]
(def themes
{:light {:primary {:icon-color colors/white
:label-color colors/white
:background-color {:default (colors/custom-color customization-color 50)
:pressed (colors/custom-color customization-color 60)
:disabled (colors/custom-color customization-color 50)}}
:background-color {:default colors/primary-50
:pressed colors/primary-60
:disabled colors/primary-50}}
:secondary {:icon-color colors/primary-50
:label-color colors/primary-50
:background-color {:default colors/primary-50-opa-20
@@ -75,9 +74,9 @@
:disabled colors/neutral-95}}}
:dark {:primary {:icon-color colors/white
:label-color colors/white
:background-color {:default (colors/custom-color customization-color 60)
:pressed (colors/custom-color customization-color 50)
:disabled (colors/custom-color customization-color 60)}}
:background-color {:default colors/primary-60
:pressed colors/primary-50
:disabled colors/primary-60}}
:secondary {:icon-color colors/primary-50
:label-color colors/primary-50
:background-color {:default colors/primary-50-opa-20
@@ -219,15 +218,14 @@
(let [pressed (reagent/atom false)]
(fn
[{:keys [on-press disabled type size community-color community-text-color before after above
width customization-color
width
override-theme override-background-color
on-long-press accessibility-label icon icon-no-color style inner-style test-ID]
:or {type :primary
size 40
customization-color :primary}}
:or {type :primary
size 40}}
children]
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color]}
(get-in (themes customization-color)
(get-in themes
[(or
override-theme
(theme/get-theme)) type])
@@ -254,7 +252,11 @@
[rn/view
{:style (merge
(shape-style-container type icon size)
{:width width}
{:background-color
(if (= state :pressed)
(colors/theme-colors colors/neutral-100 colors/white)
:transparent)
:width width}
style)}
[rn/view
{:style (merge
@@ -16,13 +16,15 @@
:height 230
:border-radius 20}
:on-press on-press}
[rn/view {:style style/detail-container}
[rn/view
{:flex 1}
[rn/view (style/community-cover-container 60)
[rn/image
{:source cover
:style {:flex 1
:border-top-right-radius 20
:border-top-left-radius 20}}]]
:style
{:flex 1
:border-top-right-radius 20
:border-top-left-radius 20}}]]
[rn/view (style/card-view-content-container 12)
[rn/view (style/card-view-chat-icon 48)
[icon/community-icon {:images images} 48]]
@@ -36,7 +38,7 @@
{:title name
:description description}]
[rn/view {:style (style/card-stats-position)}
[community-view/community-stats-column
{:type :card-view}]]
[community-view/community-stats-column :card-view]]
[rn/view {:style (style/community-tags-position)}
[community-view/community-tags tags]]]]]]])
@@ -46,7 +46,7 @@
(merge {:style {:height 56
:border-radius 16}}
props)
[rn/view {:style style/detail-container}
[rn/view {:flex 1}
[rn/view (style/list-info-container)
[community-icon/community-icon
{:images community-icon} 32]
@@ -64,8 +64,7 @@
colors/neutral-40
colors/neutral-60))}}
name]
[community-view/community-stats-column
{:type :list-view}]]
[community-view/community-stats-column :list-view]]
(if (= status :gated)
[community-view/permission-tag-container
{:locked? locked?
@@ -5,7 +5,6 @@
[quo2.components.tags.permission-tag :as permission]
[quo2.components.tags.tag :as tag]
[quo2.foundations.colors :as colors]
[quo.gesture-handler :as gesture-handler] ;;TODO move to quo2
[react-native.core :as rn]))
(defn community-stats
@@ -24,7 +23,7 @@
members-count]])
(defn community-stats-column
[{:keys [type]}]
[type]
(let [icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)]
[rn/view
(if (= type :card-view)
@@ -42,9 +41,7 @@
(defn community-tags
[tags]
[gesture-handler/scroll-view
{:shows-horizontal-scroll-indicator false
:horizontal true}
[rn/view (style/community-tags-container)
(for [{:keys [name emoji]} tags]
^{:key name}
[rn/view {:margin-right 8}
+5 -4
View File
@@ -22,9 +22,6 @@
colors/white
colors/neutral-90)})
(def detail-container
{:flex 1})
(defn stats-count-container
[]
{:flex-direction :row
@@ -40,6 +37,10 @@
{:flex-direction :row
:align-items :center})
(defn community-tags-container
[]
{:flex-direction :row})
(defn card-stats-position
[]
{:position :absolute
@@ -61,7 +62,7 @@
:bottom 0
:left 0
:right 0
:border-radius 20
:height 20
:padding-horizontal padding-horizontal
:border-top-right-radius 16
:border-top-left-radius 16
@@ -1,10 +1,7 @@
(ns quo2.components.drawers.drawer-buttons.style
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(:require [quo2.foundations.colors :as colors]))
(def outer-container
{:height 216
:border-radius 20})
(def outer-container {:height 216})
(def top-card
{:flex 1
@@ -12,9 +9,7 @@
:padding-horizontal 20
:border-top-left-radius 20
:border-top-right-radius 20
:background-color (if platform/ios?
colors/neutral-80-opa-80-blur
colors/neutral-80)})
:background-color colors/neutral-80})
(def bottom-card
{:position :absolute
@@ -26,7 +21,7 @@
:padding-horizontal 20
:border-top-left-radius 20
:border-top-right-radius 20
:background-color colors/white-opa-5})
:background-color (colors/alpha colors/white 0.05)})
(def bottom-container
{:flex-direction :row
@@ -40,14 +35,14 @@
:width 28
:justify-content :center
:align-items :center
:border-color colors/white-opa-5})
:border-color (colors/alpha colors/white 0.05)})
(def bottom-text
{:flex 1
:color colors/white-70-blur})
:color (colors/alpha colors/white 0.7)})
(def top-text
{:color colors/white-70-blur})
{:color (colors/alpha colors/white 0.7)})
(defn heading-text
[gap]
@@ -3,7 +3,6 @@
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[quo2.components.drawers.drawer-buttons.style :as style]))
(defn render-bottom
@@ -71,7 +70,7 @@
child-2 string, keyword or hiccup
"
[{:keys [container-style top-card bottom-card]} child-1 child-2]
[blur/ios-view
[rn/view
{:style (merge container-style style/outer-container)}
[card
(merge {:gap 4
+4 -4
View File
@@ -22,18 +22,18 @@
opts
{:type :default/:success/:error
:size :default/:tiny
:icon :i/info ;; info message icon
:icon :main-icons/info ;; info message icon
:text-color colors/white ;; text color override
:icon-color colors/white ;; icon color override
:no-icon-color? false ;; disable tint color for icon"
[{:keys [type size icon text-color icon-color no-icon-color? style]} message]
[{:keys [type size icon text-color icon-color no-icon-color?]} message]
(let [weight (if (= size :default) :regular :medium)
size (if (= size :default) :paragraph-2 :label)
text-color (or text-color (get-color type))
icon-color (or icon-color text-color)]
[rn/view
{:style (merge {:flex-direction :row}
style)}
{:style {:flex-direction :row
:flex 1}}
[quo2.icons/icon icon
{:color icon-color
:no-color no-icon-color?
@@ -1,70 +0,0 @@
(ns quo2.components.inputs.input.component-spec
(:require [quo2.components.inputs.input.view :as input]
[test-helpers.component :as h]))
(h/describe "Input"
(h/test "default render"
(h/render [input/input])
(h/is-truthy (h/query-by-label-text :input))
(h/is-null (h/query-by-label-text :password-input)))
(h/test "Password type"
(h/render [input/input {:type :password}])
(h/is-truthy (h/query-by-label-text :password-input))
(h/is-null (h/query-by-label-text :input)))
(h/describe "Icon"
(h/test "Doesn't exist in base input"
(h/render [input/input])
(h/is-null (h/query-by-label-text :input-icon)))
(h/test "Renders"
(h/render [input/input {:icon-name :i/placeholder}])
(h/is-truthy (h/get-by-label-text :input-icon))))
(h/describe "Right accessory"
(h/test "Doesn't exist in base input"
(h/render [input/input])
(h/is-null (h/query-by-label-text :input-right-icon)))
(h/test "Clear icon"
(h/render [input/input {:clearable? true}])
(h/is-truthy (h/query-by-label-text :input-right-icon)))
(h/test "Password icon"
(h/render [input/input {:type :password}])
(h/is-truthy (h/query-by-label-text :input-right-icon))))
(h/describe "Button"
(h/test "Doesn't exist in base input"
(h/render [input/input])
(h/is-null (h/query-by-label-text :input-button)))
(h/test "Renders with given text and it's pressable"
(let [button-text "This is a button"
button-callback (h/mock-fn)]
(h/render [input/input
{:button {:on-press button-callback
:text button-text}}])
(h/is-truthy (h/query-by-label-text :input-button))
(h/is-truthy (h/get-by-text button-text))
(h/fire-event :press (h/query-by-label-text :input-button))
(h/was-called button-callback))))
(h/describe "Label"
(h/test "Doesn't exist in base input"
(h/render [input/input])
(h/is-null (h/query-by-label-text :input-labels)))
(h/test "Renders with specified text"
(let [input-label "My label"]
(h/render [input/input {:label input-label}])
(h/is-truthy (h/query-by-label-text :input-labels))
(h/is-truthy (h/get-by-text input-label)))))
(h/test "Char limit counter"
(let [char-limit 100
char-limit-str (str "0/" char-limit)]
(h/render [input/input {:char-limit char-limit}])
(h/is-truthy (h/query-by-label-text :input-labels))
(h/is-truthy (h/get-by-text char-limit-str)))))
+12 -11
View File
@@ -66,7 +66,7 @@
:padding-horizontal 8
:border-width 1
:border-color (:border-color colors-by-status)
:border-radius (if small? 10 12)
:border-radius (if small? 10 14)
:opacity (if disabled? 0.3 1)})
(defn left-icon-container
@@ -83,15 +83,15 @@
(defn input
[colors-by-status small? multiple-lines?]
(let [base-props (assoc (text/text-style {:size :paragraph-1 :weight :regular})
:flex 1
:padding-right 0
:padding-left (if small? 4 8)
:padding-vertical (if small? 4 8)
:color (:text colors-by-status))]
(if multiple-lines?
(assoc base-props :text-align-vertical :top)
(assoc base-props :height (if small? 30 38) :line-height nil))))
(merge (text/text-style {:size :paragraph-1 :weight :regular})
{:flex 1
:text-align-vertical :top
:padding-right 0
:padding-left (if small? 4 8)
:padding-vertical (if small? 4 8)
:color (:text colors-by-status)}
(when-not multiple-lines?
{:height (if small? 30 38)})))
(defn right-icon-touchable-area
[small?]
@@ -110,7 +110,8 @@
:color (:clear-icon variant-colors)})
(def texts-container
{:flex-direction :row
{:flex 1
:flex-direction :row
:height 18
:margin-bottom 8})
+22 -34
View File
@@ -9,9 +9,7 @@
(defn- label-&-counter
[{:keys [label current-chars char-limit variant-colors]}]
(let [count-text (when char-limit (str current-chars "/" char-limit))]
[rn/view
{:accessibility-label :input-labels
:style style/texts-container}
[rn/view {:style style/texts-container}
[rn/view {:style style/label-container}
[text/text
{:style (style/label-color variant-colors)
@@ -27,40 +25,36 @@
(defn- left-accessory
[{:keys [variant-colors small? icon-name]}]
[rn/view
{:accessibility-label :input-icon
:style (style/left-icon-container small?)}
[rn/view {:style (style/left-icon-container small?)}
[icon/icon icon-name (style/icon variant-colors)]])
(defn- right-accessory
[{:keys [variant-colors small? disabled? on-press icon-style-fn icon-name]}]
[rn/touchable-opacity
{:accessibility-label :input-right-icon
:style (style/right-icon-touchable-area small?)
:disabled disabled?
:on-press on-press}
{:style (style/right-icon-touchable-area small?)
:disabled disabled?
:on-press on-press}
[icon/icon icon-name (icon-style-fn variant-colors)]])
(defn- right-button
[{:keys [variant-colors colors-by-status small? disabled? on-press text]}]
[rn/touchable-opacity
{:accessibility-label :input-button
:style (style/button variant-colors small?)
:disabled disabled?
:on-press on-press}
{:style (style/button variant-colors small?)
:disabled disabled?
:on-press on-press}
[rn/text {:style (style/button-text colors-by-status)}
text]])
(def ^:private custom-props
"Custom properties that must be removed from properties map passed to InputText."
[:type :blur? :override-theme :error? :right-icon :left-icon :disabled? :small? :button
:label :char-limit :on-char-limit-reach :icon-name :multiline? :on-focus :on-blur])
:label :char-limit :on-char-limit-reach :icon-name :multiline?])
(defn- base-input
[{:keys [on-change-text on-char-limit-reach]}]
(let [status (reagent/atom :default)
internal-on-focus #(reset! status :focus)
internal-on-blur #(reset! status :default)
on-focus #(reset! status :focus)
on-blur #(reset! status :default)
multiple-lines? (reagent/atom false)
set-multiple-lines! #(let [height (oops/oget % "nativeEvent.contentSize.height")]
(if (> height 57)
@@ -74,7 +68,7 @@
(when (>= amount-chars char-limit)
(on-char-limit-reach amount-chars))))]
(fn [{:keys [blur? override-theme error? right-icon left-icon disabled? small? button
label char-limit multiline? clearable? on-focus on-blur]
label char-limit multiline? clearable?]
:as props}]
(let [status-kw (cond
disabled? :disabled
@@ -83,7 +77,7 @@
colors-by-status (style/status-colors status-kw blur? override-theme)
variant-colors (style/variants-colors blur? override-theme)
clean-props (apply dissoc props custom-props)]
[:<>
[rn/view
(when (or label char-limit)
[label-&-counter
{:variant-colors variant-colors
@@ -98,16 +92,11 @@
:icon-name icon-name}])
[rn/text-input
(cond-> {:style (style/input colors-by-status small? @multiple-lines?)
:accessibility-label :input
:placeholder-text-color (:placeholder colors-by-status)
:cursor-color (:cursor variant-colors)
:editable (not disabled?)
:on-focus (fn []
(when on-focus (on-focus))
(internal-on-focus))
:on-blur (fn []
(when on-blur (on-blur))
(internal-on-blur))}
:on-focus on-focus
:on-blur on-blur}
:always (merge clean-props)
multiline? (assoc :multiline true
:on-content-size-change set-multiple-lines!)
@@ -137,13 +126,12 @@
(fn [props]
[base-input
(assoc props
:accessibility-label :password-input
:auto-capitalize :none
:auto-complete :new-password
:secure-text-entry (not @password-shown?)
:right-icon {:style-fn style/password-icon
:icon-name (if @password-shown? :i/hide :i/reveal)
:on-press #(swap! password-shown? not)})])))
:auto-capitalize :none
:auto-complete :new-password
:secure-text-entry (not @password-shown?)
:right-icon {:style-fn style/password-icon
:icon-name (if @password-shown? :i/hide :i/reveal)
:on-press #(swap! password-shown? not)})])))
(defn input
"This input supports the following properties:
@@ -158,7 +146,7 @@
- :clearable? - Booolean to specify if this input has a clear button at the end.
- :on-clear - Function executed when the clear button is pressed.
- :button - Map containing `:on-press` & `:text` keys, if provided renders a button
- :label - A string to set as label for this input.
- :label - A label for this input.
- :char-limit - A number to set a maximum char limit for this input.
- :on-char-limit-reach - Function executed each time char limit is reached or exceeded.
and supports the usual React Native's TextInput properties to control its behaviour:
@@ -6,7 +6,6 @@
[quo2.components.inputs.title-input.view :as title-input]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.hole-view :as hole-view]))
(defn profile-input
@@ -19,29 +18,20 @@
[rn/view
{:style (style/container customization-color)}
[rn/view
(if platform/ios?
[hole-view/hole-view
{:holes [{:x 33
:y 23
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(assoc image-picker-props
:customization-color customization-color
:full-name (if (seq full-name)
full-name
placeholder)
:status-indicator? false
:size :medium)]]
[user-avatar/user-avatar
(assoc image-picker-props
:customization-color customization-color
[hole-view/hole-view
{:holes [{:x 33
:y 23
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(merge image-picker-props
{:customization-color customization-color
:full-name (if (seq full-name)
full-name
placeholder)
:status-indicator? false
:size :medium)])
:size :medium})]]
[buttons/button
{:accessibility-label :select-profile-picture-button
:type :grey
@@ -57,7 +47,5 @@
[rn/view {:style style/input-container}
[title-input/title-input
(merge title-input-props
{:blur? true
:override-theme :dark
:placeholder placeholder
{:placeholder placeholder
:customization-color customization-color})]]]))
@@ -2,48 +2,45 @@
(:require [quo2.foundations.colors :as colors]))
(defn get-focused-placeholder-color
[blur? override-theme]
[blur?]
(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/alpha colors/white 0.2))
(colors/theme-colors colors/neutral-30 colors/neutral-60)))
(defn get-placeholder-color
[blur? override-theme]
[blur?]
(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/alpha colors/white 0.3))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(defn- get-disabled-color
[blur? override-theme]
[blur?]
(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-80-opa-40 (colors/alpha colors/white 0.3))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(defn- get-char-count-color
[blur? override-theme]
[blur?]
(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-80-opa-40 (colors/alpha colors/white 0.4))
(colors/theme-colors colors/neutral-40 colors/neutral-50)))
(defn get-selection-color
[customization-color blur? override-theme]
[customization-color blur?]
(if blur?
(colors/theme-colors colors/neutral-100 colors/white override-theme)
(colors/custom-color customization-color (if (or (= :dark override-theme) colors/dark?) 60 50))))
(colors/theme-colors colors/neutral-100 colors/white)
(colors/custom-color customization-color (if colors/dark? 60 50))))
(def text-input-container {:flex 1})
(defn title-text
[disabled? blur? override-theme]
[disabled? blur?]
{:text-align-vertical :bottom
:color (if disabled?
(get-disabled-color blur? override-theme)
(colors/theme-colors colors/neutral-100 colors/white override-theme))})
:color (when disabled? (get-disabled-color blur?))})
(defn char-count
[blur? override-theme]
{:color (get-char-count-color blur? override-theme)})
[blur?]
{:color (get-char-count-color blur?)})
(def container
{:flex-direction :row
@@ -16,8 +16,7 @@
on-change-text
placeholder
max-length
default-value
override-theme]
default-value]
:or {max-length 0
default-value ""}}]
(let [focused? (reagent/atom false)
@@ -35,7 +34,7 @@
(text/text-style
{:size :heading-2
:weight :semi-bold
:style (style/title-text disabled? blur? override-theme)})
:style (style/title-text disabled? blur?)})
:default-value default-value
:accessibility-label :profile-title-input
:on-focus #(swap! focused? (fn [] true))
@@ -45,21 +44,21 @@
: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?)
: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?)
(style/get-placeholder-color blur?))}]]
[rn/view
{:style style/counter-container}
[text/text
[text/text
{:style (style/char-count blur? override-theme)
{:style (style/char-count blur?)
:size :paragraph-2}
(pad-0
(str
(count @value)))]
[text/text
{:style (style/char-count blur? override-theme)
{:style (style/char-count blur?)
:size :paragraph-2}
(str "/"
(pad-0
+31 -37
View File
@@ -30,16 +30,16 @@
{:no-color true})))
(defn left-section-view
[{:keys [on-press icon accessibility-label type icon-background-color] :or {type :grey}}
[{:keys [on-press icon accessibility-label type icon-override-theme] :or {type :grey}}
put-middle-section-on-left?]
[rn/view {:style (when put-middle-section-on-left? {:margin-right 5})}
[button/button
{:on-press on-press
:icon true
:type type
:size 32
:accessibility-label accessibility-label
:override-background-color icon-background-color}
{:on-press on-press
:icon true
:type type
:size 32
:accessibility-label accessibility-label
:override-theme icon-override-theme}
icon]])
(defn- mid-section-comp
@@ -150,15 +150,13 @@
: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 accessibility-label]
{:keys [icon on-press type style icon-override-theme]
:or {type :grey}}]
^{:key index}
[rn/view
(cond-> {:style (assoc style
:margin-right
(if (= index last-icon-index) 0 8))}
accessibility-label (assoc :accessibility-label accessibility-label
:accessible true))
{:style (assoc style
:margin-right
(if (= index last-icon-index) 0 8))}
[button/button
{:on-press on-press
:icon true
@@ -203,8 +201,8 @@
}
}
"
[{:keys [container-style one-icon-align-left? horizontal-description?
align-mid? page-nav-color page-nav-background-uri
[{:keys [one-icon-align-left? horizontal-description? align-mid?
page-nav-color page-nav-background-uri
mid-section
left-section
right-section-buttons]}]
@@ -222,14 +220,13 @@
:left-icon (:left-icon mid-section)
:avatar (:avatar mid-section)}]
[rn/view
{:style (cond-> (merge {:display :flex
:flex-direction :row
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
:align-items :center
:padding-horizontal 20
:height 56
:justify-content :space-between}
container-style)
{:style (cond-> {:display :flex
:flex-direction :row
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
:align-items :center
:padding-horizontal 20
:height 56
:justify-content :space-between}
page-nav-background-uri (assoc :background-color page-nav-color)
page-nav-color (assoc :background page-nav-background-uri))}
[rn/view
@@ -238,18 +235,15 @@
:align-items :center}}
(when left-section
[left-section-view left-section put-middle-section-on-left?])
(when mid-section
(cond
put-middle-section-on-left?
[mid-section-view
(assoc mid-section-props
:left-align? true
:description (:description mid-section)
:description-color (:description-color mid-section)
:description-icon (:description-icon mid-section)
:align-mid? align-mid?
:description-user-icon (:description-user-icon mid-section))]
(not put-middle-section-on-left?)
[mid-section-view mid-section-props]))]
(when put-middle-section-on-left?
[mid-section-view
(assoc mid-section-props
:left-align? true
:description (:description mid-section)
:description-color (:description-color mid-section)
:description-icon (:description-icon mid-section)
:align-mid? align-mid?
:description-user-icon (:description-user-icon mid-section))])]
(when-not put-middle-section-on-left?
[mid-section-view mid-section-props])
[right-section-view right-section-buttons]]))
+1 -2
View File
@@ -16,8 +16,7 @@
[text/text
{:style (style/tip-text completed?)
:weight :regular
:size :paragraph-2}
text]
:size :paragraph-2} text]
(when completed?
[rn/view
{:style style/strike-through
@@ -2,16 +2,14 @@
(:require [quo2.foundations.colors :as colors]))
(defn card-container
[{:keys [customization-color padding-bottom border-bottom-radius]}]
{:padding-horizontal 12
:padding-top 12
:padding-bottom padding-bottom
:flex 1
:border-top-left-radius 16
:border-top-right-radius 16
:border-bottom-left-radius border-bottom-radius
:border-bottom-right-radius border-bottom-radius
:background-color (colors/custom-color customization-color 50 40)})
[customization-color padding-bottom]
{:flex-direction :column
:padding-horizontal 12
:padding-top 12
:padding-bottom padding-bottom
:flex 1
:border-radius 16
:background-color (colors/custom-color customization-color 50 40)})
(def card-header
{:flex-direction :row
@@ -4,104 +4,77 @@
[quo2.components.icon :as icon]
[quo2.components.tags.tag :as tag]
[quo2.foundations.colors :as colors]
[react-native.hole-view :as hole-view]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[quo2.components.profile.profile-card.style :as style]
[quo2.components.avatars.user-avatar.view :as user-avatar]))
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.profile.profile-card.style :as style]))
(defn- profile-card-component
[{:keys [keycard-account? profile-picture name hash
customization-color emoji-hash on-options-press
show-emoji-hash? show-options-button? show-user-hash?
show-logged-in? on-card-press login-card? last-item? card-style]
(defn profile-card
[{:keys [key-card? profile-picture name hash customization-color
emoji-hash on-options-press show-emoji-hash? padding-bottom
show-options-button? show-user-hash? show-logged-in? on-card-press]
:or {show-emoji-hash? false
show-user-hash? false
customization-color :turquoise
show-options-button? false
show-logged-in? false
keycard-account? false
login-card? false
last-item? false
card-style {:padding-horizontal 20
:flex 1}}}]
(let [{:keys [width]} (rn/use-window-dimensions)
padding-bottom (cond
login-card? 38
show-emoji-hash? 12
:else 10)
border-bottom-radius (if (or (not login-card?) last-item?) 16 0)]
[rn/touchable-without-feedback
{:on-press on-card-press
:accessibility-label :profile-card}
[hole-view/hole-view
{:key (str name last-item?) ;; Key is required to force removal of holes
:style (merge {:flex-direction :row} card-style)
:holes (if (or (not login-card?) last-item?)
[]
[{:x 20
:y 108
:width (- width 40)
:height 50
:borderRadius 16}])}
[rn/view
{:style (style/card-container
{:customization-color customization-color
:padding-bottom padding-bottom
:border-bottom-radius border-bottom-radius})}
[rn/view
{:style style/card-header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
key-card? false}}]
[rn/touchable-without-feedback
{:on-press on-card-press
:flex 1
:accessibility-label :profile-card}
[rn/view
(style/card-container
customization-color
(or padding-bottom (if show-emoji-hash? 12 10)))
[rn/view
{:style style/card-header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
:override-theme :dark
:size :medium
:status-indicator? false}]
[rn/view {:flex-direction :row}
(when show-logged-in?
[tag/tag
{:type :icon
:size 32
:blurred? true
:labelled? true
:resource :main-icons2/check
:accessibility-label :logged-in-tag
:icon-color colors/success-50
:override-theme :dark
:size :medium
:status-indicator? false
:customization-color customization-color}]
[rn/view {:flex-direction :row}
(when show-logged-in?
[tag/tag
{:type :icon
:size 32
:blurred? true
:labelled? true
:resource :main-icons2/check
:accessibility-label :logged-in-tag
:icon-color colors/success-50
:override-theme :dark
:label (i18n/label :t/logged-in)}])
(when show-options-button?
[button/button
{:size 32
:type :blur-bg
:icon true
:override-theme :dark
:style style/option-button
:on-press on-options-press
:accessibility-label :profile-card-options}
:i/options])]]
[rn/view
{:style style/name-container}
[text/text
{:size :heading-2
:weight :semi-bold
:number-of-lines 1
:style style/user-name} name]
(when keycard-account?
(icon/icon
:i/keycard
style/keycard-icon))]
(when show-user-hash?
[text/text
{:weight :monospace
:number-of-lines 1
:style style/user-hash} hash])
(when (and show-emoji-hash? emoji-hash)
[text/text
{:weight :monospace
:number-of-lines 1
:style style/emoji-hash} emoji-hash])]]]))
(defn profile-card
[props]
[:f> profile-card-component props])
:label (i18n/label :t/logged-in)}])
(when show-options-button?
[button/button
{:size 32
:type :blur-bg
:icon true
:override-theme :dark
:style style/option-button
:on-press on-options-press
:accessibility-label :profile-card-options}
:i/options])]]
[rn/view
{:style style/name-container}
[text/text
{:size :heading-2
:weight :semi-bold
:number-of-lines 1
:style style/user-name} name]
(when key-card?
(icon/icon
:i/keycard
style/keycard-icon))]
(when show-user-hash?
[text/text
{:weight :monospace
:number-of-lines 1
:style style/user-hash} hash])
(when (and show-emoji-hash? emoji-hash)
[text/text
{:weight :monospace
:number-of-lines 1
:style style/emoji-hash} emoji-hash])]])
@@ -1,29 +0,0 @@
(ns quo2.components.selectors.disclaimer.component-spec
(:require [quo2.components.selectors.disclaimer.view :as disclaimer]
[test-helpers.component :as h]))
(h/describe "Disclaimer tests"
(h/test "Default render of toggle component"
(h/render [disclaimer/view {:on-change (h/mock-fn)} "test"])
(h/is-truthy (h/get-by-label-text :checkbox-off)))
(h/test "Renders its text"
(let [text "I accept this disclaimer"]
(h/render [disclaimer/view {} text])
(h/is-truthy (h/get-by-text text))))
(h/test "On change event gets fire after press"
(let [mock-fn (h/mock-fn)]
(h/render [disclaimer/view {:on-change mock-fn} "test"])
(h/fire-event :press (h/get-by-label-text :checkbox-off))
(h/was-called mock-fn)))
(h/describe "It's rendered according to its `checked?` property"
(h/test "checked? true"
(h/render [disclaimer/view {:checked? true} "test"])
(h/is-null (h/query-by-label-text :checkbox-off))
(h/is-truthy (h/query-by-label-text :checkbox-on)))
(h/test "checked? false"
(h/render [disclaimer/view {:checked? false} "test"])
(h/is-null (h/query-by-label-text :checkbox-on))
(h/is-truthy (h/query-by-label-text :checkbox-off)))))
@@ -2,16 +2,14 @@
(:require [quo2.foundations.colors :as colors]))
(defn container
[blur?]
(let [dark-background (if blur? colors/white-opa-5 colors/neutral-80-opa-40)
dark-border (if blur? colors/white-opa-10 colors/neutral-70)]
{:flex-direction :row
:background-color (colors/theme-colors colors/neutral-5 dark-background)
:padding 11
:align-self :stretch
:border-radius 12
:border-width 1
:border-color (colors/theme-colors colors/neutral-20 dark-border)}))
[]
{:flex-direction :row
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80-opa-40)
:padding 11
:align-self :stretch
:border-radius 12
:border-width 1
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-70)})
(def text
{:margin-left 8})
@@ -5,13 +5,12 @@
[react-native.core :as rn]))
(defn view
[{:keys [checked? blur? on-change accessibility-label container-style]} label]
[{:keys [on-change accessibility-label container-style]} label]
[rn/view
{:style (merge container-style (style/container blur?))}
{:style (merge container-style (style/container))}
[selectors/checkbox
{:accessibility-label accessibility-label
:on-change on-change
:checked? checked?}]
:on-change on-change}]
[text/text
{:size :paragraph-2
:style style/text}
+10 -17
View File
@@ -5,10 +5,6 @@
[react-native.core :as rn]
[reagent.core :as reagent]))
(def themes-for-blur
{:light {:background-color colors/neutral-80-opa-5}
:dark {:background-color colors/white-opa-5}})
(def themes
{:light {:background-color colors/neutral-20}
:dark {:background-color colors/neutral-80}})
@@ -16,12 +12,11 @@
(defn segmented-control
[{:keys [default-active on-change]}]
(let [active-tab-id (reagent/atom default-active)]
(fn [{:keys [data size override-theme blur?]}]
(fn [{:keys [data size]}]
(let [active-id @active-tab-id]
[rn/view
{:flex-direction :row
:background-color (get-in (if blur? themes-for-blur themes)
[(or override-theme (theme/get-theme)) :background-color])
:background-color (get-in themes [(theme/get-theme) :background-color])
:border-radius (case size
32 10
28 8
@@ -34,14 +29,12 @@
{:margin-left (if (= 0 indx) 0 2)
:flex 1}
[tab/view
{:id id
:segmented? true
:size size
:override-theme override-theme
:blur? blur?
:active (= id active-id)
:on-press (fn [tab-id]
(reset! active-tab-id tab-id)
(when on-change
(on-change tab-id)))}
{:id id
:segmented? true
:size size
:active (= id active-id)
:on-press (fn [tab-id]
(reset! active-tab-id tab-id)
(when on-change
(on-change tab-id)))}
label]])]))))
+5 -6
View File
@@ -79,12 +79,11 @@
[notification-dot/notification-dot
{:style style/notification-dot}])
[rn/view
{:style (style/tab
{:size size
:disabled disabled
:segmented? segmented?
:background-color (if (and segmented? (not active)) :transparent background-color)
:show-notification-dot? show-notification-dot?})}
{:style (style/tab {:size size
:disabled disabled
:segmented? segmented?
:background-color background-color
:show-notification-dot? show-notification-dot?})}
(when before
[rn/view
[icons/icon before {:color icon-color}]])
-2
View File
@@ -60,7 +60,6 @@
quo2.components.settings.accounts.view
quo2.components.settings.privacy-option
quo2.components.onboarding.small-option-card.view
quo2.components.tabs.segmented-tab
quo2.components.tabs.account-selector
quo2.components.tabs.tabs
quo2.components.tags.context-tags
@@ -92,7 +91,6 @@
(def audio-tag quo2.components.tags.context-tags/audio-tag)
(def community-tag quo2.components.tags.context-tags/community-tag)
(def tabs quo2.components.tabs.tabs/tabs)
(def segmented-control quo2.components.tabs.segmented-tab/segmented-control)
(def account-selector quo2.components.tabs.account-selector/account-selector)
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
(def page-nav quo2.components.navigation.page-nav/page-nav)
+2 -4
View File
@@ -2,23 +2,21 @@
(:require [quo2.components.avatars.user-avatar.component-spec]
[quo2.components.banners.banner.component-spec]
[quo2.components.buttons.--tests--.buttons-component-spec]
[quo2.components.colors.color-picker.component-spec]
[quo2.components.counter.--tests--.counter-component-spec]
[quo2.components.dividers.--tests--.divider-label-component-spec]
[quo2.components.dividers.strength-divider.component-spec]
[quo2.components.drawers.action-drawers.component-spec]
[quo2.components.drawers.drawer-buttons.component-spec]
[quo2.components.drawers.permission-context.component-spec]
[quo2.components.inputs.input.component-spec]
[quo2.components.colors.color-picker.component-spec]
[quo2.components.inputs.profile-input.component-spec]
[quo2.components.inputs.title-input.component-spec]
[quo2.components.markdown.--tests--.text-component-spec]
[quo2.components.onboarding.small-option-card.component-spec]
[quo2.components.password.tips.component-spec]
[quo2.components.profile.select-profile.component-spec]
[quo2.components.record-audio.record-audio.--tests--.record-audio-component-spec]
[quo2.components.record-audio.soundtrack.--tests--.soundtrack-component-spec]
[quo2.components.profile.select-profile.component-spec]
[quo2.components.selectors.--tests--.selectors-component-spec]
[quo2.components.selectors.disclaimer.component-spec]
[quo2.components.selectors.filter.component-spec]
[quo2.components.tags.--tests--.status-tags-component-spec]))
+1 -8
View File
@@ -85,7 +85,6 @@
;;100 with transparency
(def neutral-100-opa-0 (alpha neutral-100 0))
(def neutral-100-opa-10 (alpha neutral-100 0.1))
(def neutral-100-opa-30 (alpha neutral-100 0.3))
(def neutral-100-opa-60 (alpha neutral-100 0.6))
(def neutral-100-opa-70 (alpha neutral-100 0.7))
(def neutral-100-opa-80 (alpha neutral-100 0.8))
@@ -117,7 +116,6 @@
;;;;Blur
(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-80-opa-80-blur (alpha "#192438" 0.8))
(def neutral-90-opa-70-blur (alpha neutral-90 0.7))
@@ -128,7 +126,6 @@
;;Solid
(def black "#000000")
(def onboarding-header-black "#000716")
;;;;Primary
@@ -239,11 +236,7 @@
([color suffix]
(custom-color color suffix nil))
([color suffix opacity]
(let [color-keyword (keyword color)
base-color (get-in colors-map
[(if (= color-keyword :yinyang)
(if (theme/dark?) :yang :yin)
(keyword color)) suffix])]
(let [base-color (get-in colors-map [(keyword color) suffix])]
(if opacity (alpha base-color (/ opacity 100)) base-color))))))
(defn custom-color-by-theme
+1 -6
View File
@@ -1,10 +1,5 @@
(ns react-native.blur
(:require ["@react-native-community/blur" :as blur]
[react-native.platform :as platform]
[reagent.core :as reagent]
[react-native.core :as rn]))
[reagent.core :as reagent]))
(def view (reagent/adapt-react-class (.-BlurView blur)))
;; blur view is currently not working correctly on Android.
(def ios-view (if platform/ios? view rn/view))
-5
View File
@@ -1,5 +0,0 @@
(ns react-native.camera-kit
(:require ["react-native-camera-kit" :refer (CameraKitCamera)]
[reagent.core :as reagent]))
(def camera (reagent/adapt-react-class CameraKitCamera))
-4
View File
@@ -6,7 +6,3 @@
(let [kb (.useKeyboard hooks)]
{:keyboard-shown (.-keyboardShown ^js kb)
:keyboard-height (.-keyboardHeight ^js kb)}))
(defn use-back-handler
[handler]
(.useBackHandler hooks handler))
+8 -16
View File
@@ -9,7 +9,6 @@
withDelay
withSpring
withRepeat
withSequence
withDecay
Easing
Keyframe
@@ -18,12 +17,10 @@
SlideOutUp
LinearTransition)]
[reagent.core :as reagent]
["react-native-redash" :refer (withPause)]
[react-native.flat-list :as rn-flat-list]
[utils.collection]
[utils.worklets.core :as worklets.core]))
(def ^:const default-duration 300)
;; Animations
(def slide-in-up-animation SlideInUp)
(def slide-out-up-animation SlideOutUp)
@@ -60,8 +57,6 @@
(def with-decay withDecay)
(def key-frame Keyframe)
(def with-repeat withRepeat)
(def with-sequence withSequence)
(def with-pause withPause)
(def cancel-animation cancelAnimation)
;; Easings
@@ -70,7 +65,6 @@
(def in-out
(.-inOut ^js Easing))
;; trying to put default-easing inside easings map causes test to fail
(defn default-easing [] (in-out (.-quad ^js Easing)))
(def easings
@@ -121,15 +115,13 @@
(js-obj "duration" duration
"easing" (get easings easing))))))
(defn animate-delay
([animation val delay]
(animate-delay animation val delay default-duration))
([animation val delay duration]
(set-shared-value animation
(with-delay delay
(with-timing val
(clj->js {:duration duration
:easing (default-easing)}))))))
(defn animate-shared-value-with-delay-default-easing
[anim val duration delay]
(set-shared-value anim
(with-delay delay
(with-timing val
(js-obj "duration" duration
"easing" (in-out (.-quad ^js Easing)))))))
(defn animate-shared-value-with-repeat
[anim val duration easing number-of-repetitions reverse?]
+3 -5
View File
@@ -147,9 +147,8 @@
(defn build-image-messages
[{db :db} chat-id input-text]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
{:keys [message-id]} (get-in db [:chat/inputs chat-id :metadata :responding-to-message])
album-id (str (random-uuid))]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
album-id (str (random-uuid))]
(mapv (fn [[_ {:keys [resized-uri width height]}]]
{:chat-id chat-id
:album-id album-id
@@ -160,8 +159,7 @@
;; TODO: message not received if text field is
;; nil or empty, issue:
;; https://github.com/status-im/status-mobile/issues/14754
:text (or input-text "placeholder")
:response-to message-id})
:text (or input-text "placeholder")})
images)))
(rf/defn clean-input
+2 -2
View File
@@ -276,7 +276,7 @@
(vals (get-in db [:communities community-id :chats])))]
(when (and id
(not= (:current-chat-id db) (str community-id id)))
(chat.events/navigate-to-chat cofx (str community-id id)))))
(chat.events/navigate-to-chat cofx (str community-id id) nil))))
(rf/defn fetch
[_]
@@ -817,7 +817,7 @@
[cofx community-id]
(rf/merge cofx
(navigation/pop-to-root :shell-stack)
(navigation/navigate-to-cofx :community-overview community-id)))
(navigation/navigate-to-nav2 :community community-id true)))
(rf/defn member-role-updated
{:events [:community.member/role-updated]}
+1 -1
View File
@@ -202,7 +202,7 @@
(defn words-count
[s]
(if (empty? s)
0
nil
(-> s
passphrase->words
count)))
+1 -2
View File
@@ -57,7 +57,6 @@
status-im2.contexts.activity-center.events
status-im2.contexts.activity-center.notification.contact-requests.events
status-im2.contexts.shell.events
status-im2.contexts.onboarding.events
status-im.chat.models.gaps
[status-im2.navigation.events :as navigation]))
@@ -117,7 +116,7 @@
(let [current-theme-type (get-in cofx [:db :multiaccount :appearance])]
(when (and (multiaccounts.model/logged-in? cofx)
(= current-theme-type status-im2.constants/theme-type-system))
{:multiaccounts.ui/switch-theme-fx
{:multiaccounts.ui/switch-theme
[(get-in db [:multiaccount :appearance])
(:view-id db) true]})))
+1 -1
View File
@@ -15,7 +15,7 @@
{:events [:navigate-chat-updated]}
[cofx chat-id]
(when (get-in cofx [:db :chats chat-id])
(chat.events/navigate-to-chat cofx chat-id)))
(chat.events/navigate-to-chat cofx chat-id nil)))
(rf/defn handle-chat-removed
{:events [:chat-removed]}
+1 -1
View File
@@ -17,7 +17,7 @@
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db db}
(navigation/pop-to-root :profiles)))
(navigation/pop-to-root :multiaccounts-stack)))
(rf/defn login-pin-more-icon-pressed
{:events [:keycard.login.pin.ui/more-icon-pressed]}
+1 -3
View File
@@ -1,6 +1,5 @@
(ns status-im.mobile-sync-settings.core
(:require [status-im2.common.bottom-sheet.events :as bottom-sheet]
[status-im2.contexts.add-new-contact.events :as add-new-contact]
[status-im.mailserver.core :as mailserver]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.update.core :as multiaccounts.update]
@@ -43,8 +42,7 @@
(and logged-in? initialized?)
[(mailserver/process-next-messages-request)
(bottom-sheet/hide-bottom-sheet)
(wallet/restart-wallet-service nil)
(add-new-contact/set-new-identity-reconnected)]
(wallet/restart-wallet-service nil)]
logged-in?
[(mailserver/process-next-messages-request)
@@ -125,28 +125,6 @@
(fn [[cb options]]
(authenticate-fx #(cb %) options)))
(re-frame/reg-fx
:biometric/enable-and-save-password
(fn [{:keys [key-uid
masked-password
on-success
on-error]}]
(-> (keychain/save-user-password!
key-uid
masked-password)
(.then
(fn [_]
(keychain/save-auth-method!
key-uid
keychain/auth-method-biometric)))
(.then
(fn [_]
(when on-success
(on-success))))
(.catch (fn [error]
(when on-error
(on-error error)))))))
(rf/defn update-biometric
[{db :db :as cofx} biometric-auth?]
(let [key-uid (or (get-in db [:multiaccount :key-uid])
+6 -14
View File
@@ -5,13 +5,14 @@
[status-im2.common.bottom-sheet.events :as bottom-sheet]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as native-module]
[status-im.theme.core :as theme]
[utils.re-frame :as rf]
[quo2.foundations.colors :as colors]
[status-im2.constants :as constants]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
[status-im2.setup.hot-reload :as hot-reload]
[status-im2.common.theme.core :as theme]
[status-im2.common.theme.core :as utils.theme]
[taoensso.timbre :as log]
[status-im2.contexts.shell.animation :as shell.animation]
[status-im.contact.db :as contact.db]))
@@ -44,7 +45,6 @@
(let [me? (= (:public-key current-multiaccount) identity)]
(if me?
[(or (:preferred-name current-multiaccount)
(:primary-name contact)
(gfycat/generate-gfy identity))]
[(:primary-name contact) (:secondary-name contact)])))
@@ -137,16 +137,16 @@
{::blank-preview-flag-changed private?}))
(re-frame/reg-fx
:multiaccounts.ui/switch-theme-fx
:multiaccounts.ui/switch-theme
(fn [[theme-type view-id reload-ui?]]
(let [[theme status-bar-theme nav-bar-color]
;; Status bar theme represents status bar icons colors, so opposite to app theme
(if (or (= theme-type constants/theme-type-dark)
(and (= theme-type constants/theme-type-system)
(theme/device-theme-dark?)))
(utils.theme/dark-mode?)))
[:dark :light colors/neutral-100]
[:light :dark colors/white])]
(theme/set-theme theme)
(theme/change-theme theme)
(re-frame/dispatch [:change-root-status-bar-style
(if (shell.animation/home-stack-open?) status-bar-theme :light)])
(when reload-ui?
@@ -158,17 +158,9 @@
{:events [:multiaccounts.ui/appearance-switched]}
[cofx theme]
(rf/merge cofx
{:multiaccounts.ui/switch-theme-fx [theme :appearance true]}
{:multiaccounts.ui/switch-theme [theme :appearance true]}
(multiaccounts.update/multiaccount-update :appearance theme {})))
(rf/defn switch-theme
{:events [:multiaccounts.ui/switch-theme]}
[cofx theme view-id]
(let [theme (or theme
(get-in cofx [:db :multiaccount :appearance])
constants/theme-type-dark)]
{:multiaccounts.ui/switch-theme-fx [theme view-id false]}))
(rf/defn switch-profile-picture-show-to
{:events [:multiaccounts.ui/profile-picture-show-to-switched]}
[cofx id]
+20 -30
View File
@@ -44,7 +44,6 @@
[status-im2.navigation.events :as navigation]
[status-im2.common.log :as logging]
[taoensso.timbre :as log]
[status-im2.contexts.shell.animation :as shell.animation]
[utils.security.core :as security]))
(re-frame/reg-fx
@@ -339,6 +338,10 @@
{:method "permissions_getDappPermissions"
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}]})
(rf/defn initialize-appearance
[cofx]
{:multiaccounts.ui/switch-theme [(get-in cofx [:db :multiaccount :appearance]) nil false]})
(rf/defn get-group-chat-invitations
[_]
{:json-rpc/call
@@ -365,25 +368,6 @@
[_]
(status/get-node-config #(re-frame/dispatch [::get-node-config-callback %])))
(rf/defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
[{:keys [db] :as cofx}]
(cond
(get db :local-pairing/completed-pairing?)
{:dispatch [:syncing/pairing-completed]}
(get db :onboarding-2/new-account?)
{:dispatch [:onboarding-2/finalize-setup]}
(get db :tos/accepted?)
(rf/merge
cofx
(multiaccounts/switch-theme nil :shell-stack)
(navigation/init-root :shell-stack))
:else
{:dispatch [:init-root :tos]}))
(rf/defn get-settings-callback
{:events [::get-settings-callback]}
[{:keys [db] :as cofx} settings]
@@ -409,6 +393,7 @@
#(do (re-frame/dispatch [:chats-list/load-success %])
(rf/dispatch [:communities/get-user-requests-to-join])
(re-frame/dispatch [::get-chats-callback]))})
(initialize-appearance)
(initialize-wallet-connect)
(get-node-config)
(communities/fetch)
@@ -416,8 +401,7 @@
(logging/set-log-level (:log-level multiaccount))
(activity-center/notifications-fetch-pending-contact-requests)
(activity-center/update-seen-state)
(activity-center/notifications-fetch-unread-count)
(redirect-to-root))))
(activity-center/notifications-fetch-unread-count))))
(re-frame/reg-fx
::open-last-chat
@@ -492,6 +476,13 @@
keychain/auth-method-biometric
keychain/auth-method-password))))
(defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
[db]
(if (get db :tos/accepted?)
(re-frame/dispatch [:init-root :shell-stack])
(re-frame/dispatch [:init-root :tos])))
(rf/defn login-only-events
[{:keys [db] :as cofx} key-uid password save-password?]
(let [auth-method (:auth-method db)
@@ -503,7 +494,8 @@
{:db (assoc db :chats/loading? true)
:json-rpc/call
[{:method "settings_getSettings"
:on-success #(re-frame/dispatch [::get-settings-callback %])}]}
:on-success #(do (re-frame/dispatch [::get-settings-callback %])
(redirect-to-root db))}]}
(notifications/load-notification-preferences)
(when save-password?
(keychain/save-user-password key-uid password))
@@ -522,11 +514,10 @@
tos-accepted? (get db :tos/accepted?)
{:networks/keys [current-network networks]} db
network-id (str (get-in networks [current-network :config :NetworkId]))]
(shell.animation/change-selected-stack-id :communities-stack true)
(rf/merge cofx
{:db (-> db
(dissoc :multiaccounts/login)
(assoc :tos/next-root :enable-notifications :chats/loading? false)
(assoc :tos/next-root :onboarding-notification :chats/loading? false)
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
::get-tokens [network-id accounts recovered-account?]}
(finish-keycard-setup)
@@ -537,7 +528,7 @@
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)
(logging/set-log-level (:log-level multiaccount))
(navigation/init-root :enable-notifications))))
(navigation/init-root :shell-stack))))
(defn- keycard-setup?
[cofx]
@@ -640,7 +631,7 @@
(assoc-in [:keycard :pin :login] []))})
#(if keycard-account?
{:init-root-fx :multiaccounts-keycard}
{:init-root-fx :profiles})
{:init-root-fx :multiaccounts})
#(when goto-key-storage?
(navigation/navigate-to-cofx % :actions-not-logged-in nil))))))
@@ -739,9 +730,8 @@
keycard-multiaccount? (boolean (:keycard-pairing multiaccount))]
(rf/merge
cofx
(merge
{:db (update db :keycard dissoc :application-info)}
(when keycard-multiaccount? {:navigate-to-fx :keycard-login-pin}))
{:db (update db :keycard dissoc :application-info)
:navigate-to-fx (if keycard-multiaccount? :keycard-login-pin :login)}
(open-login (select-keys multiaccount [:key-uid :name :public-key :identicon :images])))))
(rf/defn hide-keycard-banner
-20
View File
@@ -91,14 +91,6 @@
key-uid
#(.loginWithConfig ^js (status) account-data hashed-password config))))
(defn create-account-and-login
[request]
(.createAccountAndLogin ^js (status) (types/clj->json request)))
(defn restore-account-and-login
[request]
(.restoreAccountAndLogin ^js (status) (types/clj->json request)))
(defn export-db
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password callback]
@@ -619,15 +611,3 @@
current-password#
new-password
callback))
(defn backup-disabled-data-dir
[]
(.backupDisabledDataDir ^js (status)))
(defn keystore-dir
[]
(.keystoreDir ^js (status)))
(defn log-file-directory
[]
(.logFileDirectory ^js (status)))
+1 -1
View File
@@ -165,7 +165,7 @@
:MailserversConfig {:Enabled true}
:EnableNTPSync true
:WakuConfig
{:Enabled (not wakuv2-enabled)
{:Enabled true
:BloomFilterMode waku-bloom-filter-mode
:LightClient true
:MinimumPoW 0.000001}
+6 -40
View File
@@ -9,10 +9,7 @@
[status-im.visibility-status-updates.core :as visibility-status-updates]
[utils.re-frame :as rf]
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
[taoensso.timbre :as log]
[status-im2.constants :as constants]
[quo2.foundations.colors :as colors]
[status-im.multiaccounts.model :as multiaccounts.model]))
[taoensso.timbre :as log]))
(rf/defn status-node-started
[{db :db :as cofx} {:keys [error]}]
@@ -56,40 +53,10 @@
:peer-stats peer-stats
:peers-count (count (:peers peer-stats)))}))
(rf/defn handle-local-pairing-signals
[{:keys [db] :as cofx} event]
(log/info "local pairing signal received"
{:event event})
(let [connection-success? (= (:type event)
constants/local-pairing-event-connection-success)
error-on-pairing? (contains? constants/local-pairing-event-errors (:type event))
completed-pairing? (and (= (:type event)
constants/local-pairing-event-process-success)
(= (:action event)
constants/local-pairing-action-pairing-account))
logged-in? (multiaccounts.model/logged-in? cofx)
;; since `connection-success` event is received on both sender and receiver devices
;; we check the `logged-in?` status to identify the receiver and take the user to next screen
navigate-to-syncing-devices? (and connection-success? (not logged-in?))
user-in-syncing-devices-screen? (= (:view-id db) :syncing-devices)]
(merge {:db (cond-> db
connection-success?
(assoc :local-pairing/completed-pairing? false)
error-on-pairing?
(dissoc :local-pairing/completed-pairing?)
completed-pairing?
(assoc :local-pairing/completed-pairing? true))}
(when navigate-to-syncing-devices?
{:dispatch [:navigate-to :syncing-devices]})
(when (and error-on-pairing? user-in-syncing-devices-screen?)
{:dispatch-n [[:toasts/upsert
{:icon :i/info
:icon-color colors/danger-50
:override-theme :light
:text (i18n/label :t/error-syncing-connection-failed)}]
[:navigate-back]]}))))
(defn handle-local-pairing-signals
[event]
(log/debug "local pairing signal received"
{:event event}))
(rf/defn process
{:events [:signals/signal-received]}
@@ -143,6 +110,5 @@
"status.updates.timedout" (visibility-status-updates/handle-visibility-status-updates
cofx
(js->clj event-js :keywordize-keys true))
"localPairing" (handle-local-pairing-signals cofx
(js->clj event-js :keywordize-keys true))
"localPairing" (handle-local-pairing-signals (js->clj event-js :keywordize-keys true))
(log/debug "Event " type " not handled"))))
+8
View File
@@ -0,0 +1,8 @@
(ns status-im.theme.core
(:require [quo.theme :as quo.theme]
[quo2.theme :as quo2.theme]))
(defn change-theme
[theme]
(quo.theme/set-theme theme)
(quo2.theme/set-theme theme))
@@ -48,7 +48,7 @@
:on-press (fn []
(rf/dispatch [:communities/load-category-states id])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview id]))
(rf/dispatch [:navigate-to-nav2 :community {:community-id id}]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
[community/community-actions community])}])}
@@ -111,7 +111,7 @@
(i18n/label :t/open-membership))]]
:on-press #(do
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview id]))}]))
(rf/dispatch [:navigate-to-nav2 :community {:community-id id}]))}]))
(defn communities-actions
[]
@@ -12,7 +12,7 @@
[]
[quo/list-item
{:theme :accent
:on-press #(hide-sheet-and-dispatch [:navigate-to :intro])
:on-press #(hide-sheet-and-dispatch [:generate-and-derive-addresses])
:icon :main-icons/add
:accessibility-label :generate-a-new-key
:title (i18n/label :t/generate-a-new-key)}])
@@ -377,14 +377,14 @@
:height 40}}]
[communities.icon/community-icon community])]
[rn/view {:padding-right 14 :flex 1}
[rn/text {:style {:font-weight "700" :font-size 17 :color quo.colors/black}}
[rn/text {:style {:font-weight "700" :font-size 17}}
name]
[rn/text {:style {:color quo.colors/black}} description]]]
[rn/text description]]]
[rn/view (style/community-view-button)
[rn/touchable-opacity
{:on-press #(re-frame/dispatch
[:communities/navigate-to-community
(:id community)])}
{:community-id (:id community)}])}
[rn/text
{:style {:text-align :center
:color quo.colors/blue}} (i18n/label :t/view)]]]])))
+21 -29
View File
@@ -155,36 +155,19 @@
(callback nil))))
(callback nil))))))
(defn save-user-password!
[key-uid password]
(save-credentials
key-uid
key-uid
(security/safe-unmask-data password)
#(when-not %
(log/error
(str "Error while saving password."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))
(defn save-auth-method!
[key-uid method]
(save-credentials
(str key-uid "-auth")
key-uid
method
#(when-not %
(log/error
(str "Error while saving auth method."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))
(re-frame/reg-fx
:keychain/save-user-password
(fn [[key-uid masked-password]]
(save-user-password! key-uid masked-password)))
(fn [[key-uid password]]
(save-credentials
key-uid
key-uid
(security/safe-unmask-data password)
#(when-not %
(log/error
(str "Error while saving password."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it."))))))
(re-frame/reg-fx
:keychain/save-auth-method
@@ -195,7 +178,16 @@
"method"
method)
(when-not (empty? key-uid) ; key-uid may be nil after restore from local pairing
(save-auth-method! key-uid method))))
(save-credentials
(str key-uid "-auth")
key-uid
method
#(when-not %
(log/error
(str "Error while saving auth method."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))))
(re-frame/reg-fx
:keychain/save-keycard-keys
-5
View File
@@ -126,11 +126,6 @@
(when (string? s)
(string/replace s m r)))
(defn safe-nth
[coll index]
(when (number? index)
(nth coll index)))
(defn svg?
[some-string]
(string/ends-with? some-string ".svg"))
@@ -7,7 +7,7 @@
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[status-im2.common.bottom-sheet.view :as bottom-sheet]
[status-im2.contexts.chat.menus.pinned-messages.view :as pinned-messages-menu]
[status-im2.contexts.chat.messages.pin.list.view :as pin.list]
[react-native.core :as rn]))
(defn bottom-sheet
@@ -50,8 +50,7 @@
(merge key-storage/migrate-account-password)
(= view :pinned-messages-list)
(merge {:content pinned-messages-menu/pinned-messages
:bottom-safe-area-spacing? false}))]
(merge {:content pin.list/pinned-messages-list}))]
[:f>
(fn []
(rn/use-effect (fn []
@@ -1,42 +0,0 @@
(ns status-im2.common.bottom-sheet-screen.style
(:require
[quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(defn background
[opacity]
(reanimated/apply-animations-to-style
{:opacity opacity}
{:background-color colors/neutral-100-opa-70
:position :absolute
:top 0
:bottom 0
:left 0
:right 0}))
(defn main-view
[translate-y]
(reanimated/apply-animations-to-style
{:transform [{:translate-y translate-y}]}
{:background-color (colors/theme-colors colors/white colors/neutral-95)
:border-top-left-radius 20
:border-top-right-radius 20
:flex 1
:overflow :hidden}))
(def handle-container
{:left 0
:right 0
:top 0
:height 20
:z-index 1
:position :absolute
:justify-content :center
:align-items :center})
(defn handle
[]
{:width 32
:height 4
:border-radius 100
:background-color (colors/theme-colors colors/neutral-100-opa-30 colors/white-opa-30)})
@@ -1,81 +0,0 @@
(ns status-im2.common.bottom-sheet-screen.view
(:require
[react-native.gesture :as gesture]
[react-native.hooks :as hooks]
[react-native.navigation :as navigation]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[oops.core :as oops]
[react-native.safe-area :as safe-area]
[status-im2.common.bottom-sheet-screen.style :as style]
[react-native.core :as rn]
[reagent.core :as reagent]
[utils.re-frame :as rf]))
(def ^:const drag-threshold 100)
(defn drag-gesture
[translate-y opacity scroll-enabled curr-scroll]
(->
(gesture/gesture-pan)
(gesture/on-start (fn [e]
(when (< (oops/oget e "velocityY") 0)
(reset! scroll-enabled true))))
(gesture/on-update (fn [e]
(let [translation (oops/oget e "translationY")
progress (Math/abs (/ translation drag-threshold))]
(when (pos? translation)
(reanimated/set-shared-value translate-y translation)
(reanimated/set-shared-value opacity (- 1 (/ progress 5)))))))
(gesture/on-end (fn [e]
(if (> (oops/oget e "translationY") drag-threshold)
(do
(reanimated/set-shared-value opacity (reanimated/with-timing-duration 0 100))
(rf/dispatch [:navigate-back]))
(do
(reanimated/set-shared-value opacity (reanimated/with-timing 1))
(reanimated/set-shared-value translate-y (reanimated/with-timing 0))
(reset! scroll-enabled true)))))
(gesture/on-finalize (fn [e]
(when (and (>= (oops/oget e "velocityY") 0)
(<= @curr-scroll (if platform/ios? -1 0)))
(reset! scroll-enabled false))))))
(defn on-scroll
[e curr-scroll]
(let [y (oops/oget e "nativeEvent.contentOffset.y")]
(reset! curr-scroll y)))
(defn view
[content skip-background?]
[:f>
(let [scroll-enabled (reagent/atom true)
curr-scroll (atom 0)]
(fn []
(let [sb-height (navigation/status-bar-height)
insets (safe-area/use-safe-area)
padding-top (Math/max sb-height (:top insets))
padding-top (if platform/ios? padding-top (+ padding-top 10))
opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value 0)
close (fn []
(reanimated/set-shared-value opacity (reanimated/with-timing-duration 0 100))
(rf/dispatch [:navigate-back]))]
(rn/use-effect
(fn []
(reanimated/animate-delay opacity 1 (if platform/ios? 300 100))))
(hooks/use-back-handler close)
[rn/view
{:style {:flex 1
:padding-top padding-top}}
(when-not skip-background?
[reanimated/view {:style (style/background opacity)}])
[gesture/gesture-detector
{:gesture (drag-gesture translate-y opacity scroll-enabled curr-scroll)}
[reanimated/view {:style (style/main-view translate-y)}
[rn/view {:style style/handle-container}
[rn/view {:style (style/handle)}]]
[content
{:close close
:scroll-enabled @scroll-enabled
:on-scroll #(on-scroll % curr-scroll)}]]]])))])
@@ -26,23 +26,18 @@
[quo/text {:style {:margin-left 10}} extra-text]]))
(defn confirmation-drawer
[{:keys [title description context button-text on-press extra-action extra-text accessibility-label
close-button-text]}]
[{:keys [title description context button-text on-press extra-action extra-text accessibility-label]}]
(let [extra-action-selected? (reagent/atom false)]
(fn []
(let [{:keys [group-chat chat-id public-key color profile-picture
name]} context
id (or chat-id public-key)
display-name (or
name
(when-not group-chat
(rf/sub [:contacts/contact-name-by-identity id])))
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address
id]))
photo-path (or profile-picture
(when-not (empty? (:images contact))
(rf/sub [:chats/photo-path id])))]
(let [{:keys [group-chat chat-id public-key color name]} context
id (or chat-id public-key)
display-name
(if-not group-chat (first (rf/sub [:contacts/contact-two-names-by-identity id])) name)
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address
id]))
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path id]))]
[rn/view
{:style {:margin-horizontal 20}
:accessibility-label accessibility-label}
@@ -62,7 +57,7 @@
{:type :grey
:style {:flex 0.48} ;;WUT? 0.48 , whats that ?
:on-press #(rf/dispatch [:bottom-sheet/hide])}
(or close-button-text (i18n/label :t/close))]
(i18n/label :t/close)]
[quo/button
{:type :danger
:style {:flex 0.48}
+14 -9
View File
@@ -1,15 +1,20 @@
(ns status-im2.common.resources)
(def ui
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
:music (js/require "../resources/images/ui2/music.png")
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")})
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
:intro-1 (js/require "../resources/images/ui2/intro-1.png")
:intro-2 (js/require "../resources/images/ui2/intro-2.png")
:intro-3 (js/require "../resources/images/ui2/intro-3.png")
:intro-4 (js/require "../resources/images/ui2/intro-4.png")
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
:music (js/require "../resources/images/ui2/music.png")
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
:onboarding-bg-1 (js/require "../resources/images/ui2/onboarding-bg-1.png")
:onboarding-blur-bg (js/require "../resources/images/ui2/onboarding_blur_bg.png")
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")})
(def mock-images
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
+9 -16
View File
@@ -1,24 +1,17 @@
(ns status-im2.common.theme.core
(:require [quo.theme :as quo]
[quo2.theme :as quo2]
[react-native.core :as rn]))
(:require [react-native.core :as rn]))
(def device-theme (atom (rn/get-color-scheme)))
(def initial-mode (atom (rn/get-color-scheme)))
;; Note - don't use value returned by change listener
;; https://github.com/facebook/react-native/issues/28525
(defn add-device-theme-change-listener
(defn add-mode-change-listener
[callback]
(rn/appearance-add-change-listener #(let [theme (rn/get-color-scheme)]
(when-not (= theme @device-theme)
(reset! device-theme theme)
(callback (keyword theme))))))
(rn/appearance-add-change-listener #(let [mode (rn/get-color-scheme)]
(when-not (= mode @initial-mode)
(reset! initial-mode mode)
(callback (keyword mode))))))
(defn device-theme-dark?
(defn dark-mode?
[]
(= @device-theme "dark"))
(defn set-theme
[value]
(quo/set-theme value)
(quo2/set-theme value))
(= @initial-mode "dark"))
-6
View File
@@ -138,12 +138,6 @@
:url "#"
:icons ["https://statusnetwork.com/img/press-kit-status-logo.svg"]})
(def default-network-id
(get-in default-networks-by-id [default-network :config :NetworkId]))
(def default-network-rpc-url
(get-in default-networks-by-id [default-network :config :UpstreamConfig :URL]))
(def wallet-connect-project-id "87815d72a81d739d2a7ce15c2cfdefb3")
(def delete-message-undo-time-limit-ms 4000)
-31
View File
@@ -90,9 +90,6 @@
(def ^:const command-state-transaction-pending 6)
(def ^:const command-state-transaction-sent 7)
(def ^:const profile-default-color :blue)
(def ^:const profile-name-max-length 24)
(def ^:const profile-pictures-show-to-contacts-only 1)
(def ^:const profile-pictures-show-to-everyone 2)
(def ^:const profile-pictures-show-to-none 3)
@@ -263,27 +260,6 @@
An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 "
"cs")
;; sender and receiver events
(def ^:const local-pairing-event-connection-success "connection-success")
(def ^:const local-pairing-event-connection-error "connection-error")
(def ^:const local-pairing-event-transfer-success "transfer-success")
(def ^:const local-pairing-event-transfer-error "transfer-error")
;; receiver events
(def ^:const local-pairing-event-received-amount "received-account")
(def ^:const local-pairing-event-process-success "process-success")
(def ^:const local-pairing-event-process-error "process-error")
(def ^:const local-pairing-event-errors
#{local-pairing-event-connection-error
local-pairing-event-transfer-error
local-pairing-event-process-error})
(def ^:const local-pairing-action-connect 1)
(def ^:const local-pairing-action-pairing-account 2)
(def ^:const local-pairing-action-sync-device 3)
(def ^:const local-pairing-action-pairing-installation 4)
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
function at status-go, This key determines the output base of the serialization.
@@ -316,10 +292,3 @@
(def ^:const everyone-mention-id "0x00001")
(def ^:const empty-category-id :communities/not-categorized)
(def ^:const seed-phrase-valid-length #{12 18 24})
(def ^:const auth-method-password "password")
(def ^:const auth-method-biometric "biometric")
(def ^:const auth-method-biometric-prepare "biometric-prepare")
(def ^:const auth-method-none "none")
@@ -552,7 +552,7 @@
{:icon :placeholder
:icon-color colors/primary-50-opa-40
:title (i18n/label :t/contact-request-accepted-toast
{:name (or name (:alias message))})})
{:name (:alias message)})})
:else
cofx))
@@ -1,5 +1,6 @@
(ns status-im2.contexts.activity-center.notification.contact-requests.events
(:require [taoensso.timbre :as log]
(:require [status-im2.contexts.activity-center.events :as ac-events]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/defn accept-contact-request
@@ -18,7 +19,8 @@
(log/error "Failed to accept contact-request"
{:error error
:event :activity-center.contact-requests/accept
:contact-id contact-id}))
:contact-id contact-id})
nil)
(rf/defn decline-contact-request
{:events [:activity-center.contact-requests/decline]}
@@ -36,4 +38,32 @@
(log/error "Failed to decline contact-request"
{:error error
:event :activity-center.contact-requests/decline
:contact-id contact-id}))
:contact-id contact-id})
nil)
(rf/defn cancel-outgoing-contact-request
{:events [:activity-center.contact-requests/cancel-outgoing]}
[{:keys [db]} {:keys [contact-id notification-id]}]
(when-let [notification (ac-events/get-notification db notification-id)]
{:json-rpc/call
[{:method "wakuext_cancelOutgoingContactRequest"
:params [{:id contact-id}]
:on-success #(rf/dispatch [:activity-center.contact-requests/cancel-outgoing-success
notification])
:on-error #(rf/dispatch [:activity-center.contact-requests/cancel-outgoing-error contact-id
%])}]}))
(rf/defn cancel-outgoing-contact-request-success
{:events [:activity-center.contact-requests/cancel-outgoing-success]}
[_ notification]
{:dispatch [:activity-center.notifications/reconcile
[(assoc notification :deleted true)]]})
(rf/defn cancel-outgoing-contact-request-error
{:events [:activity-center.contact-requests/cancel-outgoing-error]}
[_ contact-id error]
(log/error "Failed to cancel outgoing contact-request"
{:error error
:event :activity-center.contact-requests/cancel-outgoing
:contact-id contact-id})
nil)
@@ -1,13 +1,12 @@
(ns status-im2.contexts.activity-center.notification.contact-requests.view
(:require
[quo2.core :as quo]
[react-native.gesture :as gesture]
[status-im2.constants :as constants]
[status-im2.contexts.activity-center.notification.common.style :as common-style]
[status-im2.contexts.activity-center.notification.common.view :as common]
[utils.datetime :as datetime]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(:require [quo2.core :as quo]
[react-native.gesture :as gesture]
[status-im2.constants :as constants]
[status-im2.contexts.activity-center.notification.common.style :as common-style]
[status-im2.contexts.activity-center.notification.common.view :as common]
[utils.datetime :as datetime]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- swipe-button-accept
[{:keys [style]} _]
@@ -23,17 +22,24 @@
:icon :i/placeholder
:text (i18n/label :t/decline)}])
(defn- swipe-button-cancel-pending
[{:keys [style]} _]
[common/swipe-button-container
{:style (common-style/swipe-danger-container style)
:icon :i/placeholder
:text (i18n/label :t/cancel)}])
(defn- swipeable
[{:keys [active-swipeable extra-fn notification]} child]
(let [{:keys [id author message]} notification
{:keys [contact-request-state]} message
{:keys [public-key]} (rf/sub [:multiaccount/contact])
outgoing? (= public-key author)]
(let [{:keys [id author message last-message]} notification
{:keys [contact-request-state]} (or (:message notification)
(:last-message notification))
{:keys [public-key]} (rf/sub [:multiaccount/contact])
message (or message last-message)]
(cond
(or (#{constants/contact-request-message-state-accepted
constants/contact-request-message-state-declined}
contact-request-state)
(and outgoing? (= contact-request-state constants/contact-request-message-state-pending)))
(#{constants/contact-request-message-state-accepted
constants/contact-request-message-state-declined}
contact-request-state)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
@@ -43,23 +49,33 @@
:extra-fn extra-fn}
child]
(and (= contact-request-state constants/contact-request-message-state-pending)
(not outgoing?))
[common/swipeable
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.contact-requests/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.contact-requests/decline id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
(= contact-request-state constants/contact-request-message-state-pending)
(if (= public-key author)
[common/swipeable
{:right-button swipe-button-cancel-pending
:right-on-press (fn []
(rf/dispatch
[:activity-center.contact-requests/cancel-outgoing
{:contact-id (:from message)
:notification-id id}]))
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
[common/swipeable
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.contact-requests/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.contact-requests/decline id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
:else
child)))
(defn- outgoing-contact-request-view
[{:keys [notification set-swipeable-height]}]
(let [{:keys [chat-id message last-message]} notification
(let [{:keys [id chat-id message last-message]} notification
{:keys [contact-request-state] :as message} (or message last-message)]
(if (= contact-request-state constants/contact-request-message-state-accepted)
[quo/activity-log
@@ -83,7 +99,17 @@
:message {:body (get-in message [:content :text])}
:items (case contact-request-state
constants/contact-request-message-state-pending
[{:type :status
[{:type :button
:subtype :danger
:key :button-cancel
:label (i18n/label :t/cancel)
:accessibility-label :cancel-contact-request
:on-press (fn []
(rf/dispatch
[:activity-center.contact-requests/cancel-outgoing
{:contact-id (:from message)
:notification-id id}]))}
{:type :status
:subtype :pending
:key :status-pending
:blur? true
@@ -1,6 +1,5 @@
(ns status-im2.contexts.add-new-contact.events
(:require [clojure.string :as string]
[utils.re-frame :as rf]
(:require [utils.re-frame :as rf]
[status-im.utils.types :as types]
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
@@ -12,120 +11,11 @@
[status-im2.contexts.contacts.events :as data-store.contacts]
[status-im.utils.utils :as utils]))
(defn init-contact
"Create a new contact (persisted to app-db as [:contacts/new-identity]).
The following options are available:
| key | description |
| -------------------|-------------|
| `:user-public-key` | user's public key (not the contact)
| `:input` | raw user input (untrimmed)
| `:scanned` | scanned user input (untrimmed)
| `:id` | public-key|compressed-key|ens
| `:type` | :empty|:public-key|:compressed-key|:ens
| `:ens` | id.eth|id.ens-stateofus
| `:public-key` | public-key (from decompression or ens resolution)
| `:state` | :empty|:invalid|:decompress-key|:resolve-ens|:valid
| `:msg` | keyword i18n msg"
([]
(-> [:user-public-key :input :scanned :id :type :ens :public-key :state :msg]
(zipmap (repeat nil))))
([kv] (-> (init-contact) (merge kv))))
(def url-regex #"^https?://join.status.im/u/(.+)")
(defn ->id
[{:keys [input] :as contact}]
(let [trimmed-input (utils/safe-trim input)]
(->> {:id (if (empty? trimmed-input)
nil
(if-some [[_ id] (re-matches url-regex trimmed-input)]
id
trimmed-input))}
(merge contact))))
(defn ->type
[{:keys [id] :as contact}]
(->> (cond
(empty? id)
{:type :empty}
(validators/valid-public-key? id)
{:type :public-key
:public-key id}
(validators/valid-compressed-key? id)
{:type :compressed-key}
:else
{:type :ens
:ens (stateofus/ens-name-parse id)})
(merge contact)))
(defn ->state
[{:keys [id type public-key user-public-key] :as contact}]
(->> (cond
(empty? id)
{:state :empty}
(= type :public-key)
{:state :invalid
:msg :t/not-a-chatkey}
(= public-key user-public-key)
{:state :invalid
:msg :t/can-not-add-yourself}
(and (= type :compressed-key) (empty? public-key))
{:state :decompress-key}
(and (= type :ens) (empty? public-key))
{:state :resolve-ens}
(and (or (= type :compressed-key) (= type :ens))
(validators/valid-public-key? public-key))
{:state :valid})
(merge contact)))
(def validate-contact (comp ->state ->type ->id))
(defn dispatcher [event input] (fn [arg] (rf/dispatch [event input arg])))
(rf/defn set-new-identity
{:events [:contacts/set-new-identity]}
[{:keys [db]} input scanned]
(let [user-public-key (get-in db [:multiaccount :public-key])
{:keys [input id ens state]
:as contact} (-> {:user-public-key user-public-key
:input input
:scanned scanned}
init-contact
validate-contact)]
(case state
:empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact)
:contacts/decompress-public-key
{:compressed-key id
:on-success
(dispatcher :contacts/set-new-identity-success input)
:on-error
(dispatcher :contacts/set-new-identity-error input)}}
:resolve-ens {:db (assoc db :contacts/new-identity contact)
:contacts/resolve-public-key-from-ens
{:chain-id (ethereum/chain-id db)
:ens ens
:on-success
(dispatcher :contacts/set-new-identity-success input)
:on-error
(dispatcher :contacts/set-new-identity-error input)}})))
(re-frame/reg-fx
:contacts/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(fn [{:keys [public-key on-success on-error]}]
(status/compressed-key->public-key
compressed-key
public-key
(fn [resp]
(let [{:keys [error]} (types/json->clj resp)]
(if error
@@ -133,16 +23,74 @@
(on-success (str "0x" (subs resp 5)))))))))
(re-frame/reg-fx
:contacts/resolve-public-key-from-ens
(fn [{:keys [chain-id ens on-success on-error]}]
(ens/pubkey chain-id ens on-success on-error)))
:contacts/resolve-public-key-from-ens-name
(fn [{:keys [chain-id ens-name on-success on-error]}]
(ens/pubkey chain-id ens-name on-success on-error)))
(defn fx-callbacks
[input ens-name]
{:on-success (fn [pubkey]
(rf/dispatch [:contacts/set-new-identity-success input ens-name pubkey]))
:on-error (fn [err]
(rf/dispatch [:contacts/set-new-identity-error err input]))})
(defn identify-type
[input]
(let [regex #"^https?://join.status.im/u/(.+)"
id (as-> (utils/safe-trim input) $
(if-some [[_ match] (re-matches regex $)]
match
$)
(if (empty? $) nil $))
public-key? (validators/valid-public-key? id)
compressed-key? (validators/valid-compressed-key? id)
type (cond (empty? id) :empty
public-key? :public-key
compressed-key? :compressed-key
:else :ens-name)
ens-name (when (= type :ens-name)
(stateofus/ens-name-parse id))]
{:input input
:id id
:type type
:ens-name ens-name}))
(rf/defn set-new-identity
{:events [:contacts/set-new-identity]}
[{:keys [db]} input]
(let [{:keys [input id type ens-name]} (identify-type input)]
(case type
:empty {:db (dissoc db :contacts/new-identity)}
:public-key {:db (assoc db
:contacts/new-identity
{:input input
:public-key id
:state :error
:error :uncompressed-key})}
:compressed-key {:db
(assoc db
:contacts/new-identity
{:input input
:state :searching})
:contacts/decompress-public-key
(merge {:public-key id}
(fx-callbacks id ens-name))}
:ens-name {:db
(assoc db
:contacts/new-identity
{:input input
:state :searching})
:contacts/resolve-public-key-from-ens-name
(merge {:chain-id (ethereum/chain-id db)
:ens-name ens-name}
(fx-callbacks id ens-name))})))
(rf/defn build-contact
{:events [:contacts/build-contact]}
[_ pubkey ens open-profile-modal?]
[_ pubkey ens-name open-profile-modal?]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:ENSName ens-name}]
:js-response true
:on-success #(rf/dispatch [:contacts/contact-built
pubkey
@@ -158,25 +106,24 @@
(rf/defn set-new-identity-success
{:events [:contacts/set-new-identity-success]}
[{:keys [db]} input pubkey]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(rf/merge {:db (assoc db
:contacts/new-identity
(->state (assoc contact :public-key pubkey)))}
(build-contact pubkey (:ens contact) false)))))
[{:keys [db] :as cofx} input ens-name pubkey]
(rf/merge cofx
{:db (assoc db
:contacts/new-identity
{:input input
:public-key pubkey
:ens-name ens-name
:state :valid})}
(build-contact pubkey ens-name false)))
(rf/defn set-new-identity-error
{:events [:contacts/set-new-identity-error]}
[{:keys [db]} input err]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(let [state (cond
(or (string/includes? (:message err) "fallback failed")
(string/includes? (:message err) "no such host"))
{:state :invalid :msg :t/lost-connection}
:else {:state :invalid})]
{:db (assoc db :contacts/new-identity (merge contact state))}))))
[{:keys [db]} error input]
{:db (assoc db
:contacts/new-identity
{:input input
:state :error
:error :invalid})})
(rf/defn clear-new-identity
{:events [:contacts/clear-new-identity :contacts/new-chat-focus]}
@@ -185,13 +132,7 @@
(rf/defn qr-code-scanned
{:events [:contacts/qr-code-scanned]}
[{:keys [db] :as cofx} scanned]
[{:keys [db] :as cofx} input]
(rf/merge cofx
(set-new-identity scanned scanned)
(set-new-identity input)
(navigation/navigate-back)))
(rf/defn set-new-identity-reconnected
[{:keys [db]}]
(let [input (get-in db [:contacts/new-identity :input])
resubmit? (and input (= :new-contact (get-in db [:view-id])))]
(rf/dispatch [:contacts/set-new-identity input])))
@@ -1,10 +1,7 @@
(ns status-im2.contexts.add-new-contact.events-test
(:require [cljs.test :refer-macros [deftest are]]
[status-im2.contexts.add-new-contact.events :as events]))
(:require [cljs.test :refer-macros [deftest is are]]
[status-im2.contexts.add-new-contact.events :as core]))
(def user-ukey
"0x04ca27ed9c7c4099d230c6d8853ad0cfaf084a019c543e9e433d3c04fac6de9147cf572b10e247cfe52f396b5aa10456b56dd1cf1d8a681e2b93993d44594b2e85")
(def user-ckey "zQ3shtFEo4PxpQiYGcNZZ8xhJmhD6WBXwnHPBueu5SRnvPXjk")
(def ukey
"0x045596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce694f1bf2d8773cd59f4dd0863e951f9b7f7351c5516291a0fceb73f8c392a0e88")
(def ckey "zQ3shWj4WaBdf2zYKCkXe6PHxDxNTzZyid1i75879Ue9cX9gA")
@@ -13,118 +10,47 @@
(def link-ckey (str "https://join.status.im/u/" ckey))
(def link-ens (str "https://join.status.im/u/" ens))
;;; unit tests (no app-db involved)
(deftest identify-type-test
(are [input expected] (= (core/identify-type input) expected)
"" {:input ""
:id nil
:type :empty
:ens-name nil}
(deftest validate-contact-test
(are [i e] (= (events/validate-contact (events/init-contact
{:user-public-key user-ukey
:input i}))
(events/init-contact e))
ukey {:input ukey
:id ukey
:type :public-key
:ens-name nil}
"" {:user-public-key user-ukey
:input ""
:type :empty
:state :empty}
ens {:input ens
:id ens
:type :ens-name
:ens-name ens-stateofus-eth}
" " {:user-public-key user-ukey
:input " "
:type :empty
:state :empty}
ckey {:input ckey
:id ckey
:type :compressed-key
:ens-name nil}
ukey {:user-public-key user-ukey
:input ukey
:id ukey
:type :public-key
:public-key ukey
:state :invalid
:msg :t/not-a-chatkey}
link-ckey {:input link-ckey
:id ckey
:type :compressed-key
:ens-name nil}
ens {:user-public-key user-ukey
:input ens
:id ens
:type :ens
:ens ens-stateofus-eth
:state :resolve-ens}
link-ens {:input link-ens
:id ens
:type :ens-name
:ens-name ens-stateofus-eth}))
(str " " ens) {:user-public-key user-ukey
:input (str " " ens)
:id ens
:type :ens
:ens ens-stateofus-eth
:state :resolve-ens}
(deftest search-empty-string-test
(is (= (core/set-new-identity {:db {:contacts/new-identity :foo}} "")
{:db {}})))
ckey {:user-public-key user-ukey
:input ckey
:id ckey
:type :compressed-key
:state :decompress-key}
(deftest search-uncompressed-key-test
(is (= (core/set-new-identity {:db {}} ukey)
{:db {:contacts/new-identity
{:input ukey
:public-key ukey
:state :error
:error :uncompressed-key}}})))
link-ckey {:user-public-key user-ukey
:input link-ckey
:id ckey
:type :compressed-key
:state :decompress-key}
link-ens {:user-public-key user-ukey
:input link-ens
:id ens
:type :ens
:ens ens-stateofus-eth
:state :resolve-ens}))
;;; event handler tests (no callbacks)
(def db
{:multiaccount {:public-key user-ukey}
:networks/current-network "mainnet_rpc"
:networks/networks {"mainnet_rpc"
{:id "mainnet_rpc"
:config {:NetworkId 1}}}})
(deftest set-new-identity-test
(with-redefs [events/dispatcher (fn [& args] args)]
(are [i edb] (= (events/set-new-identity {:db db} i nil) edb)
"" {:db db}
ukey {:db (assoc db
:contacts/new-identity
(events/init-contact
{:user-public-key user-ukey
:input ukey
:id ukey
:type :public-key
:public-key ukey
:state :invalid
:msg :t/not-a-chatkey}))}
ens {:db (assoc db
:contacts/new-identity
(events/init-contact
{:user-public-key user-ukey
:input ens
:id ens
:type :ens
:ens ens-stateofus-eth
:public-key nil ; not yet...
:state :resolve-ens}))
:contacts/resolve-public-key-from-ens
{:chain-id 1
:ens ens-stateofus-eth
:on-success [:contacts/set-new-identity-success ens]
:on-error [:contacts/set-new-identity-error ens]}}
;; compressed-key & add-self-as-contact
user-ckey {:db (assoc db
:contacts/new-identity
(events/init-contact
{:user-public-key user-ukey
:input user-ckey
:id user-ckey
:type :compressed-key
:public-key nil ; not yet...
:state :decompress-key}))
:contacts/decompress-public-key
{:compressed-key user-ckey
:on-success [:contacts/set-new-identity-success user-ckey]
:on-error [:contacts/set-new-identity-error user-ckey]}})))
@@ -32,7 +32,7 @@
{:style {:flex-direction :row
:justify-content :space-between}})
(def container-invalid
(def container-error
{:style {:flex-direction :row
:align-items :center
:margin-top 8}})
@@ -64,18 +64,18 @@
colors/neutral-50
colors/neutral-40)}})
(def icon-invalid
(def icon-error
{:size 16
:color colors/danger-50})
(def text-invalid
(def text-error
{:size :paragraph-2
:align :left
:style {:margin-left 4
:color colors/danger-50}})
(defn text-input-container
[invalid?]
[error?]
{:style {:padding-top 1
:padding-left 12
:padding-right 7
@@ -88,7 +88,7 @@
colors/neutral-95)
:border-width 1
:border-radius 12
:border-color (if invalid?
:border-color (if error?
colors/danger-50-opa-40
(colors/theme-colors
colors/neutral-20
@@ -4,7 +4,6 @@
[quo2.core :as quo]
[react-native.core :as rn]
[react-native.clipboard :as clipboard]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.utils.utils :as utils]
@@ -45,78 +44,60 @@
(defn new-contact
[]
(let [clipboard (reagent/atom nil)
default-value (reagent/atom nil)]
(fn []
(clipboard/get-string #(reset! clipboard %))
(let [{:keys [input scanned public-key ens state msg]}
(rf/sub [:contacts/new-identity])
invalid? (= state :invalid)
show-paste-button? (and (not (string/blank? @clipboard))
(string/blank? @default-value)
(string/blank? input))]
[rn/keyboard-avoiding-view (style/container-kbd)
[rn/view style/container-image
[rn/image
{:source (resources/get-image :add-new-contact)
:style style/image}]
[quo/button
(merge (style/button-close)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back]))}) :i/close]]
[rn/view (style/container-outer)
[rn/view style/container-inner
[quo/text (style/text-title)
(i18n/label :t/add-a-contact)]
[quo/text (style/text-subtitle)
(i18n/label :t/find-your-friends)]
[quo/text (style/text-description)
(i18n/label :t/ens-or-chat-key)]
[rn/view style/container-text-input
[rn/view (style/text-input-container invalid?)
[rn/text-input
(merge (style/text-input)
{:default-value (or scanned @default-value input)
:placeholder (i18n/label :t/type-some-chat-key)
:on-change-text (fn [v]
(reset! default-value v)
(debounce/debounce-and-dispatch
[:contacts/set-new-identity v nil]
600))})]
(when show-paste-button?
[quo/button
(merge style/button-paste
{:on-press
(fn []
(reset! default-value @clipboard)
(rf/dispatch
[:contacts/set-new-identity @clipboard nil]))})
(i18n/label :t/paste)])]
[quo/button
(merge style/button-qr
{:on-press #(rf/dispatch
[::qr-scanner/scan-code
{:handler :contacts/qr-code-scanned}])})
:i/scan]]
(when invalid?
[rn/view style/container-invalid
[quo/icon :i/alert style/icon-invalid]
[quo/text style/text-invalid
(i18n/label (or msg :t/invalid-ens-or-key))]])
(when (= state :valid)
[found-contact public-key])]
[rn/view
(let [{:keys [input public-key state error ens-name]} (rf/sub [:contacts/new-identity])
error? (and (= state :error)
(= error :uncompressed-key))]
[rn/keyboard-avoiding-view (style/container-kbd)
[rn/view style/container-image
[rn/image
{:source (resources/get-image :add-new-contact)
:style style/image}]
[quo/button
(merge (style/button-close)
{:on-press
(fn []
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back]))}) :i/close]]
[rn/view (style/container-outer)
[rn/view style/container-inner
[quo/text (style/text-title)
(i18n/label :t/add-a-contact)]
[quo/text (style/text-subtitle)
(i18n/label :t/find-your-friends)]
[quo/text (style/text-description)
(i18n/label :t/ens-or-chat-key)]
[rn/view style/container-text-input
[rn/view (style/text-input-container error?)
[rn/text-input
(merge (style/text-input)
{:default-value input
:placeholder (i18n/label :t/type-some-chat-key)
:on-change-text #(debounce/debounce-and-dispatch
[:contacts/set-new-identity %]
600)})]
(when (string/blank? input)
[quo/button
(merge (style/button-view-profile state)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile public-key ens]))})
(i18n/label :t/view-profile)]]]]))))
(merge style/button-paste
{:on-press (fn []
(clipboard/get-string #(rf/dispatch [:contacts/set-new-identity %])))})
(i18n/label :t/paste)])]
[quo/button
(merge style/button-qr
{:on-press #(rf/dispatch [::qr-scanner/scan-code
{:handler :contacts/qr-code-scanned}])})
:i/scan]]
(when error?
[rn/view style/container-error
[quo/icon :i/alert style/icon-error]
[quo/text style/text-error (i18n/label :t/not-a-chatkey)]])
(when (= state :valid)
[found-contact public-key])]
[rn/view
[quo/button
(merge (style/button-view-profile state)
{:on-press
(fn []
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile public-key ens-name]))})
(i18n/label :t/view-profile)]]]]))
+5 -4
View File
@@ -202,9 +202,9 @@
(rf/defn navigate-to-chat
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
{:events [:chat/navigate-to-chat]}
[{db :db :as cofx} chat-id]
[{db :db :as cofx} chat-id from-shell?]
(rf/merge cofx
{:dispatch [:navigate-to :chat chat-id]}
{:dispatch [:navigate-to-nav2 :chat chat-id from-shell?]}
(when-not (or (= (:view-id db) :community) (= (:view-id db) :community-overview))
(navigation/pop-to-root :shell-stack))
(close-chat false)
@@ -342,8 +342,9 @@
(rf/defn navigate-to-lightbox
{:events [:chat.ui/navigate-to-lightbox]}
[{:keys [db]} shared-element-id screen-params]
(reagent/next-tick #(rf/dispatch [:navigate-to :lightbox screen-params]))
{:db (assoc db :shared-element-id shared-element-id)})
(let [updated-db (assoc db :shared-element-id shared-element-id)]
(reagent/next-tick #(rf/dispatch [:navigate-to :lightbox screen-params]))
{:db updated-db}))
(rf/defn exit-lightbox-signal
{:events [:chat.ui/exit-lightbox-signal]}
@@ -88,7 +88,7 @@
(let [chat-id "test_chat"
db {:pagination-info {chat-id {:all-loaded? true}}}]
(testing "Pagination info should be reset on navigation"
(let [res (chat/navigate-to-chat {:db db} chat-id)]
(let [res (chat/navigate-to-chat {:db db} chat-id false)]
(is (nil? (get-in res [:db :pagination-info chat-id :all-loaded?])))))))
(deftest camera-roll-loading-more-test
@@ -65,7 +65,7 @@
(anim/animate background-color :transparent)
(anim/animate opacity 0)
(rf/dispatch (if platform/ios?
[:chat.ui/exit-lightbox-signal @index]
[:navigate-back]
[:navigate-back])))
:style style/close-container}
[quo/icon :close {:size 20 :color colors/white}]]
@@ -3,6 +3,7 @@
[clojure.string :as string]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[react-native.navigation :as navigation]
[react-native.orientation :as orientation]
[react-native.platform :as platform]
@@ -130,7 +131,7 @@
;; The initial value of data is the image that was pressed (and not the whole album) in order
;; for the transition animation to execute properly, otherwise it would animate towards
;; outside the screen (even if we have `initialScrollIndex` set).
data (reagent/atom (if (number? index) [(nth messages index)] []))
data (reagent/atom [(nth messages index)])
scroll-index (reagent/atom index)
transparent? (reagent/atom false)
set-full-height? (reagent/atom false)
@@ -189,6 +190,7 @@
(rf/dispatch [:chat.ui/zoom-out-signal nil])
(when platform/android?
(rf/dispatch [:chat.ui/lightbox-scale 1])))))
[:f>
(fn []
(let [curr-orientation (or (rf/sub [:lightbox/orientation]) orientation/portrait)
@@ -202,13 +204,18 @@
window-height
window-width)
item-width (if (and landscape? platform/ios?) screen-height screen-width)]
;[gesture/flat-list
; {:data [1]
; :horizontal true
; :render-fn (fn [] [rn/view {:style {:width 300 :height 300 :background-color :red}
; :native-ID :shared-element}])}]
[reanimated/view
{:style (reanimated/apply-animations-to-style {:background-color (:background-color
animations)}
{:height screen-height})}
(when-not @transparent?
[top-view/top-view (first messages) insets scroll-index animations derived landscape?
screen-width])
;(when-not @transparent?
; [top-view/top-view (first messages) insets scroll-index animations derived landscape?
; screen-width])
[gesture/gesture-detector
{:gesture (drag-gesture animations (and landscape? platform/ios?) set-full-height?)}
[reanimated/view
@@ -221,7 +228,8 @@
:key-fn :message-id
:style {:width (+ screen-width seperator-width)}
:data @data
:render-fn image
:render-fn (fn [] [rn/view {:style {:width 300 :height 300 :background-color :red}
:native-ID :shared-element}])
:render-data {:opacity-value (:opacity animations)
:border-value (:border animations)
:transparent? transparent?
@@ -240,6 +248,9 @@
:shows-vertical-scroll-indicator false
:shows-horizontal-scroll-indicator false
:on-viewable-items-changed callback}]]]
(when (and (not @transparent?) (not landscape?))
[bottom-view/bottom-view messages index scroll-index insets animations derived
item-width atoms])]))]))])
;(when (and (not @transparent?) (not landscape?))
; [bottom-view/bottom-view messages index scroll-index insets animations derived
; item-width atoms])
]
))]
))])
@@ -13,5 +13,3 @@
(def ^:const velocity-factor 0.5)
(def ^:const default-duration 300)
(def ^:const default-dimension 300)

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