Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd3a1172b3 | ||
|
|
8c9d351f14 | ||
|
|
3e93aba011 | ||
|
|
8d43a6d5be | ||
|
|
ff3ba6c0f0 | ||
|
|
3483bb1107 | ||
|
|
1f1ab30a4e | ||
|
|
064204256e | ||
|
|
8923408972 | ||
|
|
52b87bab3e | ||
|
|
25d44b11f1 | ||
|
|
9333692830 | ||
|
|
4fe8b81bf6 | ||
|
|
4dfd3af7f5 | ||
|
|
11b6702939 | ||
|
|
39c39915a7 | ||
|
|
01c058fecc | ||
|
|
8f75874868 | ||
|
|
041622d98b | ||
|
|
4190dfd26b | ||
|
|
f731f75fca | ||
|
|
78682b823b | ||
|
|
7d9709ee67 | ||
|
|
aec1b5fafa | ||
|
|
5c67216b31 | ||
|
|
0c9a195ca9 | ||
|
|
06192e7a24 | ||
|
|
4a6e42c6f9 | ||
|
|
2ce4a820d7 | ||
|
|
b72f0d4702 | ||
|
|
b75e1304d8 | ||
|
|
c2782a26f7 | ||
|
|
fa03e91080 | ||
|
|
f9dda56310 | ||
|
|
51276237f2 | ||
|
|
c667d05929 | ||
|
|
e1bcc8fec4 | ||
|
|
f84c2ec9f5 | ||
|
|
80f063d0dd | ||
|
|
69c3a72357 | ||
|
|
c28b34ac08 | ||
|
|
b192e9efd4 | ||
|
|
6c7054b5b4 | ||
|
|
1806cb792a | ||
|
|
432f7bcd8c | ||
|
|
26d618e305 | ||
|
|
fac2f952d0 | ||
|
|
e830f633d8 | ||
|
|
6a58f9552d | ||
|
|
00db44ab0d | ||
|
|
6ffed4ad47 | ||
|
|
e2169cbbd4 | ||
|
|
c8fd7121d3 | ||
|
|
0c96661583 | ||
|
|
d6c09d289c | ||
|
|
d5cc24fecf | ||
|
|
20e16e2f42 | ||
|
|
3fc4c36ac6 | ||
|
|
1b33aa4988 | ||
|
|
888bf12856 | ||
|
|
c4aef97a6d |
@@ -0,0 +1,47 @@
|
||||
library 'status-jenkins-lib@v1.6.6'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'linux'
|
||||
}
|
||||
|
||||
triggers {
|
||||
cron('H 5 * * *')
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 15, unit: 'MINUTES')
|
||||
/* Disable concurrent jobs */
|
||||
disableConcurrentBuilds()
|
||||
/* Don't keep more than 50 builds */
|
||||
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Get Nodes') {
|
||||
steps { script {
|
||||
stagePerNode = nodesByLabel('macos').collectEntries {
|
||||
["${it}" : generateNodeCleanupStage(it)]
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Clean Xcode') {
|
||||
steps { script {
|
||||
parallel stagePerNode
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def generateNodeCleanupStage(nodeLabel) {
|
||||
return { stage(nodeLabel) {
|
||||
node(nodeLabel) {
|
||||
dir('/Users/jenkins/Library/Developer/Xcode') {
|
||||
sh 'rm -fr Archives DerivedData'
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
@@ -525,8 +525,8 @@
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "set -o errexit\nexport NODE_BINARY=\"node\"\nexport NODE_ARGS=\" --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./react-native-xcode.log 2>&1";
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\" --openssl-legacy-provider --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./react-native-xcode.log 2>&1";
|
||||
};
|
||||
0F876BD5356F61BF142A01A0 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -546,7 +546,7 @@
|
||||
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-StatusImTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
@@ -568,7 +568,7 @@
|
||||
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
@@ -583,8 +583,8 @@
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "set -o errexit\nexport NODE_BINARY=\"node\"\nexport NODE_ARGS=\" --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./react-native-xcode.log 2>&1";
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\" --openssl-legacy-provider --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./react-native-xcode.log 2>&1";
|
||||
};
|
||||
3AAD2AD724A3A60E0075D594 /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -597,7 +597,7 @@
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./set_xcode_version.log 2>&1";
|
||||
};
|
||||
3C1038075AE5E6FB86AC2319 /* [CP] Copy Pods Resources */ = {
|
||||
@@ -618,7 +618,7 @@
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
@@ -640,7 +640,7 @@
|
||||
"$(DERIVED_FILE_DIR)/Pods-Status-StatusImPR-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
@@ -662,7 +662,7 @@
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
@@ -677,7 +677,7 @@
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./set_xcode_version.log 2>&1";
|
||||
};
|
||||
E732E3E1B024946173BF6D3D /* [CP] Copy Pods Resources */ = {
|
||||
@@ -698,7 +698,7 @@
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellPath = "/usr/bin/env sh";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ let
|
||||
mkdir -p $out
|
||||
cd $out
|
||||
'' +
|
||||
# TODO: Generalize this section to not repeat the same code.
|
||||
(concatMapStrings (dep:
|
||||
let
|
||||
url = "${dep.host}/${dep.path}";
|
||||
@@ -33,6 +34,13 @@ let
|
||||
jar-download = optionalString (jar.sha256 != "") (
|
||||
fetchurl { url = "${url}.${dep.type}"; inherit (jar) sha256; }
|
||||
);
|
||||
nodeps = {
|
||||
sha1 = attrByPath [ "nodeps" "sha1" ] "" dep;
|
||||
sha256 = attrByPath [ "nodeps" "sha256" ] "" dep;
|
||||
};
|
||||
nodeps-download = optionalString (nodeps.sha256 != "") (
|
||||
fetchurl { url = "${url}-nodeps.jar"; inherit (nodeps) sha256; }
|
||||
);
|
||||
fileName = last (splitString "/" dep.path);
|
||||
directory = removeSuffix fileName dep.path;
|
||||
in
|
||||
@@ -51,6 +59,12 @@ let
|
||||
${optionalString (jar.sha1 != "") ''
|
||||
echo "${jar.sha1}" > "${dep.path}.${dep.type}.sha1"
|
||||
''}
|
||||
${optionalString (nodeps-download != "") ''
|
||||
ln -s "${nodeps-download}" "${dep.path}-nodeps.jar"
|
||||
''}
|
||||
${optionalString (nodeps.sha1 != "") ''
|
||||
echo "${nodeps.sha1}" > "${dep.path}.${dep.type}.sha1"
|
||||
''}
|
||||
'')
|
||||
deps));
|
||||
|
||||
|
||||
@@ -4018,30 +4018,30 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/github/status-im/status-keycard-java/android/3.0.4/android-3.0.4",
|
||||
"path": "com/github/status-im/status-keycard-java/android/3.1.1/android-3.1.1",
|
||||
"host": "https://jitpack.io",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "e6e1933d85ac05b51953effc21ab893679f5864b",
|
||||
"sha256": "1y9kqp3qgx3kqaf6vm6iwphdj8caqd9x6kncjsnp6f0nirp5ijzq"
|
||||
"sha1": "ac7e6699628e329dfc028345f32bc41c5d6c2f33",
|
||||
"sha256": "12qh5qwncj2gbv6g1whz32rliap34mv2kxlyqv2ivg5jc6yfvyhj"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "dca6e47e087a649643bbad1c1feb4b0b5e1aaf45",
|
||||
"sha256": "0krxjj5h5zmap4645llscwkmyszm8qyngwg8vi8ds1mf2kp0jaz1"
|
||||
"sha1": "26118061c0996fff357ae30cc360e5928c8dd455",
|
||||
"sha256": "15m0h4ri0ny7jz4vvl25blw5s65iivlv5gchw0j5n0jblr1wr270"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/github/status-im/status-keycard-java/lib/3.0.4/lib-3.0.4",
|
||||
"path": "com/github/status-im/status-keycard-java/lib/3.1.1/lib-3.1.1",
|
||||
"host": "https://jitpack.io",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "718d3d286d53186552a84cee1a1283e0975da789",
|
||||
"sha256": "0s2mbx1638qig4m802rf0ill9bghgga8w3ld0vpcz6x7h2kmvv6g"
|
||||
"sha1": "63c7bbd55ddbf88d1b89941f78158aa07fb46873",
|
||||
"sha256": "1x0n0xq6zgg5qj6s6j9sjpy3zbggfznr64pb6sjh2882y4d1j6qi"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "b2afa2711a9898d9aeb188195edde53c00984543",
|
||||
"sha256": "16c7r0667pbgljx1p8zmvahv1igcnway1qjqprbn0n4ny1vy2imm"
|
||||
"sha1": "07f0374f17160c8731350316226ffe0de50f6f31",
|
||||
"sha256": "1bfvb0ynxa0ws46cqmyx6d960pyg7hjxv3xwx7mg0xw03xk2bam1"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5778,6 +5778,10 @@
|
||||
"jar": {
|
||||
"sha1": "de8c77583e97bbbd3cdbe5f406b583e9b081ff56",
|
||||
"sha256": "0435ff3qzmcxprsm93x3aw9clgfpa871zl41izhijwm3bwib9yfy"
|
||||
},
|
||||
"nodeps": {
|
||||
"sha1": "273cc1869ddf7ebbac8176402e29f41b1c83d7df",
|
||||
"sha256": "1w4a2ak60r46wiy8yl00yy8v397qa2zja5jmsd7wsk1p2sjyqn9z"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6930,12 +6934,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/sun/xml/bind/jaxb-bom-ext/4.0.1/jaxb-bom-ext-4.0.1",
|
||||
"path": "com/sun/xml/bind/jaxb-bom-ext/4.0.2/jaxb-bom-ext-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "6916f1573d78b0d41b629257277da86215ea7a6f",
|
||||
"sha256": "069gm0wclljzdjn5j29hizhc4rakszk8kgzmsx66h5fkvlcvgd5b"
|
||||
"sha1": "600924984be6a63e1c38d5f6ef0637a070002937",
|
||||
"sha256": "1jsdpynkd7d7bqp81ajcy7fa2riz9wnl8rb81icd8shv7awnkbfx"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6950,12 +6954,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/sun/xml/bind/mvn/jaxb-parent/4.0.1/jaxb-parent-4.0.1",
|
||||
"path": "com/sun/xml/bind/mvn/jaxb-parent/4.0.2/jaxb-parent-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "315ec09b889041008f815ddd41cca9633ee50cc4",
|
||||
"sha256": "1bpqac2a25qq81h99zvj20n9ac2hd8iry7mnwisvd4f8avpm272i"
|
||||
"sha1": "160938bb66dc61a4839edaad77a5b7b7f9f5171d",
|
||||
"sha256": "184avj0jpjz1rsxrrw88yn31yxkvw1l3blyq6fs4sbmgac12dvqc"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6980,12 +6984,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/sun/xml/bind/mvn/jaxb-txw-parent/4.0.1/jaxb-txw-parent-4.0.1",
|
||||
"path": "com/sun/xml/bind/mvn/jaxb-txw-parent/4.0.2/jaxb-txw-parent-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "0f5e6242fe24ccd5e4c663dc66f7b935b4cffb55",
|
||||
"sha256": "1niyxycc1k9qb0hpkb30zcccai28pq4yhy9a8p45d24zgrvdgs1a"
|
||||
"sha1": "c9c99b4e33782535b5988616bc3b452543cb48e5",
|
||||
"sha256": "0xxyqayffjwdmagqa6jqca8ykl3iz2vhw59l6478nv8ir268x2rn"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7650,12 +7654,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/antlr/antlr4-master/4.11.1/antlr4-master-4.11.1",
|
||||
"path": "org/antlr/antlr4-master/4.12.0/antlr4-master-4.12.0",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "298ecf68d872658e1d92457168018bd5b8fff245",
|
||||
"sha256": "1b80dq56qs5rqzbvq5pyf2pcsgfmmfmsmznhbxw1armvvbl5vskj"
|
||||
"sha1": "5cd9d694d06e046886a7a8e54d70b22bc03af4a3",
|
||||
"sha256": "0x3rhw76nrzh35d8liq9wffm74rshxwg944xc55c3qlcwlxg3xj2"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7674,16 +7678,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/antlr/antlr4-runtime/4.11.1/antlr4-runtime-4.11.1",
|
||||
"path": "org/antlr/antlr4-runtime/4.12.0/antlr4-runtime-4.12.0",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "b76aa0c70639f8b3112e4d5e14abf951cb38761c",
|
||||
"sha256": "0d0vd3nh9f2aqy4njx4d0qh7jwha83crmxkyplgmk307b4lyqmn4"
|
||||
"sha1": "3113149fe4ea467b27f14f2b99096cac9d4ca53a",
|
||||
"sha256": "1r3isigbls4i2ldc4kyq3kzv2klcgz7przyq3knz02aasrzm95n6"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "069214c1de1960040729702eb58deac8827135e7",
|
||||
"sha256": "0nfsdach3x0vyv1isnvvjp7hif0kdzyb1i1f0lv4vhfcq59nav70"
|
||||
"sha1": "dd105cf6ac9f7417b3782c178f6dbd06bf75df57",
|
||||
"sha256": "0d6sd7jrxfxd7qp5gbsd8vdq6wp1r2iww189g76i0vkxj8s3ndfv"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8540,16 +8544,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/checkerframework/checker-qual/3.29.0/checker-qual-3.29.0",
|
||||
"path": "org/checkerframework/checker-qual/3.31.0/checker-qual-3.31.0",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "76bd5ffeef4d9b039e6445e2674264dbc5bfb94c",
|
||||
"sha256": "0azs4ndih02r5a3fvn08sndwc58ymzma2krqclfz6pivmfrxcyp2"
|
||||
"sha1": "a600a4210e8c3db6ea45ea0989920b0255dbb6f6",
|
||||
"sha256": "0cajb4ivvw446lc3bcwl49difmpgg1rrcbzklxc87rs7pqz9qms3"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "a805a761b7a734d69f9c1766ead1ff78698a1497",
|
||||
"sha256": "1hb8ajlszzvh3cimvzkwgkx2689rh131jh7259a7s94cvzjq1p77"
|
||||
"sha1": "eeefd4af42e2f4221d145c1791582f91868f99ab",
|
||||
"sha256": "1fai6kk72j76ivgipgl7ckbcn8g8yl289pbx712zpii2dm3mzvqw"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8775,6 +8779,16 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/eclipse/ee4j/project/1.0.8/project-1.0.8",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "41a621037931f9f4aa8768694be9f5cb59df83df",
|
||||
"sha256": "0jv7vwx72mx30ydlhk5ql3q8zb67m2qpw43f4inaypm3aip7n30d"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
@@ -8828,12 +8842,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/glassfish/jaxb/jaxb-bom/4.0.1/jaxb-bom-4.0.1",
|
||||
"path": "org/glassfish/jaxb/jaxb-bom/4.0.2/jaxb-bom-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "pom",
|
||||
"pom": {
|
||||
"sha1": "99d85661aef6ac9f6bfb6af0f0ea507d054b91e1",
|
||||
"sha256": "151zbrywjzbnmwqg246iyz0bqnx2hh730hxmig62vh67s2nbw8lm"
|
||||
"sha1": "12668536ac24e77398bd675a1e458c1824d156c7",
|
||||
"sha256": "08bgmpyhps9h25z6950g7751zg6g5vkvn02v1znamarlaw2niyl6"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8852,16 +8866,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/glassfish/jaxb/jaxb-core/4.0.1/jaxb-core-4.0.1",
|
||||
"path": "org/glassfish/jaxb/jaxb-core/4.0.2/jaxb-core-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "e366262bbe2037088461f748896f6aa4afcfd3c6",
|
||||
"sha256": "14d3d3p0c42qd8jq8mxmpymd17x5zxixhyccwfmxkr24ad9pvj46"
|
||||
"sha1": "9aecfe4442b96fc3f9cabc25e7c6e310972d674e",
|
||||
"sha256": "00yij4s17cvixysjdjrzc51jd07fpcc11jy4lgg1z8zfvx6zdhma"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "b4707bb31dfcf54ae424b930741f0cd62d672af9",
|
||||
"sha256": "19v525w4qb65czx1v31k5lz0yan9vc030h736iqgz59l2048hf3l"
|
||||
"sha1": "08c29249f6c10f4ee08967783831580b0f5c5360",
|
||||
"sha256": "1k8c8wf420nmqyhyr6p0ns12mx127bzwq71rp6x0nj3qmma2kzyp"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8894,16 +8908,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/glassfish/jaxb/txw2/4.0.1/txw2-4.0.1",
|
||||
"path": "org/glassfish/jaxb/txw2/4.0.2/txw2-4.0.2",
|
||||
"host": "https://repo.maven.apache.org/maven2",
|
||||
"type": "jar",
|
||||
"pom": {
|
||||
"sha1": "160273691bf3ffa0745bf86453dd56c62ec23ac2",
|
||||
"sha256": "03zv45jgmppikcqk7gq01pyryzvam3qnllc5q7jjywvnq5mjdvvp"
|
||||
"sha1": "f8eef3319522b021e51123ea88d6ab4d484d2c59",
|
||||
"sha256": "1ry99inn7v0fpgfrnhj3h4qnhaccmksn8vsrgfn1ysj6cqrfgc8p"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "797720dfe2e15504f6014fb82eb873051a653c75",
|
||||
"sha256": "1aba3rk9jm66k65vx95a92sdapbsvfbsvii26s8y9rach44p9m7l"
|
||||
"sha1": "24e167be69c29ebb7ee0a3b1f9b546f1dfd111fc",
|
||||
"sha256": "036gl0lp8y83zxy01pyzvq169i0r03lhm169fw7m6hha9wp92wga"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -357,8 +357,8 @@ com.github.bumptech.glide:glide:4.12.0
|
||||
com.github.bumptech.glide:okhttp3-integration:4.12.0
|
||||
com.github.clans:fab:1.6.4
|
||||
com.github.gundy:semver4j:0.16.4
|
||||
com.github.status-im.status-keycard-java:android:3.0.4
|
||||
com.github.status-im.status-keycard-java:lib:3.0.4
|
||||
com.github.status-im.status-keycard-java:android:3.1.1
|
||||
com.github.status-im.status-keycard-java:lib:3.1.1
|
||||
com.github.status-im:function:0.0.1
|
||||
com.github.wix-playground:ahbottomnavigation:3.3.0
|
||||
com.github.wix-playground:reflow-animator:1.0.6
|
||||
|
||||
@@ -285,8 +285,8 @@ https://dl.google.com/dl/android/maven2/com/google/android/material/material/1.0
|
||||
https://dl.google.com/dl/android/maven2/com/google/android/material/material/1.2.0-alpha03/material-1.2.0-alpha03.pom
|
||||
https://jitpack.io/com/github/Dimezis/BlurView/version-2.0.2/BlurView-version-2.0.2.pom
|
||||
https://jitpack.io/com/github/status-im/function/0.0.1/function-0.0.1.pom
|
||||
https://jitpack.io/com/github/status-im/status-keycard-java/android/3.0.4/android-3.0.4.pom
|
||||
https://jitpack.io/com/github/status-im/status-keycard-java/lib/3.0.4/lib-3.0.4.pom
|
||||
https://jitpack.io/com/github/status-im/status-keycard-java/android/3.1.1/android-3.1.1.pom
|
||||
https://jitpack.io/com/github/status-im/status-keycard-java/lib/3.1.1/lib-3.1.1.pom
|
||||
https://jitpack.io/com/github/wix-playground/ahbottomnavigation/3.3.0/ahbottomnavigation-3.3.0.pom
|
||||
https://jitpack.io/com/github/wix-playground/reflow-animator/1.0.6/reflow-animator-1.0.6.pom
|
||||
https://jitpack.io/com/github/yalantis/ucrop/2.2.6-native/ucrop-2.2.6-native.pom
|
||||
@@ -503,12 +503,12 @@ https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons-runtime/4.1.1
|
||||
https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons/2.21/istack-commons-2.21.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons/4.1.1/istack-commons-4.1.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/2.2.11/jaxb-bom-ext-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/4.0.1/jaxb-bom-ext-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/4.0.2/jaxb-bom-ext-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/2.2.11/jaxb-parent-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/4.0.1/jaxb-parent-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/4.0.2/jaxb-parent-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-runtime-parent/2.2.11/jaxb-runtime-parent-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/2.2.11/jaxb-txw-parent-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/4.0.1/jaxb-txw-parent-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/4.0.2/jaxb-txw-parent-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/FastInfoset/1.2.13/FastInfoset-1.2.13.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/FastInfoset/2.1.0/FastInfoset-2.1.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/fastinfoset-project/1.2.13/fastinfoset-project-1.2.13.pom
|
||||
@@ -561,9 +561,9 @@ https://repo.maven.apache.org/maven2/org/antlr/ST4/4.0.8/ST4-4.0.8.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/ST4/4.3.4/ST4-4.3.4.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.5.2-1/antlr4-master-4.5.2-1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.5.3/antlr4-master-4.5.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.11.1/antlr4-master-4.11.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-master/4.12.0/antlr4-master-4.12.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-runtime/4.5.2-1/antlr4-runtime-4.5.2-1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-runtime/4.11.1/antlr4-runtime-4.11.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4-runtime/4.12.0/antlr4-runtime-4.12.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr4/4.5.3/antlr4-4.5.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr-master/3.3/antlr-master-3.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/antlr/antlr-master/3.5.2/antlr-master-3.5.2.pom
|
||||
@@ -636,7 +636,7 @@ https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.56/bcprov
|
||||
https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.pom
|
||||
https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.70/bcprov-jdk15on-1.70.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.29.0/checker-qual-3.29.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.31.0/checker-qual-3.31.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/codehaus-parent/4/codehaus-parent-4.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy-all/2.4.15/groovy-all-2.4.15.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.pom
|
||||
@@ -656,16 +656,17 @@ https://repo.maven.apache.org/maven2/org/easymock/easymock/5.1.0/easymock-5.1.0.
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/angus/angus-activation-project/2.0.0/angus-activation-project-2.0.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/angus/angus-activation/2.0.0/angus-activation-2.0.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/ee4j/project/1.0.7/project-1.0.7.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/ee4j/project/1.0.8/project-1.0.8.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.4/ecj-4.4.pom
|
||||
https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.6.1/ecj-4.6.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/2.2.11/jaxb-bom-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/4.0.1/jaxb-bom-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/4.0.2/jaxb-bom-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/2.2.11/jaxb-core-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/4.0.1/jaxb-core-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/4.0.2/jaxb-core-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-runtime/2.2.11/jaxb-runtime-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/2.2.11/txw2-2.2.11.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/4.0.1/txw2-4.0.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/4.0.2/txw2-4.0.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom
|
||||
https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/2.2/hamcrest-core-2.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom
|
||||
|
||||
@@ -36,6 +36,11 @@ function match_repo_url() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
function pom_has_nodeps_jar() {
|
||||
grep '<shadedClassifierName>nodeps</shadedClassifierName>' $1 \
|
||||
2>&1 >/dev/null
|
||||
}
|
||||
|
||||
if [[ -z "${1}" ]]; then
|
||||
echo "Required argument not given!" >&2
|
||||
exit 1
|
||||
@@ -96,6 +101,16 @@ if [[ "${OBJ_TYPE}" != "pom" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Some deps include nodeps JARs which include.
|
||||
if pom_has_nodeps_jar "${POM_PATH}"; then
|
||||
NODEPS_NIX_FETCH_OUT=$(nix_fetch "${OBJ_REL_URL}-nodeps.jar")
|
||||
if [[ ${?} -eq 0 ]]; then
|
||||
NODEPS_PATH=$(get_nix_path "${NODEPS_NIX_FETCH_OUT}")
|
||||
NODEPS_SHA256=$(get_nix_sha "${NODEPS_NIX_FETCH_OUT}")
|
||||
NODEPS_SHA1=$(get_sha1 "${NODEPS_PATH}")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Format into a Nix attrset entry
|
||||
echo -ne "
|
||||
{
|
||||
@@ -114,6 +129,13 @@ if [[ -n "${OBJ_SHA256}" ]]; then
|
||||
\"jar\": {
|
||||
\"sha1\": \"${OBJ_SHA1}\",
|
||||
\"sha256\": \"${OBJ_SHA256}\"
|
||||
}";[[ -n "${NODEPS_SHA256}" ]] && echo -n ","
|
||||
fi
|
||||
if [[ -n "${NODEPS_SHA256}" ]]; then
|
||||
echo -n "
|
||||
\"nodeps\": {
|
||||
\"sha1\": \"${NODEPS_SHA1}\",
|
||||
\"sha256\": \"${NODEPS_SHA256}\"
|
||||
}"
|
||||
fi
|
||||
echo -e "\n },"
|
||||
|
||||
@@ -20,6 +20,7 @@ in {
|
||||
];
|
||||
|
||||
# WARNING: Executes shellHook in reverse order.
|
||||
# WARNING: Only some variables are merged.
|
||||
inputsFrom = [
|
||||
fastlane.shell
|
||||
cocoapods-sh
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
{ mkShell, deps }:
|
||||
{ mkShell, nodejs, deps }:
|
||||
|
||||
mkShell {
|
||||
# check if node modules changed and if so install them
|
||||
# Check if node modules changed and if so install them.
|
||||
shellHook = ''
|
||||
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
|
||||
export NODE_OPTIONS="--openssl-legacy-provider";
|
||||
|
||||
# Fix Xcode using system Node.js version.
|
||||
export NODE_BINARY="${nodejs}/bin/node";
|
||||
|
||||
export STATUS_MOBILE_HOME=$(git rev-parse --show-toplevel)
|
||||
"$STATUS_MOBILE_HOME/nix/scripts/node_modules.sh" ${deps.nodejs-patched}
|
||||
'';
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"@react-native-community/push-notification-ios": "^1.4.1",
|
||||
"@react-native-community/slider": "^3.0.0",
|
||||
"@walletconnect/client": "^2.0.0-beta.23",
|
||||
"@walletconnect/client-legacy": "npm:@walletconnect/client@^1.7.1",
|
||||
"bignumber.js": "git+https://github.com/status-im/bignumber.js.git#refs/tags/v4.0.2-status",
|
||||
"chance": "^1.1.0",
|
||||
"create-react-class": "^15.6.2",
|
||||
@@ -62,6 +61,7 @@
|
||||
"react-native-lottie-splash-screen": "^1.0.1",
|
||||
"react-native-mail": "^6.1.1",
|
||||
"react-native-navigation": "^7.27.1",
|
||||
"react-native-orientation-locker": "^1.5.0",
|
||||
"react-native-permissions": "^2.1.5",
|
||||
"react-native-randombytes": "^3.6.1",
|
||||
"react-native-reanimated": "2.3.3",
|
||||
@@ -69,7 +69,7 @@
|
||||
"react-native-safe-area-context": "^2.0.0",
|
||||
"react-native-shake": "^3.3.1",
|
||||
"react-native-share": "^7.0.1",
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.38",
|
||||
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39",
|
||||
"react-native-svg": "^9.8.4",
|
||||
"react-native-touch-id": "^4.4.1",
|
||||
"react-native-webview": "git+https://github.com/status-im/react-native-webview.git#refs/tags/v11.16.0-status",
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 989 B |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 539 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 192 KiB |
|
Before Width: | Height: | Size: 601 B After Width: | Height: | Size: 601 B |
|
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 896 B |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 837 B After Width: | Height: | Size: 837 B |
|
Before Width: | Height: | Size: 998 B After Width: | Height: | Size: 998 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 377 KiB After Width: | Height: | Size: 377 KiB |
|
Before Width: | Height: | Size: 738 KiB After Width: | Height: | Size: 738 KiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
@@ -1,11 +1,9 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
CHANGES=$(git diff --no-ext-diff --diff-filter=d --cached --unified=0 --no-prefix --minimal --exit-code src/quo src/quo2 | grep '^+' || echo '')
|
||||
|
||||
INVALID_CHANGES=$(echo "$CHANGES" | grep -E '(re-frame/dispatch|rf/dispatch|re-frame/subscribe|rf/subscribe|rf/sub|<sub|>evt|status-im)')
|
||||
INVALID_CHANGES=$(grep -E -r '(re-frame/dispatch|rf/dispatch|re-frame/subscribe|rf/subscribe|rf/sub|<sub|>evt|status-im\.|status-im2\.)' './src/quo2')
|
||||
|
||||
if test -n "$INVALID_CHANGES"; then
|
||||
echo "re-frame dispatch/subscribe and status-im are not allowed in quo/quo2 components"
|
||||
echo "WARNING: re-frame, status-im are not allowed in quo2 components"
|
||||
echo ''
|
||||
echo "$INVALID_CHANGES"
|
||||
exit 1
|
||||
|
||||
@@ -139,6 +139,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
(def react-native-svg
|
||||
#js
|
||||
{:ClipPath #js {:render identity}
|
||||
:Circle #js {:render identity}
|
||||
:Defs #js {:render identity}
|
||||
:Path #js {:render identity}
|
||||
:Rect #js {:render identity}
|
||||
@@ -265,7 +266,15 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
|
||||
(def react-native-gesture-handler
|
||||
#js
|
||||
{:default #js {}
|
||||
{:FlatList #js {}
|
||||
:Gesture #js {:Pan nil}
|
||||
:GestureDetector #js {}
|
||||
:LongPressGestureHandler #js {}
|
||||
:NativeViewGestureHandler #js {}
|
||||
:PanGestureHandler #js {}
|
||||
:PureNativeButton #js {}
|
||||
:RectButton #js {}
|
||||
:ScrollView #js {}
|
||||
:State #js
|
||||
{:BEGAN nil
|
||||
:ACTIVE nil
|
||||
@@ -273,19 +282,13 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
:END nil
|
||||
:FAILED nil
|
||||
:UNDETERMINED nil}
|
||||
:PureNativeButton #js {}
|
||||
:Swipeable #js {}
|
||||
:TapGestureHandler #js {}
|
||||
:PanGestureHandler #js {}
|
||||
:TouchableHighlight #js {}
|
||||
:LongPressGestureHandler #js {}
|
||||
:TouchableWithoutFeedback #js {}
|
||||
:NativeViewGestureHandler #js {}
|
||||
:FlatList #js {}
|
||||
:ScrollView #js {}
|
||||
:TouchableOpacity #js {}
|
||||
:GestureDetector #js {}
|
||||
:Gesture #js {:Pan nil}
|
||||
:createNativeWrapper identity})
|
||||
:TouchableWithoutFeedback #js {}
|
||||
:createNativeWrapper identity
|
||||
:default #js {}})
|
||||
|
||||
(def react-native-redash #js {:clamp nil})
|
||||
|
||||
@@ -331,6 +334,10 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
(def react-native-camera-roll
|
||||
(clj->js {:default #js {}}))
|
||||
|
||||
(def react-native-orientation-locker
|
||||
(clj->js {:default #js {}
|
||||
:useDeviceOrientationChange #js {}}))
|
||||
|
||||
(def wallet-connect-client
|
||||
#js
|
||||
{:default #js {}
|
||||
@@ -396,6 +403,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
"react-native-share" react-native-share
|
||||
"@react-native-async-storage/async-storage" async-storage
|
||||
"react-native-svg" react-native-svg
|
||||
"react-native-orientation-locker" react-native-orientation-locker
|
||||
"../src/js/worklet_factory.js" worklet-factory
|
||||
"../src/js/shell_worklets.js" shell-worklets
|
||||
"../src/js/bottom_sheet.js" bottom-sheet
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.ui.components.fast-image :as fast-image]
|
||||
[quo2.components.animated-header-flatlist.style :as style]
|
||||
[oops.core :as oops]
|
||||
[utils.re-frame :as rf]))
|
||||
[oops.core :as oops]))
|
||||
|
||||
(def header-height 234)
|
||||
(def cover-height 192)
|
||||
@@ -51,10 +50,8 @@
|
||||
[reanimated/view {:style (style/entity-picture size-animation)}
|
||||
[display-picture-comp image-animation]]]))
|
||||
|
||||
|
||||
|
||||
(defn animated-header-list
|
||||
[{:keys [header-comp main-comp] :as parameters}]
|
||||
[{:keys [header-comp main-comp back-button-on-press] :as parameters}]
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
(let [window-height (:height (rn/get-window))
|
||||
@@ -76,7 +73,7 @@
|
||||
[rn/view {:style (style/container-view view-height)}
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:on-press back-button-on-press
|
||||
:style (style/button-container {:left 20})}
|
||||
[quo/icon :i/arrow-left {:size 20 :color (colors/theme-colors colors/black colors/white)}]]
|
||||
[rn/touchable-opacity
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
(ns quo2.components.avatars.user-avatar
|
||||
(:require [clojure.string :refer [blank? split upper-case]]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :refer [dark?]]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(def sizes
|
||||
{:big {:outer 80
|
||||
:inner 72
|
||||
:status-indicator 20
|
||||
:status-indicator-border 4
|
||||
:font-size :heading-1}
|
||||
:medium {:outer 48
|
||||
:inner 44
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-1}
|
||||
:small {:outer 32
|
||||
:inner 28
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-2}
|
||||
:xs {:outer 24
|
||||
:inner 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xxs {:outer 20
|
||||
:inner 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}
|
||||
:xxxs {:outer 16
|
||||
:inner 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}})
|
||||
|
||||
(defn dot-indicator
|
||||
[size status-indicator? online? ring? dark?]
|
||||
(when status-indicator?
|
||||
(let [dimensions (get-in sizes [size :status-indicator])
|
||||
border-width (get-in sizes [size :status-indicator-border])
|
||||
right (case size
|
||||
:big 2
|
||||
:medium 0
|
||||
:small -2
|
||||
0)
|
||||
bottom (case size
|
||||
:big (if ring?
|
||||
-1
|
||||
2)
|
||||
:medium (if ring?
|
||||
0
|
||||
-2)
|
||||
:small (if ring?
|
||||
-2
|
||||
-2)
|
||||
0)]
|
||||
[rn/view
|
||||
{:style {:background-color (if online?
|
||||
colors/success-50
|
||||
colors/neutral-40)
|
||||
:width dimensions
|
||||
:height dimensions
|
||||
:border-width border-width
|
||||
:border-radius dimensions
|
||||
:border-color (if dark?
|
||||
colors/neutral-100
|
||||
colors/white)
|
||||
:position :absolute
|
||||
:bottom bottom
|
||||
:right right}}])))
|
||||
|
||||
(defn container-styling
|
||||
[inner-dimensions outer-dimensions]
|
||||
{:width inner-dimensions
|
||||
:position :absolute
|
||||
:top (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:left (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:height inner-dimensions
|
||||
:border-radius inner-dimensions})
|
||||
|
||||
(defn container
|
||||
[inner-dimensions outer-dimensions & children]
|
||||
[rn/view
|
||||
{:style (merge {:background-color (colors/custom-color-by-theme :turquoise 50 60)
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
(container-styling inner-dimensions outer-dimensions))}
|
||||
children])
|
||||
|
||||
(def small-sizes #{:xs :xxs :xxxs})
|
||||
(def identicon-sizes #{:big :medium :small})
|
||||
|
||||
(defn user-avatar
|
||||
[{:keys [ring?
|
||||
online?
|
||||
size
|
||||
status-indicator?
|
||||
profile-picture
|
||||
full-name]
|
||||
:or {full-name "empty name"
|
||||
status-indicator? true
|
||||
online? true
|
||||
size :big
|
||||
ring? true}}]
|
||||
(let [initials (if full-name
|
||||
(reduce str (map first (split full-name " ")))
|
||||
"")
|
||||
first-initial-letter (if full-name
|
||||
(or (first full-name) "")
|
||||
"")
|
||||
identicon? (contains? identicon-sizes size)
|
||||
small? (contains? small-sizes size)
|
||||
outer-dimensions (get-in sizes [size :outer])
|
||||
inner-dimensions (get-in sizes
|
||||
[size
|
||||
(if ring?
|
||||
:inner
|
||||
:outer)])
|
||||
font-size (get-in sizes [size :font-size])
|
||||
icon-text (if-not (or (blank? first-initial-letter)
|
||||
(blank? initials))
|
||||
(if small?
|
||||
first-initial-letter
|
||||
initials)
|
||||
"")]
|
||||
[rn/view
|
||||
{:accessibility-label :user-avatar
|
||||
:style {:width outer-dimensions
|
||||
:height outer-dimensions
|
||||
:border-radius outer-dimensions}}
|
||||
(when (and false (and ring? identicon?)) ;;TODO not implemented yet
|
||||
[icons/icon :i/identicon-ring
|
||||
{:size outer-dimensions
|
||||
:no-color true}])
|
||||
(if profile-picture
|
||||
;; display image
|
||||
[fast-image/fast-image
|
||||
{:source profile-picture
|
||||
:style (container-styling inner-dimensions outer-dimensions)}]
|
||||
;; else display initials
|
||||
[container inner-dimensions outer-dimensions
|
||||
^{:key :icon-text}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size font-size
|
||||
:style {:color colors/white-opa-70}}
|
||||
(upper-case icon-text)]])
|
||||
[dot-indicator size status-indicator? online? ring? (dark?)]]))
|
||||
@@ -0,0 +1,127 @@
|
||||
(ns quo2.components.avatars.user-avatar.component-spec
|
||||
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[status-im2.common.resources :as resources]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- test-truthy [element]
|
||||
(.toBeTruthy (js/expect element)))
|
||||
|
||||
(defn- test-null [element]
|
||||
(.toBeNull (js/expect element)))
|
||||
|
||||
(h/describe "user avatar"
|
||||
(h/test "Default render"
|
||||
(h/render [user-avatar/user-avatar])
|
||||
(test-truthy (h/get-by-label-text :user-avatar))
|
||||
(test-truthy (h/get-by-text "EN")))
|
||||
|
||||
(h/describe "Profile picture"
|
||||
(h/test "Renders"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:profile-picture (resources/get-mock-image :user-picture-male4)}])
|
||||
(test-truthy (h/get-by-label-text :profile-picture)))
|
||||
|
||||
(h/test "Renders even if `:full-name` is passed"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:profile-picture (resources/get-mock-image :user-picture-male4)
|
||||
:full-name "New User1"}])
|
||||
(test-truthy (h/get-by-label-text :profile-picture))
|
||||
(test-null (h/query-by-label-text :initials-avatar)))
|
||||
|
||||
(h/describe "Status indicator"
|
||||
(h/test "Render"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:profile-picture (resources/get-mock-image :user-picture-male4)
|
||||
:status-indicator? true}])
|
||||
(test-truthy (h/get-by-label-text :profile-picture))
|
||||
(test-truthy (h/get-by-label-text :status-indicator)))
|
||||
|
||||
(h/test "Do not render"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:profile-picture (resources/get-mock-image :user-picture-male4)
|
||||
:status-indicator? false}])
|
||||
(test-truthy (h/get-by-label-text :profile-picture))
|
||||
(test-null (h/query-by-label-text :status-indicator)))))
|
||||
|
||||
(h/describe "Initials Avatar"
|
||||
(h/describe "Render initials"
|
||||
(letfn [(user-avatar-component [size]
|
||||
[user-avatar/user-avatar {:full-name "New User"
|
||||
:size size}])]
|
||||
(h/describe "Two letters"
|
||||
(h/test "Size :big"
|
||||
(h/render (user-avatar-component :big))
|
||||
(test-truthy (h/get-by-text "NU")))
|
||||
|
||||
(h/test "Size :medium"
|
||||
(h/render (user-avatar-component :medium))
|
||||
(test-truthy (h/get-by-text "NU")))
|
||||
|
||||
(h/test "Size :small"
|
||||
(h/render (user-avatar-component :small))
|
||||
(test-truthy (h/get-by-text "NU"))))
|
||||
|
||||
(h/describe "One letter"
|
||||
(h/test "Size :xs"
|
||||
(h/render (user-avatar-component :xs))
|
||||
(test-truthy (h/get-by-text "N")))
|
||||
|
||||
(h/test "Size :xxs"
|
||||
(h/render (user-avatar-component :xxs))
|
||||
(test-truthy (h/get-by-text "N")))
|
||||
|
||||
(h/test "Size :xxxs"
|
||||
(h/render (user-avatar-component :xxxs))
|
||||
(test-truthy (h/get-by-text "N"))))))
|
||||
|
||||
(h/describe "Render ring"
|
||||
(letfn [(user-avatar-component [size]
|
||||
[user-avatar/user-avatar {:full-name "New User"
|
||||
:ring-background (resources/get-mock-image :ring)
|
||||
:size size}])]
|
||||
(h/describe "Passed and drawn"
|
||||
(h/test "Size :big"
|
||||
(h/render (user-avatar-component :big))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-truthy (h/get-by-label-text :ring-background)))
|
||||
|
||||
(h/test "Size :medium"
|
||||
(h/render (user-avatar-component :medium))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-truthy (h/get-by-label-text :ring-background)))
|
||||
|
||||
(h/test "Size :small"
|
||||
(h/render (user-avatar-component :small))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-truthy (h/get-by-label-text :ring-background))))
|
||||
|
||||
(h/describe "Passed and not drawn (because of invalid size for ring)"
|
||||
(h/test "Size :xs"
|
||||
(h/render (user-avatar-component :xs))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-null (h/query-by-label-text :ring-background)))
|
||||
|
||||
(h/test "Size :xxs"
|
||||
(h/render (user-avatar-component :xxs))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-null (h/query-by-label-text :ring-background)))
|
||||
|
||||
(h/test "Size :xxxs"
|
||||
(h/render (user-avatar-component :xxxs))
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-null (h/query-by-label-text :ring-background))))))
|
||||
|
||||
(h/describe "Status indicator"
|
||||
(h/test "Render"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:full-name "Test User"
|
||||
:status-indicator? true}])
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-truthy (h/get-by-label-text :status-indicator)))
|
||||
|
||||
(h/test "Do not render"
|
||||
(h/render
|
||||
[user-avatar/user-avatar {:full-name "Test User"
|
||||
:status-indicator? false}])
|
||||
(test-truthy (h/get-by-label-text :initials-avatar))
|
||||
(test-null (h/query-by-label-text :status-indicator))))))
|
||||
@@ -0,0 +1,83 @@
|
||||
(ns quo2.components.avatars.user-avatar.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def sizes
|
||||
{:big {:outer 80
|
||||
:inner 72
|
||||
:status-indicator 20
|
||||
:status-indicator-border 4
|
||||
:font-size :heading-1}
|
||||
:medium {:outer 48
|
||||
:inner 44
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-1}
|
||||
:small {:outer 32
|
||||
:inner 28
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-2}
|
||||
:xs {:outer 24
|
||||
:inner 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xxs {:outer 20
|
||||
:inner 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}
|
||||
:xxxs {:outer 16
|
||||
:inner 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}})
|
||||
|
||||
(defn outer
|
||||
[size]
|
||||
(let [dimensions (get-in sizes [size :outer])]
|
||||
{:width dimensions
|
||||
:height dimensions
|
||||
:border-radius dimensions}))
|
||||
|
||||
(defn initials-avatar
|
||||
[size draw-ring?]
|
||||
(let [outer-dimensions (get-in sizes [size :outer])
|
||||
inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])]
|
||||
{:position :absolute
|
||||
:top (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:left (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:width inner-dimensions
|
||||
:height inner-dimensions
|
||||
:border-radius inner-dimensions
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/custom-color-by-theme :turquoise 50 60)}))
|
||||
|
||||
(def initials-avatar-text
|
||||
{:color colors/white-opa-70})
|
||||
|
||||
(defn dot
|
||||
[size online? ring?]
|
||||
(let [background (if online? colors/success-50 colors/neutral-40)
|
||||
dimensions (get-in sizes [size :status-indicator])
|
||||
border-width (get-in sizes [size :status-indicator-border])
|
||||
right (case size
|
||||
:big 2
|
||||
:medium 0
|
||||
:small -2
|
||||
0)
|
||||
bottom (case size
|
||||
:big (if ring? -1 2)
|
||||
:medium (if ring? 0 -2)
|
||||
:small -2
|
||||
0)]
|
||||
{:position :absolute
|
||||
:bottom bottom
|
||||
:right right
|
||||
:width dimensions
|
||||
:height dimensions
|
||||
:border-width border-width
|
||||
:border-radius dimensions
|
||||
:border-color (colors/theme-colors colors/white colors/neutral-100)
|
||||
:background-color background}))
|
||||
@@ -0,0 +1,56 @@
|
||||
(ns quo2.components.avatars.user-avatar.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.user-avatar.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(defn- extract-initials
|
||||
[full-name amount-initials]
|
||||
(let [upper-case-first-letter (comp string/upper-case first)
|
||||
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?]}]
|
||||
(let [font-size (get-in style/sizes [size :font-size])
|
||||
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)]
|
||||
[rn/view {:accessibility-label :initials-avatar
|
||||
:style (style/initials-avatar size draw-ring?)}
|
||||
[text/text
|
||||
{:style style/initials-avatar-text
|
||||
:size font-size
|
||||
:weight :semi-bold}
|
||||
(extract-initials full-name amount-initials)]]))
|
||||
|
||||
(def valid-ring-sizes #{:big :medium :small})
|
||||
|
||||
(defn user-avatar
|
||||
"If no `profile-picture` is given, draws the initials based on the `full-name` and
|
||||
uses `ring-background` to display the ring behind the initials when given. Otherwise,
|
||||
shows the `profile-picture` which already comes with the ring drawn."
|
||||
[{:keys [full-name status-indicator? online? size profile-picture ring-background]
|
||||
:or {status-indicator? true
|
||||
online? true
|
||||
size :big}}]
|
||||
(let [full-name (or full-name "empty name")
|
||||
draw-ring? (and ring-background (valid-ring-sizes size))
|
||||
outer-styles (style/outer size)]
|
||||
[rn/view {:style outer-styles :accessibility-label :user-avatar}
|
||||
;; The `profile-picture` already has the ring in it
|
||||
(when-let [image (or profile-picture ring-background)]
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label (if draw-ring? :ring-background :profile-picture)
|
||||
:style outer-styles
|
||||
:source image}])
|
||||
(when-not profile-picture
|
||||
[initials-avatar
|
||||
{:full-name full-name
|
||||
:size size
|
||||
:draw-ring? draw-ring?}])
|
||||
(when status-indicator?
|
||||
[rn/view {:accessibility-label :status-indicator
|
||||
:style (style/dot size online? draw-ring?)}])]))
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns quo2.components.colors.color-picker.component-spec
|
||||
(:require [quo2.components.colors.color-picker.view :as color-picker]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "color-picker"
|
||||
(h/test "color picker rendered"
|
||||
(h/render [color-picker/view])
|
||||
(-> (h/expect (h/get-all-by-label-text :color-picker-item))
|
||||
(.toHaveLength 12)))
|
||||
(h/test "clicks on a color item"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [color-picker/view {:on-change #(event)}])
|
||||
(h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0))
|
||||
(-> (h/expect event)
|
||||
(.toHaveBeenCalled))))
|
||||
(h/test "color picker color changed"
|
||||
(let [selected (reagent/atom nil)]
|
||||
(h/render [color-picker/view {:on-change #(reset! selected %)}])
|
||||
(h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0))
|
||||
(-> (h/expect @selected)
|
||||
(.toStrictEqual :blue)))))
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
(ns quo2.components.colors.color-picker.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def color-picker-container
|
||||
{:max-width 338
|
||||
:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:justify-content :space-between})
|
||||
|
||||
(def flex-break
|
||||
{:flex-basis "100%"
|
||||
:height 10})
|
||||
|
||||
(defn color-button
|
||||
[color selected?]
|
||||
(merge {:width 48
|
||||
:height 48
|
||||
:border-width 4
|
||||
:border-radius 24
|
||||
:transform [{:rotate "45deg"}]
|
||||
:border-color :transparent}
|
||||
(when selected?
|
||||
{:border-top-color (colors/alpha color 0.4)
|
||||
:border-end-color (colors/alpha color 0.4)
|
||||
:border-bottom-color (colors/alpha color 0.2)
|
||||
:border-start-color (colors/alpha color 0.2)})))
|
||||
|
||||
(defn color-circle
|
||||
[color border?]
|
||||
{:width 40
|
||||
:height 40
|
||||
:transform [{:rotate "-45deg"}]
|
||||
:background-color color
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color color
|
||||
:border-width (if border? 2 0)
|
||||
:overflow :hidden
|
||||
:border-radius 20})
|
||||
|
||||
(defn secondary-overlay
|
||||
[secondary-color border?]
|
||||
{:width (if border? 18 20)
|
||||
:height 40
|
||||
:position :absolute
|
||||
:right 0
|
||||
:background-color secondary-color})
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
(ns quo2.components.colors.color-picker.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icon]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.colors.color-picker.style :as style]))
|
||||
|
||||
(def color-list [:blue :yellow :turquoise :copper :sky :camel :orange :army :pink :purple :magenta])
|
||||
|
||||
(defn picker-colors
|
||||
[blur?]
|
||||
(concat (map (fn [color]
|
||||
{:name color
|
||||
:color (colors/custom-color-by-theme color (if blur? 60 50) 60)})
|
||||
color-list)
|
||||
[{:name :yinyang
|
||||
:color (colors/theme-colors (colors/custom-color :yin 50)
|
||||
(colors/custom-color :yang 50))
|
||||
:secondary-color (colors/theme-colors (colors/custom-color :yang 50)
|
||||
(colors/custom-color :yin 50))}]))
|
||||
|
||||
(defn- on-change-handler
|
||||
[selected color-name on-change]
|
||||
(reset! selected color-name)
|
||||
(when on-change (on-change color-name)))
|
||||
|
||||
(defn- color-item
|
||||
[{:keys [name
|
||||
color
|
||||
secondary-color
|
||||
selected?
|
||||
on-press
|
||||
blur?]}]
|
||||
(let [border? (and (not blur?) (and secondary-color (not selected?)))]
|
||||
[rn/touchable-opacity
|
||||
{:style (style/color-button color selected?)
|
||||
:accessibility-label :color-picker-item
|
||||
:on-press #(on-press name)}
|
||||
[rn/view
|
||||
{:style (style/color-circle color border?)}
|
||||
(when (and secondary-color (not selected?))
|
||||
[rn/view
|
||||
{:style (style/secondary-overlay secondary-color border?)}])
|
||||
(when selected?
|
||||
[icon/icon :i/check
|
||||
{:size 20
|
||||
:color (or secondary-color
|
||||
colors/white)}])]]))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
- `default-selected?` Default selected color name.
|
||||
- `selected` Selected color name.
|
||||
- `on-change` Callback called when a color is selected `(fn [color-name])`.
|
||||
- `blur?` Boolean to enable blur background support.}"
|
||||
[{:keys [default-selected?]}]
|
||||
(let [internal-selected (reagent/atom default-selected?)]
|
||||
(fn [{:keys [blur? on-change selected]}]
|
||||
(when (and (not (nil? selected)) (not= @internal-selected selected))
|
||||
(reset! internal-selected selected))
|
||||
[rn/view {:style style/color-picker-container}
|
||||
(doall (map-indexed (fn [index color]
|
||||
[:<> {:key (color :name)}
|
||||
[color-item
|
||||
(merge color
|
||||
{:selected? (= (color :name) @internal-selected)
|
||||
:on-press #(on-change-handler internal-selected % on-change)
|
||||
:blur? blur?})]
|
||||
(when (= index 5) [rn/view {:style style/flex-break}])])
|
||||
(picker-colors blur?)))])))
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
(ns quo2.components.dividers.strength-divider.component-spec
|
||||
(:require [quo2.components.dividers.strength-divider.view :as strength-divider]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "select-profile component"
|
||||
(h/test "render component"
|
||||
(h/render [strength-divider/view {:type :okay}])
|
||||
(-> (h/expect (h/get-by-label-text :strength-divider))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :very-weak"
|
||||
(h/render [strength-divider/view {:type :very-weak}])
|
||||
(-> (h/expect (h/get-by-translation-text :strength-divider-very-weak-label))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :weak"
|
||||
(h/render [strength-divider/view {:type :weak}])
|
||||
(-> (h/expect (h/get-by-translation-text :strength-divider-weak-label))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :okay"
|
||||
(h/render [strength-divider/view {:type :okay}])
|
||||
(-> (h/expect (h/get-by-translation-text :strength-divider-okay-label))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :strong"
|
||||
(h/render [strength-divider/view {:type :strong}])
|
||||
(-> (h/expect (h/get-by-translation-text :strength-divider-strong-label))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :very-strong"
|
||||
(h/render [strength-divider/view {:type :very-strong}])
|
||||
(-> (h/expect (h/get-by-translation-text :strength-divider-very-strong-label))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :alert"
|
||||
(h/render [strength-divider/view {:type :alert} "Text message"])
|
||||
(-> (h/expect (h/get-by-text "Text message"))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with :type :info"
|
||||
(h/render [strength-divider/view {:type :info} "Text Info"])
|
||||
(-> (h/expect (h/get-by-text "Text Info"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
(ns quo2.components.dividers.strength-divider.style)
|
||||
|
||||
(def container
|
||||
{:height 40
|
||||
:flex-direction :row
|
||||
:padding-horizontal 20
|
||||
:align-items :center})
|
||||
|
||||
(defn text
|
||||
[color]
|
||||
{:color color
|
||||
:margin-left 4})
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
(ns quo2.components.dividers.strength-divider.view
|
||||
(:require [quo2.components.dividers.strength-divider.style :as style]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.svg :as svg]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def strength-divider-types
|
||||
{:very-weak {:default-text (i18n/label :t/strength-divider-very-weak-label)
|
||||
:color colors/danger-60
|
||||
:percentage 20}
|
||||
:weak {:default-text (i18n/label :t/strength-divider-weak-label)
|
||||
:color (colors/custom-color :orange 60)
|
||||
:percentage 40}
|
||||
:okay {:default-text (i18n/label :t/strength-divider-okay-label)
|
||||
:color (colors/custom-color :yellow 60)
|
||||
:percentage 60}
|
||||
:strong {:default-text (i18n/label :t/strength-divider-strong-label)
|
||||
:color colors/success-60
|
||||
:percentage 80}
|
||||
:very-strong {:default-text (i18n/label :t/strength-divider-very-strong-label)
|
||||
:color colors/success-60
|
||||
:percentage 100}
|
||||
:info {:color colors/white-opa-40}
|
||||
:alert {:color colors/danger-60}})
|
||||
|
||||
(defn circular-progress
|
||||
[{:keys [color percentage]}]
|
||||
(let [strength-indicator-radius 6.5
|
||||
strength-indicator-circumference (* 2 Math/PI strength-indicator-radius)]
|
||||
[svg/svg
|
||||
{:view-box "0 0 16 16"
|
||||
:width 14.2
|
||||
:transform [{:rotate "270deg"}]
|
||||
:height 14.2}
|
||||
[svg/circle
|
||||
{:cx 8
|
||||
:cy 8
|
||||
:r strength-indicator-radius
|
||||
:fill :transparent
|
||||
:stroke-width 1.2
|
||||
:stroke (colors/alpha color 0.2)}]
|
||||
[svg/circle
|
||||
{:cx 8
|
||||
:cy 8
|
||||
:r strength-indicator-radius
|
||||
:fill :transparent
|
||||
:stroke-width 1.2
|
||||
:stroke-dasharray strength-indicator-circumference
|
||||
:stroke-dashoffset (* (- 100 percentage) 0.01 strength-indicator-circumference)
|
||||
:stroke color}]
|
||||
[svg/circle]]))
|
||||
|
||||
(defn strength-indicator
|
||||
[type]
|
||||
(let [{:keys [color percentage]} (strength-divider-types type)]
|
||||
(case type
|
||||
:info nil
|
||||
:alert [icon/icon :i/alert
|
||||
{:color color
|
||||
:size 16}]
|
||||
[circular-progress {:color color :percentage percentage}])))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
- `:type` `:very-weak`/`:weak`/`:okay`/`:strong`/`:very-strong`/`:info`/`:alert`)
|
||||
|
||||
`text` message string(only works when type is `info`/`alert`)"
|
||||
[{:keys [type] :or {type :very-weak}} text]
|
||||
(let [{:keys [color default-text]} (strength-divider-types type)]
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [(colors/alpha color 0.05) (colors/alpha color 0)]}
|
||||
[rn/view
|
||||
{:style style/container
|
||||
:accessibility-label :strength-divider}
|
||||
[strength-indicator type]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/text color)}
|
||||
(or default-text text)]]]))
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
(ns quo2.components.input.style
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(def variants-colors
|
||||
"Colors that keep the same across input's status change"
|
||||
{:light {:label colors/neutral-50
|
||||
:icon colors/neutral-50
|
||||
:cursor (colors/custom-color :blue 50)
|
||||
:button-border colors/neutral-30
|
||||
:clear-icon colors/neutral-40
|
||||
:password-icon colors/neutral-50}
|
||||
:light-blur {:label colors/neutral-80-opa-40
|
||||
:icon colors/neutral-80-opa-70
|
||||
:cursor (colors/custom-color :blue 50)
|
||||
:button-border colors/neutral-80-opa-30
|
||||
:password-icon colors/neutral-100
|
||||
:clear-icon colors/neutral-80-opa-30}
|
||||
:dark {:label colors/neutral-40
|
||||
:icon colors/neutral-40
|
||||
:cursor (colors/custom-color :blue 60)
|
||||
:button-border colors/neutral-70
|
||||
:password-icon colors/white
|
||||
:clear-icon colors/neutral-60}
|
||||
:dark-blur {:label colors/white-opa-40
|
||||
:icon colors/white-opa-70
|
||||
:cursor colors/white
|
||||
:button-border colors/white-opa-10
|
||||
:password-icon colors/white
|
||||
:clear-icon colors/white-opa-10}})
|
||||
|
||||
(def status-colors
|
||||
{:light {:default {:border-color colors/neutral-20
|
||||
:placeholder colors/neutral-40
|
||||
:text colors/neutral-100}
|
||||
:focus {:border-color colors/neutral-40
|
||||
:placeholder colors/neutral-30
|
||||
:text colors/neutral-100}
|
||||
:error {:border-color colors/danger-opa-40
|
||||
:placeholder colors/neutral-40
|
||||
:text colors/neutral-100}
|
||||
:disabled {:border-color colors/neutral-20
|
||||
:placeholder colors/neutral-40
|
||||
:text colors/neutral-40}}
|
||||
:light-blur {:default {:border-color colors/neutral-80-opa-10
|
||||
:placeholder colors/neutral-80-opa-40
|
||||
:text colors/neutral-100}
|
||||
:focus {:border-color colors/neutral-80-opa-20
|
||||
:placeholder colors/neutral-80-opa-20
|
||||
:text colors/neutral-100}
|
||||
:error {:border-color colors/danger-opa-40
|
||||
:placeholder colors/neutral-80-opa-40
|
||||
:text colors/neutral-100}
|
||||
:disabled {:border-color colors/neutral-80-opa-10
|
||||
:placeholder colors/neutral-80-opa-30
|
||||
:text colors/neutral-80-opa-30}}
|
||||
:dark {:default {:border-color colors/neutral-80
|
||||
:placeholder colors/neutral-50
|
||||
:text colors/white}
|
||||
:focus {:border-color colors/neutral-60
|
||||
:placeholder colors/neutral-60
|
||||
:text colors/white}
|
||||
:error {:border-color colors/danger-opa-40
|
||||
:placeholder colors/white-opa-40
|
||||
:text colors/white}
|
||||
:disabled {:border-color colors/neutral-80
|
||||
:placeholder colors/neutral-40
|
||||
:text colors/neutral-40}}
|
||||
:dark-blur {:default {:border-color colors/white-opa-10
|
||||
:placeholder colors/white-opa-40
|
||||
:text colors/white}
|
||||
:focus {:border-color colors/white-opa-40
|
||||
:placeholder colors/white-opa-20
|
||||
:text colors/white}
|
||||
:error {:border-color colors/danger-opa-40
|
||||
:placeholder colors/white-opa-40
|
||||
:text colors/white}
|
||||
:disabled {:border-color colors/white-opa-10
|
||||
:placeholder colors/white-opa-20
|
||||
:text colors/white-opa-20}}})
|
||||
|
||||
(defn input-container
|
||||
[colors-by-status small? disabled?]
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 8
|
||||
:border-width 1
|
||||
:border-color (:border-color colors-by-status)
|
||||
:border-radius (if small? 10 14)
|
||||
:opacity (if disabled? 0.3 1)})
|
||||
|
||||
(defn left-icon-container
|
||||
[small?]
|
||||
{:margin-left (if small? 0 4)
|
||||
:margin-right (if small? 4 8)
|
||||
:margin-top (if small? 5 9)
|
||||
:height 20
|
||||
:width 20})
|
||||
|
||||
(defn icon
|
||||
[colors-by-variant]
|
||||
{:color (:icon colors-by-variant)
|
||||
:size 20})
|
||||
|
||||
(defn input
|
||||
[colors-by-status small? multiple-lines?]
|
||||
(merge (text/text-style {:size :paragraph-1 :weight :regular})
|
||||
{:flex 1
|
||||
:text-align-vertical :top
|
||||
:padding-horizontal 0
|
||||
: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?]
|
||||
{:margin-left (if small? 4 8)
|
||||
:padding-right (if small? 0 4)
|
||||
:padding-top (if small? 5 9)})
|
||||
|
||||
(defn password-icon
|
||||
[variant-colors]
|
||||
{:size 20
|
||||
:color (:password-icon variant-colors)})
|
||||
|
||||
(defn clear-icon
|
||||
[variant-colors]
|
||||
{:size 20
|
||||
:color (:clear-icon variant-colors)})
|
||||
|
||||
(def texts-container
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:height 18
|
||||
:margin-bottom 8})
|
||||
|
||||
(def label-container {:flex 1})
|
||||
|
||||
(defn label-color
|
||||
[variant-colors]
|
||||
{:color (:label variant-colors)})
|
||||
|
||||
(def counter-container
|
||||
{:flex 1
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn counter-color
|
||||
[current-chars char-limit variant-colors]
|
||||
{:color (if (> current-chars char-limit)
|
||||
colors/danger-60
|
||||
(:label variant-colors))})
|
||||
|
||||
(defn button
|
||||
[colors-by-variant small?]
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:height 24
|
||||
:border-width 1
|
||||
:border-color (:button-border colors-by-variant)
|
||||
:border-radius 8
|
||||
:margin-vertical (if small? 3 7)
|
||||
:margin-left 4
|
||||
:margin-right (if small? -4 0)
|
||||
:padding-horizontal 7
|
||||
:padding-top 1.5
|
||||
:padding-bottom 2.5})
|
||||
|
||||
(defn button-text
|
||||
[colors-by-status]
|
||||
{:color (:text colors-by-status)})
|
||||
@@ -0,0 +1,173 @@
|
||||
(ns quo2.components.input.view
|
||||
(:require [oops.core :as oops]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.input.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- label-&-counter
|
||||
[{:keys [label current-chars char-limit variant-colors]}]
|
||||
(let [count-text (when char-limit (str current-chars "/" char-limit))]
|
||||
[rn/view {:style style/texts-container}
|
||||
[rn/view {:style style/label-container}
|
||||
[text/text
|
||||
{:style (style/label-color variant-colors)
|
||||
:weight :medium
|
||||
:size :paragraph-2}
|
||||
label]]
|
||||
[rn/view {:style style/counter-container}
|
||||
[text/text
|
||||
{:style (style/counter-color current-chars char-limit variant-colors)
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
count-text]]]))
|
||||
|
||||
(defn- left-accessory
|
||||
[{:keys [variant-colors small icon-name]}]
|
||||
[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
|
||||
{: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
|
||||
{: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 :variant :error :right-icon :left-icon :disabled :small :button :label
|
||||
:char-limit :on-char-limit-reach :icon-name])
|
||||
|
||||
(defn- base-input
|
||||
[{:keys [on-change-text on-char-limit-reach]}]
|
||||
(let [status (reagent/atom :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)
|
||||
(reset! multiple-lines? true)
|
||||
(reset! multiple-lines? false)))
|
||||
char-count (reagent/atom 0)
|
||||
update-char-limit! (fn [new-text char-limit]
|
||||
(when on-change-text (on-change-text new-text))
|
||||
(let [amount-chars (count new-text)]
|
||||
(reset! char-count amount-chars)
|
||||
(when (>= amount-chars char-limit)
|
||||
(on-char-limit-reach amount-chars))))]
|
||||
(fn [{:keys [variant error right-icon left-icon disabled small button label char-limit
|
||||
multiline clearable]
|
||||
:or {variant :light}
|
||||
:as props}]
|
||||
(let [status-path (cond
|
||||
disabled :disabled
|
||||
error :error
|
||||
:else @status)
|
||||
colors-by-status (get-in style/status-colors [variant status-path])
|
||||
variant-colors (style/variants-colors variant)
|
||||
clean-props (apply dissoc props custom-props)]
|
||||
[rn/view
|
||||
(when (or label char-limit)
|
||||
[label-&-counter
|
||||
{:variant-colors variant-colors
|
||||
:label label
|
||||
:current-chars @char-count
|
||||
:char-limit char-limit}])
|
||||
[rn/view {:style (style/input-container colors-by-status small disabled)}
|
||||
(when-let [{:keys [icon-name]} left-icon]
|
||||
[left-accessory
|
||||
{:variant-colors variant-colors
|
||||
:small small
|
||||
:icon-name icon-name}])
|
||||
[rn/text-input
|
||||
(cond-> {:style (style/input colors-by-status small @multiple-lines?)
|
||||
:placeholder-text-color (:placeholder colors-by-status)
|
||||
:cursor-color (:cursor variant-colors)
|
||||
:editable (not disabled)
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur}
|
||||
:always (merge clean-props)
|
||||
multiline (assoc :on-content-size-change set-multiple-lines!)
|
||||
char-limit (assoc :on-change-text #(update-char-limit! char-limit %)))]
|
||||
(when-let [{:keys [on-press icon-name style-fn]} right-icon]
|
||||
[right-accessory
|
||||
{:variant-colors variant-colors
|
||||
:small small
|
||||
:disabled disabled
|
||||
:icon-style-fn style-fn
|
||||
:icon-name icon-name
|
||||
:on-press (fn []
|
||||
(when clearable (reset! char-count 0))
|
||||
(on-press))}])
|
||||
(when-let [{:keys [on-press text]} button]
|
||||
[right-button
|
||||
{:colors-by-status colors-by-status
|
||||
:variant-colors variant-colors
|
||||
:small small
|
||||
:disabled disabled
|
||||
:on-press on-press
|
||||
:text text}])]]))))
|
||||
|
||||
(defn- password-input
|
||||
[_]
|
||||
(let [password-shown? (reagent/atom false)]
|
||||
(fn [props]
|
||||
[base-input
|
||||
(assoc props
|
||||
: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:
|
||||
- :type - Can be `:text`(default) or `:password`.
|
||||
- :variant - :light(default), :light-blur, :dark or :dark-blur.
|
||||
- :small - Boolean to specify if this input is rendered in its small version.
|
||||
- :multiline - Boolean to specify if this input support multiple lines.
|
||||
- :icon-name - The name of an icon to display at the left of the input.
|
||||
- :error - Boolean to specify it this input marks an error.
|
||||
- :disabled - Boolean to specify if this input is disabled or not.
|
||||
- :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 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:
|
||||
- :value
|
||||
- :default-value
|
||||
- :on-change
|
||||
- :on-change-text
|
||||
...
|
||||
"
|
||||
[{:keys [type clearable on-clear on-change-text icon-name]
|
||||
:or {type :text}
|
||||
:as props}]
|
||||
(let [base-props (cond-> props
|
||||
icon-name (assoc-in [:left-icon :icon-name] icon-name)
|
||||
clearable (assoc :right-icon
|
||||
{:style-fn style/clear-icon
|
||||
:icon-name :i/clear
|
||||
:on-press #(when on-clear (on-clear))})
|
||||
on-change-text (assoc :on-change-text
|
||||
(fn [new-text]
|
||||
(on-change-text new-text)
|
||||
(reagent/flush))))]
|
||||
(if (= type :password)
|
||||
[password-input base-props]
|
||||
[base-input base-props])))
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns quo2.components.list-items.preview-list
|
||||
(:require [quo2.components.avatars.user-avatar :as user-avatar]
|
||||
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
(ns quo2.components.list-items.user-list
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.messages.author.view :as author]
|
||||
[quo2.components.selectors.selectors :as selectors]))
|
||||
|
||||
(def container-style
|
||||
{:margin-horizontal 8
|
||||
:padding-vertical 8
|
||||
:padding-horizontal 12
|
||||
:border-radius 12
|
||||
:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn action-icon
|
||||
[{:keys [type on-press on-check disabled? checked?]}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press (when on-press on-press)
|
||||
:style {:position :absolute :right 20}}
|
||||
(case type
|
||||
:options
|
||||
[icons/icon :i/options
|
||||
{:size 20
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
|
||||
:checkbox
|
||||
[selectors/checkbox
|
||||
{:checked? checked?
|
||||
:accessibility-label :user-list-toggle-check
|
||||
:disabled? disabled?
|
||||
:on-change (when on-check on-check)}]
|
||||
:close
|
||||
[text/text "not implemented"]
|
||||
[rn/view])])
|
||||
|
||||
(defn user-list
|
||||
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
|
||||
untrustworthy? on-press on-long-press accessory]}]
|
||||
[rn/touchable-opacity
|
||||
{:style container-style
|
||||
:accessibility-label :user-list
|
||||
:on-press (when on-press on-press)
|
||||
:on-long-press (when on-long-press on-long-press)}
|
||||
[user-avatar/user-avatar
|
||||
{:full-name primary-name
|
||||
:profile-picture photo-path
|
||||
:status-indicator? true
|
||||
:online? online?
|
||||
:size :small}]
|
||||
[rn/view {:style {:margin-left 8}}
|
||||
[author/author
|
||||
{:primary-name primary-name
|
||||
:secondary-name secondary-name
|
||||
:contact? contact?
|
||||
:verified? verified?
|
||||
:untrustworthy? untrustworthy?}]
|
||||
(when short-chat-key
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
short-chat-key])]
|
||||
(when accessory
|
||||
[action-icon accessory])])
|
||||
@@ -7,14 +7,6 @@
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn ens-text
|
||||
[]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)})
|
||||
|
||||
(defn nickname-text
|
||||
[]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)})
|
||||
|
||||
(def middle-dot-nickname
|
||||
{:color colors/neutral-50
|
||||
:margin-horizontal 4})
|
||||
@@ -27,12 +19,6 @@
|
||||
{:color colors/neutral-50
|
||||
:margin-left 4})
|
||||
|
||||
(defn profile-name-text
|
||||
[nickname?]
|
||||
{:color (if nickname?
|
||||
(colors/theme-colors colors/neutral-60 colors/neutral-40)
|
||||
(colors/theme-colors colors/neutral-100 colors/white))})
|
||||
|
||||
(def icon-container
|
||||
{:margin-left 4})
|
||||
|
||||
|
||||
@@ -3,97 +3,71 @@
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.messages.author.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def middle-dot "·")
|
||||
|
||||
(defn display-name
|
||||
[{:keys [profile-name nickname ens-name text-style]}]
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
nickname? (-> nickname string/blank? not)]
|
||||
(if ens?
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
text-style)
|
||||
ens-name]
|
||||
[:<>
|
||||
(if nickname?
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
text-style)
|
||||
nickname]
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
text-style)
|
||||
profile-name])])))
|
||||
|
||||
(defn author
|
||||
[{:keys [profile-name nickname short-chat-key ens-name time-str contact? verified? untrustworthy?]}]
|
||||
[{:keys [primary-name secondary-name short-chat-key time-str contact? verified? untrustworthy?]}]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
nickname? (-> nickname string/blank? not)]
|
||||
[rn/view {:style style/container}
|
||||
(if ens?
|
||||
[rn/view {:style style/container}
|
||||
[:<>
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style {:color (colors/theme-colors colors/neutral-100 colors/white)}}
|
||||
primary-name]
|
||||
(when (not (string/blank? secondary-name))
|
||||
[:<>
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
ens-name]
|
||||
[:<>
|
||||
(when nickname?
|
||||
[:<>
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
nickname]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style style/middle-dot-nickname}
|
||||
middle-dot]])
|
||||
[text/text
|
||||
{:weight (if nickname? :medium :semi-bold)
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
profile-name]])
|
||||
(when contact?
|
||||
[icons/icon :main-icons2/contact
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}])
|
||||
(cond
|
||||
verified?
|
||||
[icons/icon :main-icons2/verified
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}]
|
||||
untrustworthy?
|
||||
[icons/icon :main-icons2/untrustworthy
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}])
|
||||
(when-not ens?
|
||||
{:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style style/middle-dot-nickname}
|
||||
middle-dot]
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/chat-key-text}
|
||||
short-chat-key])
|
||||
(when-not ens?
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/middle-dot-chat-key}
|
||||
middle-dot])
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style {:color (colors/theme-colors colors/neutral-60 colors/neutral-40)}}
|
||||
secondary-name]])]
|
||||
(when contact?
|
||||
[icons/icon :main-icons2/contact
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}])
|
||||
(cond
|
||||
verified?
|
||||
[icons/icon :main-icons2/verified
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}]
|
||||
untrustworthy?
|
||||
[icons/icon :main-icons2/untrustworthy
|
||||
{:size 12
|
||||
:no-color true
|
||||
:container-style style/icon-container}])
|
||||
(when (and (not verified?) short-chat-key)
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style style/chat-key-text}
|
||||
short-chat-key])
|
||||
(when (and (not verified?) time-str)
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style style/middle-dot-chat-key}
|
||||
middle-dot])
|
||||
(when time-str
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:accessibility-label :message-timestamp
|
||||
:style (style/time-text ens?)}
|
||||
time-str]]))])
|
||||
:number-of-lines 1
|
||||
:style (style/time-text verified?)}
|
||||
time-str])])])
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.messages.system-message
|
||||
(:require [quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.navigation.page-nav
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
|
||||
@@ -33,25 +33,16 @@
|
||||
:padding-vertical 8
|
||||
:background-color colors/white-opa-5})
|
||||
|
||||
(def buttons-container
|
||||
(def footer-container
|
||||
{:margin-top 12
|
||||
:flex-direction :row
|
||||
:align-items :flex-start})
|
||||
|
||||
(def status
|
||||
{:margin-top 12
|
||||
:align-items :flex-start
|
||||
:flex 1})
|
||||
:flex-direction :row})
|
||||
|
||||
(defn title
|
||||
[replying?]
|
||||
{:color colors/white
|
||||
:flex-shrink 1
|
||||
:max-width (when-not replying? "60%")})
|
||||
[]
|
||||
{:color colors/white})
|
||||
|
||||
(def timestamp
|
||||
{:text-transform :none
|
||||
:flex-grow 1
|
||||
:margin-left 8
|
||||
:color colors/neutral-40})
|
||||
|
||||
@@ -75,3 +66,8 @@
|
||||
(def top-section-container
|
||||
{:align-items :center
|
||||
:flex-direction :row})
|
||||
|
||||
(def title-container
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
@@ -7,19 +7,12 @@
|
||||
[quo2.components.notifications.activity-log.style :as style]
|
||||
[quo2.components.tags.status-tags :as status-tags]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[utils.i18n :as i18n]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ^:private max-reply-length
|
||||
280)
|
||||
|
||||
(defn- valid-reply?
|
||||
[reply]
|
||||
(<= (count reply) max-reply-length))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- activity-reply-text-input
|
||||
[reply-input on-update-reply]
|
||||
[{:keys [on-update-reply max-reply-length valid-reply?]} reply-input]
|
||||
[rn/view
|
||||
[rn/view
|
||||
{:style {:margin-top 16
|
||||
@@ -99,44 +92,12 @@
|
||||
body]
|
||||
body)])
|
||||
|
||||
(defn- activity-buttons
|
||||
[button-1 button-2 replying? reply-input]
|
||||
(let [size (if replying? 40 24)
|
||||
common-style (when replying?
|
||||
{:padding-vertical 9
|
||||
:flex-grow 1
|
||||
:flex-basis 0})]
|
||||
[rn/view style/buttons-container
|
||||
(when button-1
|
||||
[button/button
|
||||
(-> button-1
|
||||
(assoc :size size)
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
(:label button-1)])
|
||||
(when button-2
|
||||
[button/button
|
||||
(-> button-2
|
||||
(assoc :size size)
|
||||
(assoc :disabled (and replying? (not (valid-reply? @reply-input))))
|
||||
(update :style merge common-style))
|
||||
(:label button-2)])]))
|
||||
|
||||
(defn- activity-status
|
||||
[status]
|
||||
[rn/view
|
||||
{:style style/status
|
||||
:accessibility-label :activity-status}
|
||||
[status-tags/status-tag
|
||||
{:size :small
|
||||
:label (:label status)
|
||||
:status status}]])
|
||||
|
||||
(defn- activity-title
|
||||
[title replying?]
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:accessibility-label :activity-title
|
||||
:style (style/title replying?)
|
||||
:style (style/title)
|
||||
:size (if replying? :heading-2 :paragraph-1)}
|
||||
title])
|
||||
|
||||
@@ -155,18 +116,42 @@
|
||||
:style style/unread-dot-container}
|
||||
[rn/view {:style style/unread-dot}]])
|
||||
|
||||
(defmulti footer-item-view (fn [item _ _] (:type item)))
|
||||
|
||||
(defmethod footer-item-view :button
|
||||
[{:keys [label subtype disable-when] :as button} replying? reply-input]
|
||||
(let [size (if replying? 40 24)
|
||||
common-style (when replying?
|
||||
{:padding-vertical 9
|
||||
:flex-grow 1
|
||||
:flex-basis 0})]
|
||||
[button/button
|
||||
(-> button
|
||||
(assoc :size size)
|
||||
(assoc :type subtype)
|
||||
(assoc :disabled (and replying? (disable-when @reply-input)))
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
label]))
|
||||
|
||||
(defmethod footer-item-view :status
|
||||
[{:keys [label subtype]} _ _]
|
||||
[status-tags/status-tag
|
||||
{:size :small
|
||||
:label label
|
||||
:status {:type subtype}}])
|
||||
|
||||
(defn- footer
|
||||
[_]
|
||||
[_ _]
|
||||
(let [reply-input (reagent/atom "")]
|
||||
(fn [{:keys [replying? on-update-reply status button-1 button-2]}]
|
||||
(fn [{:keys [replying? items] :as props}]
|
||||
[:<>
|
||||
(when replying?
|
||||
[activity-reply-text-input reply-input on-update-reply])
|
||||
(cond (some? status)
|
||||
[activity-status status]
|
||||
|
||||
(or button-1 button-2)
|
||||
[activity-buttons button-1 button-2 replying? reply-input])])))
|
||||
[activity-reply-text-input props reply-input])
|
||||
(when items
|
||||
[rn/view style/footer-container
|
||||
(for [{:keys [key] :as item} items]
|
||||
^{:key key}
|
||||
[footer-item-view item replying? reply-input])])])))
|
||||
|
||||
(defn view
|
||||
[{:keys [icon
|
||||
@@ -179,7 +164,8 @@
|
||||
:as props}]
|
||||
[rn/view
|
||||
{:accessibility-label :activity
|
||||
:style style/container}
|
||||
:style style/container
|
||||
:on-layout (:on-layout props)}
|
||||
(when-not replying?
|
||||
[activity-icon icon])
|
||||
[rn/view
|
||||
@@ -187,9 +173,10 @@
|
||||
:flex 1}}
|
||||
[rn/view
|
||||
[rn/view {:style style/top-section-container}
|
||||
[activity-title title replying?]
|
||||
(when-not replying?
|
||||
[activity-timestamp timestamp])
|
||||
[rn/view {:style style/title-container}
|
||||
[activity-title title replying?]
|
||||
(when-not replying?
|
||||
[activity-timestamp timestamp])]
|
||||
(when (and unread? (not replying?))
|
||||
[activity-unread-dot])]
|
||||
(when context
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
:else 0))
|
||||
|
||||
(def ^:private themes
|
||||
{:color {:light colors/neutral-80-opa-40
|
||||
:dark colors/white-opa-40}})
|
||||
{:color {:dark colors/neutral-80-opa-40
|
||||
:light colors/white-opa-40}})
|
||||
|
||||
(defn circle-timer
|
||||
[{:keys [color duration size stroke-width trail-color rotation initial-remaining-time]}]
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
(ns quo2.components.notifications.toast
|
||||
(:require [utils.i18n :as i18n]
|
||||
[quo2.components.icon :as icon]
|
||||
(:require [quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.count-down-circle :as count-down-circle]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.shadows :as shadows]
|
||||
[quo2.theme :as theme]
|
||||
[utils.i18n :as i18n]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private themes
|
||||
{:container {:dark {:background-color colors/white-opa-70}
|
||||
:light {:background-color colors/neutral-80-opa-90}}
|
||||
:light {:background-color colors/neutral-80-opa-70}}
|
||||
:title {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:text {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:icon {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:action-container {:dark {:background-color :colors/neutral-80-opa-5}
|
||||
:light {:background-color :colors/white-opa-5}}})
|
||||
:action-container {:dark {:background-color colors/neutral-80-opa-5}
|
||||
:light {:background-color colors/white-opa-5}}})
|
||||
|
||||
(defn- merge-theme-style
|
||||
[component-key styles override-theme]
|
||||
@@ -51,31 +55,56 @@
|
||||
[i18n/label :t/undo]]])
|
||||
|
||||
(defn- toast-container
|
||||
[{:keys [left middle right container-style override-theme]}]
|
||||
[rn/view {:style (merge {:padding-left 12 :padding-right 12} container-style)}
|
||||
[{:keys [left title text right container-style override-theme]}]
|
||||
[rn/view
|
||||
{:style (merge {:margin-horizontal 12
|
||||
:border-radius 12
|
||||
:overflow :hidden}
|
||||
container-style)}
|
||||
[blur/view
|
||||
{:style {:height "100%"
|
||||
:width "100%"
|
||||
:position :absolute
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:background-color :transparent}
|
||||
:blur-amount 13
|
||||
:blur-radius 10
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent}]
|
||||
[rn/view
|
||||
{:style (merge-theme-style :container
|
||||
{:flex-direction :row
|
||||
:width "100%"
|
||||
:margin :auto
|
||||
:justify-content :space-between
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:border-radius 12}
|
||||
(merge
|
||||
(:shadow-1 shadows/normal-scale)
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:border-radius 12})
|
||||
override-theme)}
|
||||
[rn/view {:style {:padding 2}} left]
|
||||
[rn/view {:style {:padding 4 :flex 1}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (merge-theme-style :text {} override-theme)
|
||||
:accessibility-label :toast-content}
|
||||
middle]]
|
||||
(when title
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style (merge-theme-style :title {} override-theme)
|
||||
:accessibility-label :toast-title}
|
||||
title])
|
||||
(when text
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (merge-theme-style :text {} override-theme)
|
||||
:accessibility-label :toast-content}
|
||||
text])]
|
||||
(when right right)]])
|
||||
|
||||
(defn toast
|
||||
[{:keys [icon icon-color text action undo-duration undo-on-press container-style override-theme]}]
|
||||
[{:keys [icon icon-color title text action undo-duration undo-on-press container-style
|
||||
override-theme]}]
|
||||
[toast-container
|
||||
{:left (when icon
|
||||
[icon/icon icon
|
||||
@@ -84,7 +113,8 @@
|
||||
(get-in themes
|
||||
[:icon (or override-theme (theme/get-theme))
|
||||
:color]))}])
|
||||
:middle text
|
||||
:title title
|
||||
:text text
|
||||
:right (if undo-duration
|
||||
[toast-undo-action undo-duration undo-on-press override-theme]
|
||||
action)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns quo2.components.onboarding.small-option-card.component-spec
|
||||
(:require [quo2.components.onboarding.small-option-card.view :as small-option-card]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- testing-small-option-card
|
||||
@@ -43,8 +42,7 @@
|
||||
(-> on-press-fn js/expect .toHaveBeenCalled))))
|
||||
|
||||
(h/describe "Image rendered"
|
||||
(let [image (resources/get-mock-image :small-opt-card-main)
|
||||
component-props {:image image}]
|
||||
(let [component-props {:image nil}]
|
||||
(h/test "`:main` variant"
|
||||
(h/render (testing-small-option-card :main component-props))
|
||||
(-> (h/get-by-label-text :small-option-card-main-image) h/expect .-not .toBeNull))
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns quo2.components.password.tips.component-spec
|
||||
(:require [quo2.components.password.tips.view :as quo]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "password tips component"
|
||||
(h/test "render component"
|
||||
(h/render [quo/view])
|
||||
(-> (h/expect (h/get-by-label-text :password-tips))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with proper text"
|
||||
(h/render [quo/view {:completed? false} "Upper case"])
|
||||
(-> (h/expect (h/get-by-text "Upper case"))
|
||||
(.toBeTruthy)))
|
||||
(h/test "render component with completed proper text & completed state"
|
||||
(h/render [quo/view {:completed? true} "Numbers"])
|
||||
(-> (h/expect (h/get-by-text "Numbers"))
|
||||
(.toBeTruthy))
|
||||
(-> (h/expect (h/get-by-label-text :password-tips-completed))
|
||||
(.toBeTruthy))))
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
(ns quo2.components.password.tips.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:align-self :flex-start})
|
||||
|
||||
(defn tip-text
|
||||
[completed?]
|
||||
{:color (if completed? colors/white-opa-40 colors/white-opa-70)})
|
||||
|
||||
(def strike-through
|
||||
{:position :absolute
|
||||
:background-color colors/white
|
||||
:top 10
|
||||
:left 0
|
||||
:right 0
|
||||
:height 0.8})
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
(ns quo2.components.password.tips.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.password.tips.style :as style]
|
||||
[quo2.components.markdown.text :as text]))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
- `completed?` Password tip state
|
||||
|
||||
`text` Password tip string
|
||||
"
|
||||
[{:keys [completed?]} text]
|
||||
[rn/view
|
||||
{:style style/container
|
||||
:accessibility-label :password-tips}
|
||||
[text/text
|
||||
{:style (style/tip-text completed?)
|
||||
:weight :regular
|
||||
:size :paragraph-2} text]
|
||||
(when completed?
|
||||
[rn/view
|
||||
{:style style/strike-through
|
||||
:accessibility-label :password-tips-completed}])])
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require
|
||||
[quo2.components.profile.profile-card.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.buttons.button :as button]
|
||||
@@ -25,8 +25,7 @@
|
||||
:profile-picture profile-picture
|
||||
:override-theme :dark
|
||||
:size :medium
|
||||
:status-indicator? false
|
||||
:ring? true}]
|
||||
:status-indicator? false}]
|
||||
[button/button
|
||||
{:size 32
|
||||
:type :blur-bg
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
(ns quo2.components.profile.select-profile.component-spec
|
||||
(:require [quo2.components.profile.select-profile.view :as select-profile]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "select-profile component"
|
||||
(h/test "render component"
|
||||
(h/render [select-profile/view])
|
||||
(-> (h/expect (h/get-by-label-text :select-profile))
|
||||
(.toBeTruthy)))
|
||||
(h/test "call on-change handler when clicked"
|
||||
(let [on-change (h/mock-fn)]
|
||||
(h/render [select-profile/view {:on-change on-change}])
|
||||
(h/fire-event :on-press (h/get-by-label-text :select-profile))
|
||||
(-> (h/expect on-change)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
(ns quo2.components.profile.select-profile.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[customization-color selected?]
|
||||
{:padding 12
|
||||
:background-color (colors/custom-color customization-color 50 40)
|
||||
:border-width 1
|
||||
:border-radius 16
|
||||
:flex 1
|
||||
:border-color (if selected? colors/white-opa-40 :transparent)})
|
||||
|
||||
(def header
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(def profile-name
|
||||
{:margin-top 8
|
||||
:color colors/white})
|
||||
|
||||
(defn select-radio
|
||||
[selected?]
|
||||
{:background-color (if selected? :transparent colors/white-opa-5)
|
||||
:border-width 1.2
|
||||
:width 20
|
||||
:height 20
|
||||
:border-radius 10
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color (if selected? colors/white colors/white-opa-40)})
|
||||
|
||||
(def select-radio-inner
|
||||
{:background-color colors/white
|
||||
:border-radius 7
|
||||
:width 14
|
||||
:height 14})
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
(ns quo2.components.profile.select-profile.view
|
||||
(:require
|
||||
[quo2.components.profile.select-profile.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- on-change-handler
|
||||
[selected? on-change]
|
||||
(swap! selected? not)
|
||||
(when on-change (on-change @selected?)))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
- `default-selected?` The default selected state. Use when the component is not controlled.
|
||||
- `selected?` Selected state. Use when the component is controlled.
|
||||
- `name` Full name
|
||||
- `profile-picture` Profile picture
|
||||
- `customization-color` Customization color
|
||||
- `(on-change selected?)` On change event handler
|
||||
"
|
||||
[{:keys [default-selected?]}]
|
||||
(let [internal-selected? (reagent/atom (or default-selected? false))]
|
||||
(fn [{:keys [selected?
|
||||
profile-picture
|
||||
ring-background
|
||||
name
|
||||
customization-color
|
||||
on-change]
|
||||
:or {customization-color :turquoise}}]
|
||||
(let [avatar-image-key (if profile-picture :profile-picture :ring-background)
|
||||
picture (or profile-picture ring-background)]
|
||||
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
|
||||
(reset! internal-selected? selected?))
|
||||
[rn/touchable-opacity
|
||||
{:style (style/container customization-color @internal-selected?)
|
||||
:on-press #(on-change-handler internal-selected? on-change)
|
||||
:active-opacity 1
|
||||
:accessibility-label :select-profile}
|
||||
[rn/view {:style style/header}
|
||||
[user-avatar/user-avatar
|
||||
{:full-name name
|
||||
:status-indicator? false
|
||||
:size :medium
|
||||
avatar-image-key picture}]
|
||||
[rn/view {:style (style/select-radio @internal-selected?)}
|
||||
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style style/profile-name}
|
||||
name]]))))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.record-audio.record-audio.--tests--.record-audio-component-spec
|
||||
(:require [quo2.components.record-audio.record-audio.view :as record-audio]
|
||||
[status-im.audio.core :as audio]
|
||||
[react-native.audio-toolkit :as audio]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "record audio component"
|
||||
@@ -20,7 +20,9 @@
|
||||
|
||||
(h/test "record-audio on-start-recording works"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-start-recording event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-start-recording event
|
||||
:record-audio-permission-granted true}])
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
@@ -31,7 +33,9 @@
|
||||
|
||||
(h/test "record-audio on-reviewing-audio works"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-reviewing-audio event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-reviewing-audio event
|
||||
:record-audio-permission-granted true}])
|
||||
(with-redefs [audio/start-recording (fn [_ on-start _]
|
||||
(on-start))]
|
||||
(h/fire-event
|
||||
@@ -50,7 +54,9 @@
|
||||
|
||||
(h/test "record-audio on-send works after reviewing audio"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-send event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-send event
|
||||
:record-audio-permission-granted true}])
|
||||
(with-redefs [audio/start-recording (fn [_ on-start _]
|
||||
(on-start))
|
||||
audio/get-recorder-file-path (fn [] "audio-file-path")]
|
||||
@@ -77,7 +83,9 @@
|
||||
|
||||
(h/test "record-audio on-send works after sliding to the send button"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-send event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-send event
|
||||
:record-audio-permission-granted true}])
|
||||
(with-redefs [audio/start-recording (fn [_ on-start _]
|
||||
(on-start))
|
||||
audio/stop-recording (fn [_ on-stop _]
|
||||
@@ -108,7 +116,9 @@
|
||||
|
||||
(h/test "record-audio on-cancel works after reviewing audio"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-cancel event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-cancel event
|
||||
:record-audio-permission-granted true}])
|
||||
(with-redefs [audio/start-recording (fn [_ on-start _]
|
||||
(on-start))]
|
||||
(h/fire-event
|
||||
@@ -132,7 +142,9 @@
|
||||
|
||||
(h/test "cord-audio on-cancel works after sliding to the cancel button"
|
||||
(let [event (js/jest.fn)]
|
||||
(h/render [record-audio/record-audio {:on-cancel event}])
|
||||
(h/render [record-audio/record-audio
|
||||
{:on-cancel event
|
||||
:record-audio-permission-granted true}])
|
||||
(with-redefs [audio/start-recording (fn [_ on-start _]
|
||||
(on-start))
|
||||
audio/stop-recording (fn [_ on-stop _]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn :refer [use-effect]]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.audio.core :as audio]
|
||||
[react-native.audio-toolkit :as audio]
|
||||
[taoensso.timbre :as log]
|
||||
[cljs-bean.core :as bean]
|
||||
[reagent.core :as reagent]
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
(ns quo2.components.record-audio.record-audio.view
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[oops.core :as oops]
|
||||
(:require [oops.core :as oops]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.record-audio.record-audio.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.record-audio.soundtrack.view :as soundtrack]
|
||||
[react-native.core :as rn :refer [use-effect]]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.utils.utils :as utils]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[goog.string :as gstring]
|
||||
[status-im.audio.core :as audio]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.i18n :as i18n]
|
||||
[react-native.permissions :as permissions]
|
||||
[react-native.audio-toolkit :as audio]
|
||||
[taoensso.timbre :as log]
|
||||
[quo2.components.record-audio.record-audio.buttons.record-button-big :as record-button-big]
|
||||
[quo2.components.record-audio.record-audio.buttons.send-button :as send-button]
|
||||
@@ -154,7 +149,8 @@
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)}]]))])
|
||||
|
||||
(defn view
|
||||
[{:keys [on-start-recording on-send on-cancel on-reviewing-audio]}]
|
||||
[{:keys [on-start-recording on-send on-cancel on-reviewing-audio record-audio-permission-granted
|
||||
on-request-record-audio-permission on-check-audio-permissions]}]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [recording? (reagent/atom false)
|
||||
@@ -176,29 +172,8 @@
|
||||
playing-timer (atom nil)
|
||||
recorder-ref (atom nil)
|
||||
player-ref (atom nil)
|
||||
record-audio-permission-granted (atom true)
|
||||
output-file (atom nil)
|
||||
reached-max-duration? (atom false)
|
||||
check-audio-permission
|
||||
(fn []
|
||||
(permissions/permission-granted?
|
||||
:record-audio
|
||||
#(reset! record-audio-permission-granted %)
|
||||
#(reset! record-audio-permission-granted false)))
|
||||
request-record-audio-permission
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
[:request-permissions
|
||||
{:permissions [:record-audio]
|
||||
:on-allowed
|
||||
#(reset! record-audio-permission-granted true)
|
||||
:on-denied
|
||||
#(js/setTimeout
|
||||
(fn []
|
||||
(utils/show-popup
|
||||
(i18n/label :t/audio-recorder-error)
|
||||
(i18n/label :t/audio-recorder-permissions-error)))
|
||||
50)}]))
|
||||
destroy-player
|
||||
(fn []
|
||||
(audio/destroy-player @player-ref)
|
||||
@@ -247,7 +222,7 @@
|
||||
:ignore-max-x? false}
|
||||
record-button-area)]
|
||||
(when-not @reviewing-audio?
|
||||
(if @record-audio-permission-granted
|
||||
(if record-audio-permission-granted
|
||||
(do
|
||||
(when (not @idle?)
|
||||
(reset! recording? pressed-record-button?))
|
||||
@@ -294,8 +269,8 @@
|
||||
#(log/error "[record-audio] start recording - error: " %))
|
||||
(when on-start-recording
|
||||
(on-start-recording))))
|
||||
(request-record-audio-permission)))
|
||||
(when @record-audio-permission-granted
|
||||
(some-> on-request-record-audio-permission)))
|
||||
(when record-audio-permission-granted
|
||||
(reset! touch-active? true))))
|
||||
(not @idle?))
|
||||
on-responder-move
|
||||
@@ -469,7 +444,7 @@
|
||||
(reset! reached-max-duration? false)))]
|
||||
(fn []
|
||||
(use-effect (fn []
|
||||
(check-audio-permission)
|
||||
(some-> on-check-audio-permissions)
|
||||
(reload-recorder)))
|
||||
[rn/view
|
||||
{:style style/bar-container}
|
||||
@@ -515,14 +490,4 @@
|
||||
on-cancel]
|
||||
[record-button/record-button recording? reviewing-audio?]]])))])
|
||||
|
||||
(def record-audio
|
||||
(reagent/adapt-react-class
|
||||
(rn/memo
|
||||
(fn [props]
|
||||
(let [{:keys [onStartRecording onReviewingAudio onSend onCancel]} (bean/bean props)]
|
||||
(reagent/as-element
|
||||
[view
|
||||
{:on-start-recording onStartRecording
|
||||
:on-reviewing-audio onReviewingAudio
|
||||
:on-send onSend
|
||||
:on-cancel onCancel}]))))))
|
||||
(def record-audio view)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require [quo2.components.record-audio.soundtrack.view :as soundtrack]
|
||||
[test-helpers.component :as h]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.audio.core :as audio]))
|
||||
[react-native.audio-toolkit :as audio]))
|
||||
|
||||
(h/describe "soundtrack component"
|
||||
(h/before-each
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns quo2.components.record-audio.soundtrack.view
|
||||
(:require [quo2.components.record-audio.soundtrack.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.audio.core :as audio]
|
||||
[react-native.audio-toolkit :as audio]
|
||||
[taoensso.timbre :as log]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.slider :as slider]))
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
;; {:overflow :visible} doesn't work on components inheriting
|
||||
;; from ScrollView (e.g. FlatList). There are open issues, here's
|
||||
;; just one about this topic:
|
||||
;; https://github.com/facebook/react-native/issues/3121
|
||||
;; https://github.com/facebook/react-native/issues/31218
|
||||
:content-container-style {:padding-top (dec unread-count-offset)}
|
||||
:extra-data (str @active-tab-id)
|
||||
:horizontal true
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
(def small-container-style
|
||||
(merge default-container-style
|
||||
{:padding-horizontal 8
|
||||
:padding-vertical 3}))
|
||||
:padding-vertical 1}))
|
||||
|
||||
(def large-container-style
|
||||
(merge default-container-style
|
||||
@@ -56,8 +56,8 @@
|
||||
[size theme label]
|
||||
[base-tag
|
||||
{:size size
|
||||
:background-color colors/success-50-opa-10
|
||||
:icon :verified
|
||||
:background-color colors/success-50-opa-10
|
||||
:border-color colors/success-50-opa-20
|
||||
:label label
|
||||
:text-color (if (= theme :light)
|
||||
@@ -77,18 +77,14 @@
|
||||
colors/danger-60)}])
|
||||
|
||||
(defn- pending
|
||||
[size theme label]
|
||||
[size _ label]
|
||||
[base-tag
|
||||
{:size size
|
||||
:icon :pending
|
||||
:label label
|
||||
:background-color (if (= theme :light)
|
||||
colors/neutral-10
|
||||
colors/neutral-80)
|
||||
:border-color (if (= theme :light)
|
||||
colors/neutral-20
|
||||
colors/neutral-70)
|
||||
:text-color colors/neutral-50}])
|
||||
:background-color colors/white-opa-5
|
||||
:border-color colors/white-opa-5
|
||||
:text-color colors/white-opa-70}])
|
||||
|
||||
(defn status-tag
|
||||
[{:keys [status size override-theme label]}]
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
quo2.components.avatars.channel-avatar
|
||||
quo2.components.avatars.group-avatar
|
||||
quo2.components.avatars.icon-avatar
|
||||
quo2.components.avatars.user-avatar
|
||||
quo2.components.avatars.user-avatar.view
|
||||
quo2.components.avatars.wallet-user-avatar
|
||||
quo2.components.banners.banner.view
|
||||
quo2.components.buttons.button
|
||||
quo2.components.buttons.dynamic-button
|
||||
quo2.components.colors.color-picker.view
|
||||
quo2.components.community.community-card-view
|
||||
quo2.components.community.community-list-view
|
||||
quo2.components.community.community-view
|
||||
@@ -20,6 +21,7 @@
|
||||
quo2.components.dividers.date
|
||||
quo2.components.dividers.divider-label
|
||||
quo2.components.dividers.new-messages
|
||||
quo2.components.dividers.strength-divider.view
|
||||
quo2.components.drawers.action-drawers.view
|
||||
quo2.components.drawers.drawer-buttons.view
|
||||
quo2.components.drawers.permission-context.view
|
||||
@@ -28,6 +30,7 @@
|
||||
quo2.components.icon
|
||||
quo2.components.info.info-message
|
||||
quo2.components.info.information-box
|
||||
quo2.components.input.view
|
||||
quo2.components.list-items.channel
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list
|
||||
@@ -43,7 +46,9 @@
|
||||
quo2.components.notifications.info-count
|
||||
quo2.components.notifications.notification-dot
|
||||
quo2.components.notifications.toast
|
||||
quo2.components.password.tips.view
|
||||
quo2.components.profile.profile-card.view
|
||||
quo2.components.profile.select-profile.view
|
||||
quo2.components.reactions.reaction
|
||||
quo2.components.selectors.disclaimer.view
|
||||
quo2.components.selectors.filter.view
|
||||
@@ -59,7 +64,8 @@
|
||||
quo2.components.tags.permission-tag
|
||||
quo2.components.tags.tag
|
||||
quo2.components.tags.tags
|
||||
quo2.components.tags.token-tag))
|
||||
quo2.components.tags.token-tag
|
||||
quo2.components.list-items.user-list))
|
||||
|
||||
(def toast quo2.components.notifications.toast/toast)
|
||||
(def button quo2.components.buttons.button/button)
|
||||
@@ -90,14 +96,13 @@
|
||||
(def filter quo2.components.selectors.filter.view/view)
|
||||
(def skeleton quo2.components.loaders.skeleton/skeleton)
|
||||
(def author quo2.components.messages.author.view/author)
|
||||
(def display-name quo2.components.messages.author.view/display-name)
|
||||
|
||||
;;;; AVATAR
|
||||
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
||||
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
|
||||
(def group-avatar quo2.components.avatars.group-avatar/group-avatar)
|
||||
(def icon-avatar quo2.components.avatars.icon-avatar/icon-avatar)
|
||||
(def user-avatar quo2.components.avatars.user-avatar/user-avatar)
|
||||
(def user-avatar quo2.components.avatars.user-avatar.view/user-avatar)
|
||||
(def wallet-user-avatar quo2.components.avatars.wallet-user-avatar/wallet-user-avatar)
|
||||
|
||||
;;;; BANNER
|
||||
@@ -106,6 +111,10 @@
|
||||
;;;; CARDS
|
||||
(def small-option-card quo2.components.onboarding.small-option-card.view/small-option-card)
|
||||
|
||||
;;;; COLORS
|
||||
(def color-picker quo2.components.colors.color-picker.view/view)
|
||||
(def picker-colors quo2.components.colors.color-picker.view/picker-colors)
|
||||
|
||||
;;;; COMMUNITY
|
||||
(def community-card-view-item quo2.components.community.community-card-view/community-card-view-item)
|
||||
(def communities-list-view-item quo2.components.community.community-list-view/communities-list-view-item)
|
||||
@@ -124,16 +133,21 @@
|
||||
(def divider-label quo2.components.dividers.divider-label/divider-label)
|
||||
(def new-messages quo2.components.dividers.new-messages/new-messages)
|
||||
(def divider-date quo2.components.dividers.date/date)
|
||||
(def strength-divider quo2.components.dividers.strength-divider.view/view)
|
||||
|
||||
;;;; DRAWERS
|
||||
(def action-drawer quo2.components.drawers.action-drawers.view/action-drawer)
|
||||
(def drawer-buttons quo2.components.drawers.drawer-buttons.view/view)
|
||||
(def permission-context quo2.components.drawers.permission-context.view/view)
|
||||
|
||||
;;;; INPUTS
|
||||
(def input quo2.components.input.view/input)
|
||||
|
||||
;;;; LIST ITEMS
|
||||
(def channel-list-item quo2.components.list-items.channel/list-item)
|
||||
(def menu-item quo2.components.list-items.menu-item/menu-item)
|
||||
(def preview-list quo2.components.list-items.preview-list/preview-list)
|
||||
(def user-list quo2.components.list-items.user-list/user-list)
|
||||
|
||||
;;;; NOTIFICATIONS
|
||||
(def activity-log quo2.components.notifications.activity-log.view/view)
|
||||
@@ -141,8 +155,12 @@
|
||||
(def notification-dot quo2.components.notifications.notification-dot/notification-dot)
|
||||
(def count-down-circle quo2.components.notifications.count-down-circle/circle-timer)
|
||||
|
||||
;;;; PASSWORD
|
||||
(def tips quo2.components.password.tips.view/view)
|
||||
|
||||
;;;; PROFILE
|
||||
(def profile-card quo2.components.profile.profile-card.view/profile-card)
|
||||
(def select-profile quo2.components.profile.select-profile.view/view)
|
||||
|
||||
;;;; SETTINGS
|
||||
(def privacy-option quo2.components.settings.privacy-option/card)
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
(ns quo2.core-spec
|
||||
(:require [quo2.components.banners.banner.component-spec]
|
||||
(:require [quo2.components.avatars.user-avatar.component-spec]
|
||||
[quo2.components.banners.banner.component-spec]
|
||||
[quo2.components.buttons.--tests--.buttons-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.colors.color-picker.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.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.filter.component-spec]))
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
|
||||
;;Blur
|
||||
(def neutral-5-opa-70 (alpha neutral-5 0.7))
|
||||
(def neutral-80-blur-opa-80 "rgba(25,36,56,0.8)")
|
||||
(def neutral-90-opa-70 (alpha neutral-90 0.7))
|
||||
|
||||
;;80 with transparency
|
||||
@@ -152,6 +153,10 @@
|
||||
(def success-60-opa-40 (alpha success-60 0.4))
|
||||
|
||||
;;;;Danger
|
||||
(def danger "#E95460")
|
||||
|
||||
;; Danger with transparency
|
||||
(def danger-opa-40 (alpha danger 0.4))
|
||||
|
||||
;;Solid
|
||||
(def danger-50 "#E65F5C")
|
||||
@@ -170,26 +175,40 @@
|
||||
(def customization
|
||||
{:primary {50 primary-50 ;; User can also use primary color as customisation color
|
||||
60 primary-60}
|
||||
:purple {50 "#8661C1"
|
||||
60 "#5E478C"}
|
||||
:purple {50 "#7140FD"
|
||||
60 "#5A33CA"}
|
||||
:indigo {50 "#496289"
|
||||
60 "#3D5273"}
|
||||
:turquoise {50 "#448EA2"
|
||||
60 "#397788"}
|
||||
:blue {50 "#4CB4EF"
|
||||
60 "#4097C9"}
|
||||
:turquoise {50 "#2A799B"
|
||||
60 "#22617C"}
|
||||
:blue {50 "#2A4AF5"
|
||||
60 "#223BC4"}
|
||||
:green {50 "#5BCC95"
|
||||
60 "#4CAB7D"}
|
||||
:yellow {50 "#FFCB53"
|
||||
60 "#D6AA46"}
|
||||
:orange {50 "#FB8F61"
|
||||
60 "#D37851"}
|
||||
:yellow {50 "#F6B03C"
|
||||
60 "#C58D30"}
|
||||
:orange {50 "#FF7D46"
|
||||
60 "#CC6438"}
|
||||
:red {50 "#F46666"
|
||||
60 "#CD5656"}
|
||||
:pink {50 "#FC7BAB"
|
||||
60 "#D46790"}
|
||||
:pink {50 "#F66F8F"
|
||||
60 "#C55972"}
|
||||
:brown {50 "#99604D"
|
||||
60 "#805141"}
|
||||
:sky {50 "#1992D7"
|
||||
60 "#1475AC"}
|
||||
:army {50 "#216266"
|
||||
60 "#1A4E52"}
|
||||
:magenta {50 "#EC266C"
|
||||
60 "#BD1E56"}
|
||||
:copper {50 "#CB6256"
|
||||
60 "#A24E45"}
|
||||
:camel {50 "#C78F67"
|
||||
60 "#9F7252"}
|
||||
:yin {50 "#09101C"
|
||||
60 "#1D232E"}
|
||||
:yang {50 "#FFFFFF"
|
||||
60 "#EBEBEB"}
|
||||
:beige {50 "#CAAE93"
|
||||
60 "#AA927C"}})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns status-im.audio.core
|
||||
(ns react-native.audio-toolkit
|
||||
(:require ["@react-native-community/audio-toolkit" :refer (Player Recorder MediaStates)]))
|
||||
|
||||
;; get mediastates from react module
|
||||
@@ -10,6 +10,10 @@
|
||||
|
||||
(def app-state ^js (.-AppState ^js react-native))
|
||||
|
||||
;; Only use this component for exceptional cases, otherwise use Reanimated, e.g.
|
||||
;; when using interpolated values exposed by RN Gesture Handler > Swipeable.
|
||||
(def animated-view (reagent/adapt-react-class react-native/Animated.View))
|
||||
|
||||
(def view (reagent/adapt-react-class (.-View ^js react-native)))
|
||||
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native)))
|
||||
(def image (reagent/adapt-react-class (.-Image ^js react-native)))
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
(defn- wrap-key-fn
|
||||
[f]
|
||||
(fn [data index]
|
||||
{:post [(some? %)]}
|
||||
(f data index)))
|
||||
(when f
|
||||
(f data index))))
|
||||
|
||||
(defn base-list-props
|
||||
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn]
|
||||
|
||||
@@ -1,27 +1,65 @@
|
||||
(ns react-native.gesture
|
||||
(:require ["react-native-gesture-handler" :refer
|
||||
(GestureDetector Gesture gestureHandlerRootHOC TapGestureHandler State)]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :refer [oget]]))
|
||||
(Gesture
|
||||
GestureDetector
|
||||
RectButton
|
||||
Swipeable
|
||||
TouchableWithoutFeedback
|
||||
gestureHandlerRootHOC)]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def gesture-detector (reagent/adapt-react-class GestureDetector))
|
||||
|
||||
(def gesture-handler-root-hoc gestureHandlerRootHOC)
|
||||
|
||||
(defn gesture-tap [] (.Tap ^js Gesture))
|
||||
|
||||
(defn gesture-pan [] (.Pan ^js Gesture))
|
||||
|
||||
(defn on-update [^js pan handler] (.onUpdate pan handler))
|
||||
(defn gesture-pinch [] (.Pinch ^js Gesture))
|
||||
|
||||
(defn on-start [^js pan handler] (.onStart pan handler))
|
||||
(defn on-begin [gesture handler] (.onBegin ^js gesture handler))
|
||||
|
||||
(defn on-end [^js pan handler] (.onEnd pan handler))
|
||||
(defn on-start [gesture handler] (.onStart ^js gesture handler))
|
||||
|
||||
(def tap-gesture-handler
|
||||
(reagent/adapt-react-class TapGestureHandler))
|
||||
(defn on-update [gesture handler] (.onUpdate ^js gesture handler))
|
||||
|
||||
(def states
|
||||
{:began (oget State "BEGAN")
|
||||
:active (oget State "ACTIVE")
|
||||
:cancelled (oget State "CANCELLED")
|
||||
:end (oget State "END")
|
||||
:failed (oget State "FAILED")
|
||||
:undetermined (oget State "UNDETERMINED")})
|
||||
(defn on-end [gesture handler] (.onEnd ^js gesture handler))
|
||||
|
||||
(defn on-finalize [gesture handler] (.onFinalize ^js gesture handler))
|
||||
|
||||
(defn number-of-taps [gesture count] (.numberOfTaps ^js gesture count))
|
||||
|
||||
(defn enabled [gesture enabled?] (.enabled ^js gesture enabled?))
|
||||
|
||||
(defn average-touches [gesture average-touches?] (.averageTouches ^js gesture average-touches?))
|
||||
|
||||
(defn simultaneous
|
||||
([g1 g2] (.Simultaneous ^js Gesture g1 g2))
|
||||
([g1 g2 g3] (.Simultaneous ^js Gesture g1 g2 g3)))
|
||||
|
||||
(defn exclusive [g1 g2] (.Exclusive ^js Gesture g1 g2))
|
||||
|
||||
;; RN Gesture Handler touchables are drop-in replacements for the RN ones. In
|
||||
;; some cases, it's the only touchable that works with Swipeable components.
|
||||
(def touchable-without-feedback (reagent/adapt-react-class TouchableWithoutFeedback))
|
||||
|
||||
(def rect-button (reagent/adapt-react-class RectButton))
|
||||
|
||||
(def ^:private swipeable-component
|
||||
(reagent/adapt-react-class Swipeable))
|
||||
|
||||
(defn swipeable
|
||||
[{:keys [render-left-actions render-right-actions] :as props} & children]
|
||||
(into [swipeable-component
|
||||
(cond-> props
|
||||
render-left-actions
|
||||
(assoc :render-left-actions
|
||||
(fn [& args]
|
||||
(reagent/as-element (apply render-left-actions args))))
|
||||
|
||||
render-right-actions
|
||||
(assoc :render-right-actions
|
||||
(fn [& args]
|
||||
(reagent/as-element (apply render-right-actions args)))))]
|
||||
children))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
(ns react-native.orientation
|
||||
(:require ["react-native-orientation-locker" :default orientation :refer (useDeviceOrientationChange)]
|
||||
[react-native.navigation :as navigation]))
|
||||
|
||||
(def use-device-orientation-change useDeviceOrientationChange)
|
||||
|
||||
(def get-auto-rotate-state (.-getAutoRotateState orientation))
|
||||
|
||||
(def portrait-options
|
||||
(clj->js {:layout {:orientation ["portrait"]}
|
||||
:statusBar {:visible true}}))
|
||||
|
||||
(def landscape-option-1 (clj->js {:layout {:orientation ["landscape"]}}))
|
||||
(def landscape-option-2 (clj->js {:statusBar {:visible false}}))
|
||||
|
||||
(defn lock-to-portrait
|
||||
[id]
|
||||
(navigation/merge-options id portrait-options))
|
||||
|
||||
(defn lock-to-landscape
|
||||
[id]
|
||||
(navigation/merge-options id landscape-option-1)
|
||||
;; On Android, hiding the status-bar while changing orientation causes a flicker, so we enqueue it
|
||||
(js/setTimeout #(navigation/merge-options id landscape-option-2) 0))
|
||||
|
||||
(def ^:const portrait "PORTRAIT")
|
||||
|
||||
(def ^:const landscape "LANDSCAPE")
|
||||
|
||||
(def ^:const landscape-left "LANDSCAPE-LEFT")
|
||||
|
||||
(def ^:const landscape-right "LANDSCAPE-RIGHT")
|
||||
@@ -9,6 +9,7 @@
|
||||
withDelay
|
||||
withSpring
|
||||
withRepeat
|
||||
withDecay
|
||||
Easing
|
||||
Keyframe
|
||||
cancelAnimation
|
||||
@@ -48,6 +49,7 @@
|
||||
(def with-timing withTiming)
|
||||
(def with-delay withDelay)
|
||||
(def with-spring withSpring)
|
||||
(def with-decay withDecay)
|
||||
(def key-frame Keyframe)
|
||||
(def with-repeat withRepeat)
|
||||
(def cancel-animation cancelAnimation)
|
||||
@@ -55,9 +57,12 @@
|
||||
;; Easings
|
||||
(def bezier (.-bezier ^js Easing))
|
||||
|
||||
(def in-out
|
||||
(.-inOut ^js Easing))
|
||||
|
||||
(def easings
|
||||
{:linear (bezier 0 0 1 1)
|
||||
:easing1 (bezier 0.25 0.1 0.25 1) ;; TODO(parvesh) - rename easing functions, (design team input)
|
||||
:easing1 (bezier 0.25 0.1 0.25 1)
|
||||
:easing2 (bezier 0 0.3 0.6 0.9)
|
||||
:easing3 (bezier 0.3 0.3 0.3 0.9)})
|
||||
|
||||
@@ -107,6 +112,14 @@
|
||||
(js-obj "duration" duration
|
||||
"easing" (get easings 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?]
|
||||
(set-shared-value anim
|
||||
@@ -137,3 +150,15 @@
|
||||
(js-obj "mass" mass
|
||||
"damping" damping
|
||||
"stiffness" stiffness))))
|
||||
|
||||
(defn animate-shared-value-with-decay
|
||||
[anim velocity clamp]
|
||||
(set-shared-value anim
|
||||
(with-decay (clj->js {:velocity velocity
|
||||
:clamp clamp}))))
|
||||
|
||||
(defn with-timing-duration
|
||||
[val duration]
|
||||
(with-timing val
|
||||
(clj->js {:duration duration
|
||||
:easing (in-out (.-quad ^js Easing))})))
|
||||
|
||||
@@ -7,3 +7,5 @@
|
||||
(def rect (reagent/adapt-react-class Svg/Rect))
|
||||
(def clippath (reagent/adapt-react-class Svg/ClipPath))
|
||||
(def defs (reagent/adapt-react-class Svg/Defs))
|
||||
(def circle (reagent/adapt-react-class Svg/Circle))
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.add-new.db :as db]
|
||||
[status-im2.contexts.chat.events :as chat]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im2.contexts.contacts.events :as contact]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
@@ -91,7 +91,7 @@
|
||||
(i18n/label :t/use-valid-contact-code)
|
||||
:yourself
|
||||
(i18n/label :t/can-not-add-yourself))
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :shell-stack])}})))
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
|
||||
|
||||
(rf/defn qr-code-scanned
|
||||
{:events [:contact/qr-code-scanned]}
|
||||
|
||||
@@ -305,9 +305,10 @@
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id (:browser-id browser)})}
|
||||
(navigation/change-tab :browser)
|
||||
(navigation/set-stack-root :browser-stack :browser)
|
||||
{:browser-id (:browser-id browser)}
|
||||
:browser/screen-id :browser)}
|
||||
(navigation/pop-to-root :shell-stack)
|
||||
(navigation/change-tab :browser-stack)
|
||||
(update-browser browser)
|
||||
(resolve-url nil)))))
|
||||
|
||||
@@ -319,11 +320,19 @@
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id browser-id})}
|
||||
{:browser-id browser-id}
|
||||
:browser/screen-id :browser)}
|
||||
(update-browser browser)
|
||||
(navigation/set-stack-root :browser-stack :browser)
|
||||
(navigation/change-tab :browser-stack)
|
||||
(resolve-url nil))))
|
||||
|
||||
(rf/defn open-browser-tabs
|
||||
{:events [:browser.ui/open-browser-tabs]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :browser/screen-id :browser-tabs)}
|
||||
(navigation/change-tab :browser-stack)))
|
||||
|
||||
(rf/defn web3-error-callback
|
||||
{:events [:browser.dapp/transaction-on-error]}
|
||||
[_ message-id message]
|
||||
@@ -573,9 +582,9 @@
|
||||
|
||||
(rf/defn open-empty-tab
|
||||
{:events [:browser.ui/open-empty-tab]}
|
||||
[cofx]
|
||||
[{:keys [db]}]
|
||||
(debounce/clear :browser/navigation-state-changed)
|
||||
(navigation/set-stack-root cofx :browser-stack :empty-tab))
|
||||
{:db (assoc db :browser/screen-id :empty-tab)})
|
||||
|
||||
(rf/defn url-input-pressed
|
||||
{:events [:browser.ui/url-input-pressed]}
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
(fn [^js resized-image]
|
||||
(let [path (.-path resized-image)
|
||||
path (if (string/starts-with? path "file") path (str "file://" path))]
|
||||
(cb path)))
|
||||
(cb {:resized-uri path
|
||||
:width width
|
||||
:height height})))
|
||||
#(log/error "could not resize image" %))))))
|
||||
|
||||
(defn result->id
|
||||
@@ -238,13 +240,15 @@
|
||||
|
||||
(rf/defn image-selected
|
||||
{:events [:chat.ui/image-selected]}
|
||||
[{:keys [db]} current-chat-id original uri]
|
||||
[{:keys [db]} current-chat-id original {:keys [resized-uri width height]}]
|
||||
{:db
|
||||
(update-in db
|
||||
[:chat/inputs current-chat-id :metadata :sending-image (:uri original)]
|
||||
merge
|
||||
original
|
||||
{:resized-uri uri})})
|
||||
{:resized-uri resized-uri
|
||||
:width width
|
||||
:height height})})
|
||||
|
||||
(rf/defn image-unselected
|
||||
{:events [:chat.ui/image-unselected]}
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
|
||||
(rf/defn select-mention
|
||||
{:events [:chat.ui/select-mention]}
|
||||
[{:keys [db] :as cofx} text-input-ref {:keys [alias name searched-text match] :as user}]
|
||||
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match] :as user}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
new-text (mentions/new-input-text-with-mention cofx user)
|
||||
at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx])
|
||||
cursor (+ at-sign-idx (count name) 2)]
|
||||
cursor (+ at-sign-idx (count primary-name) 2)]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
@@ -63,15 +63,14 @@
|
||||
;; NOTE(roman): on-text-input event is not dispatched when we change input
|
||||
;; programmatically, so we have to call `on-text-input` manually
|
||||
(mentions/on-text-input
|
||||
(let [match-len (count match)
|
||||
searched-text-len (count searched-text)
|
||||
start (inc at-sign-idx)
|
||||
end (+ start match-len)]
|
||||
(let [match-len (count match)
|
||||
start (inc at-sign-idx)
|
||||
end (+ start match-len)]
|
||||
{:new-text match
|
||||
:previous-text searched-text
|
||||
:start start
|
||||
:end end}))
|
||||
(mentions/recheck-at-idxs {alias user}))))
|
||||
(mentions/recheck-at-idxs {primary-name user}))))
|
||||
|
||||
(rf/defn disable-chat-cooldown
|
||||
"Turns off chat cooldown (protection against message spamming)"
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
(get-in db [:pagination-info chat-id :messages-initialized?])))
|
||||
(let [already-loaded-messages (get-in db [:messages chat-id])
|
||||
;; We remove those messages that are already loaded, as we might get some duplicates
|
||||
{:keys [all-messages new-messages senders contacts]}
|
||||
{:keys [all-messages new-messages contacts]}
|
||||
(reduce (fn [{:keys [all-messages] :as acc}
|
||||
{:keys [message-id from]
|
||||
:as message}]
|
||||
@@ -143,25 +143,23 @@
|
||||
:cursor-clock-value])
|
||||
clock-value (when cursor (cursor->clock-value cursor))
|
||||
new-messages (map mark-album new-messages)]
|
||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||
:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
#(if (and (seq cursor) (or (not %) (< clock-value %)))
|
||||
clock-value
|
||||
%))
|
||||
|
||||
(update-in [:pagination-info chat-id :cursor]
|
||||
#(if (or (empty? cursor)
|
||||
(not current-clock-value)
|
||||
(< clock-value current-clock-value))
|
||||
cursor
|
||||
%))
|
||||
(assoc-in [:pagination-info chat-id :loading-messages?] false)
|
||||
(assoc-in [:messages chat-id] all-messages)
|
||||
(update-in [:message-lists chat-id] message-list/add-many new-messages)
|
||||
(assoc-in [:pagination-info chat-id :all-loaded?]
|
||||
(empty? cursor))
|
||||
(update :contacts/contacts merge contacts))})))
|
||||
{:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
#(if (and (seq cursor) (or (not %) (< clock-value %)))
|
||||
clock-value
|
||||
%))
|
||||
(update-in [:pagination-info chat-id :cursor]
|
||||
#(if (or (empty? cursor)
|
||||
(not current-clock-value)
|
||||
(< clock-value current-clock-value))
|
||||
cursor
|
||||
%))
|
||||
(assoc-in [:pagination-info chat-id :loading-messages?] false)
|
||||
(assoc-in [:messages chat-id] all-messages)
|
||||
(update-in [:message-lists chat-id] message-list/add-many new-messages)
|
||||
(assoc-in [:pagination-info chat-id :all-loaded?]
|
||||
(empty? cursor))
|
||||
(update :contacts/contacts merge contacts))})))
|
||||
|
||||
(rf/defn load-more-messages
|
||||
{:events [:chat.ui/load-more-messages]}
|
||||
|
||||
@@ -9,13 +9,10 @@
|
||||
[status-im.native-module.core :as status]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def at-sign "@")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn re-pos
|
||||
[re s]
|
||||
(loop [res []
|
||||
@@ -177,43 +174,25 @@
|
||||
|
||||
:else (recur data (inc idx)))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn add-searchable-phrases
|
||||
[{:keys [alias name nickname] :as user}]
|
||||
(reduce
|
||||
(fn [user s]
|
||||
(if (nil? s)
|
||||
user
|
||||
(let [new-words (concat
|
||||
[s]
|
||||
(rest (string/split s " ")))]
|
||||
(update user :searchable-phrases (fnil concat []) new-words))))
|
||||
user
|
||||
[alias name nickname]))
|
||||
|
||||
(defn add-searchable-phrases-to-contact
|
||||
[{:keys [alias name added? blocked? identicon public-key nickname ens-verified]} community-chat?]
|
||||
(when (and alias
|
||||
(not (string/blank? alias))
|
||||
(or name
|
||||
nickname
|
||||
added?
|
||||
community-chat?)
|
||||
(not blocked?))
|
||||
(add-searchable-phrases
|
||||
{:alias alias
|
||||
:name (or (and ens-verified (utils/safe-replace name ".stateofus.eth" "")) alias)
|
||||
:identicon identicon
|
||||
:nickname nickname
|
||||
:ens-verified ens-verified
|
||||
:public-key public-key})))
|
||||
[{:keys [primary-name secondary-name blocked?] :as contact}]
|
||||
(when (not blocked?)
|
||||
(reduce
|
||||
(fn [user s]
|
||||
(if (nil? s)
|
||||
user
|
||||
(let [new-words (concat
|
||||
[s]
|
||||
(rest (string/split s " ")))]
|
||||
(update user :searchable-phrases (fnil concat []) new-words))))
|
||||
contact
|
||||
[primary-name secondary-name])))
|
||||
|
||||
(defn mentionable-contacts
|
||||
[contacts]
|
||||
(reduce
|
||||
(fn [acc [key contact]]
|
||||
(let [mentionable-contact (add-searchable-phrases-to-contact contact false)]
|
||||
(let [mentionable-contact (add-searchable-phrases-to-contact contact)]
|
||||
(if (nil? mentionable-contact)
|
||||
acc
|
||||
(assoc acc key mentionable-contact))))
|
||||
@@ -223,17 +202,8 @@
|
||||
(defn mentionable-contacts-from-identites
|
||||
[contacts my-public-key identities]
|
||||
(reduce (fn [acc identity]
|
||||
(let [contact (multiaccounts/contact-by-identity
|
||||
contacts
|
||||
identity)
|
||||
contact (if (string/blank? (:alias contact))
|
||||
(assoc contact
|
||||
:alias
|
||||
(get-in contact [:names :three-words-name]))
|
||||
contact)
|
||||
mentionable-contact (add-searchable-phrases-to-contact
|
||||
contact
|
||||
true)]
|
||||
(let [contact (multiaccounts/contact-by-identity contacts identity)
|
||||
mentionable-contact (add-searchable-phrases-to-contact contact)]
|
||||
(if (nil? mentionable-contact)
|
||||
acc
|
||||
(assoc acc identity mentionable-contact))))
|
||||
@@ -247,9 +217,9 @@
|
||||
mentionable-contacts (mentionable-contacts all-contacts)
|
||||
mentionable-users (assoc users
|
||||
public-key
|
||||
{:alias name
|
||||
:name (or preferred-name name)
|
||||
:public-key public-key})]
|
||||
{:secondary-name name
|
||||
:primary-name (or preferred-name name)
|
||||
:public-key public-key})]
|
||||
(cond
|
||||
(= chat-type constants/private-group-chat-type)
|
||||
(merge mentionable-users
|
||||
@@ -273,30 +243,31 @@
|
||||
(= chat-type constants/public-chat-type)
|
||||
(merge mentionable-users (select-keys mentionable-contacts (keys mentionable-users)))
|
||||
|
||||
:else mentionable-users)))
|
||||
:else
|
||||
mentionable-users)))
|
||||
|
||||
(def ending-chars "[\\s\\.,;:]")
|
||||
(def ending-chars-regex (re-pattern ending-chars))
|
||||
(def word-regex (re-pattern (str "^[\\w\\d]*" ending-chars "|^[\\S]*$")))
|
||||
|
||||
(defn mentioned?
|
||||
[{:keys [alias name]} text]
|
||||
(let [lcase-name (string/lower-case name)
|
||||
lcase-alias (string/lower-case alias)
|
||||
[{:keys [primary-name secondary-name]} text]
|
||||
(let [lcase-fname (string/lower-case primary-name)
|
||||
lcase-sname (when secondary-name (string/lower-case secondary-name))
|
||||
regex (re-pattern
|
||||
(string/join
|
||||
"|"
|
||||
[(str "^" lcase-name ending-chars)
|
||||
(str "^" lcase-name "$")
|
||||
(str "^" lcase-alias ending-chars)
|
||||
(str "^" lcase-alias "$")]))
|
||||
[(str "^" lcase-fname ending-chars)
|
||||
(str "^" lcase-fname "$")
|
||||
(str "^" lcase-sname ending-chars)
|
||||
(str "^" lcase-sname "$")]))
|
||||
lcase-text (string/lower-case text)]
|
||||
(re-find regex lcase-text)))
|
||||
|
||||
(defn get-user-suggestions
|
||||
[users searched-text]
|
||||
(reduce
|
||||
(fn [acc [k {:keys [alias name nickname searchable-phrases] :as user}]]
|
||||
(fn [acc [k {:keys [primary-name secondary-name searchable-phrases] :as user}]]
|
||||
(if-let [match
|
||||
(if (seq searchable-phrases)
|
||||
(when (some
|
||||
@@ -305,27 +276,23 @@
|
||||
(string/lower-case s)
|
||||
searched-text))
|
||||
searchable-phrases)
|
||||
(or name alias))
|
||||
(or primary-name secondary-name))
|
||||
(cond
|
||||
(and nickname
|
||||
(and primary-name
|
||||
(string/starts-with?
|
||||
(string/lower-case nickname)
|
||||
(string/lower-case primary-name)
|
||||
searched-text))
|
||||
(or name alias)
|
||||
(or primary-name secondary-name)
|
||||
|
||||
(and alias
|
||||
(and secondary-name
|
||||
(string/starts-with?
|
||||
(string/lower-case alias)
|
||||
(string/lower-case secondary-name)
|
||||
searched-text))
|
||||
alias
|
||||
|
||||
(string/starts-with?
|
||||
(string/lower-case name)
|
||||
searched-text)
|
||||
name))]
|
||||
secondary-name))]
|
||||
(assoc acc
|
||||
k
|
||||
(assoc user
|
||||
:key k
|
||||
:match match
|
||||
:searched-text searched-text))
|
||||
acc))
|
||||
@@ -642,7 +609,7 @@
|
||||
(assoc-in [:chats/mention-suggestions chat-id] mentions))}))))
|
||||
|
||||
(defn new-input-text-with-mention
|
||||
[{:keys [db]} {:keys [name]}]
|
||||
[{:keys [db]} {:keys [primary-name]}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [mention-end at-sign-idx]}
|
||||
@@ -652,7 +619,7 @@
|
||||
new-input-text-with-mention)
|
||||
(string/join
|
||||
[(subs text 0 (inc at-sign-idx))
|
||||
name
|
||||
primary-name
|
||||
(let [next-char (get text mention-end)]
|
||||
(when (or (not next-char)
|
||||
(and next-char
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"@helpinghand.eth"]
|
||||
[:text
|
||||
" "]])
|
||||
|
||||
(def ->info-expected
|
||||
{:at-sign-idx 2
|
||||
:mention-end 19
|
||||
@@ -75,17 +76,16 @@
|
||||
|
||||
(test/deftest test-replace-mentions
|
||||
(let [users {"User Number One"
|
||||
{:name "User Number One"
|
||||
:alias "User Number One"
|
||||
:public-key "0xpk1"}
|
||||
{:primary-name "User Number One"
|
||||
:public-key "0xpk1"}
|
||||
"User Number Two"
|
||||
{:name "user2"
|
||||
:alias "User Number Two"
|
||||
:public-key "0xpk2"}
|
||||
{:primary-name "user2"
|
||||
:secondary-name "User Number Two"
|
||||
:public-key "0xpk2"}
|
||||
"User Number Three"
|
||||
{:name "user3"
|
||||
:alias "User Number Three"
|
||||
:public-key "0xpk3"}}]
|
||||
{:primary-name "user3"
|
||||
:secondary-name "User Number Three"
|
||||
:public-key "0xpk3"}}]
|
||||
(test/testing "empty string"
|
||||
(let [text ""
|
||||
result (mentions/replace-mentions text users)]
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.contexts.chat.messages.delete-message.events :as delete-message]
|
||||
@@ -34,26 +32,6 @@
|
||||
;; TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
|
||||
(message-list/rebuild-message-list {:db (update-in db [:messages chat-id] dissoc message-id)} chat-id))
|
||||
|
||||
(rf/defn add-senders-to-chat-users
|
||||
{:events [:chat/add-senders-to-chat-users]}
|
||||
[{:keys [db]} messages]
|
||||
(reduce (fn [acc {:keys [chat-id alias name identicon from]}]
|
||||
(let [alias (if (string/blank? alias)
|
||||
(gfycat/generate-gfy from)
|
||||
alias)]
|
||||
(update-in acc
|
||||
[:db :chats chat-id :users]
|
||||
assoc
|
||||
from
|
||||
(mentions/add-searchable-phrases
|
||||
{:alias alias
|
||||
:name (or name alias)
|
||||
:identicon identicon
|
||||
:public-key from
|
||||
:nickname (get-in db [:contacts/contacts from :nickname])}))))
|
||||
{:db db}
|
||||
messages))
|
||||
|
||||
(defn add-message
|
||||
[{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
|
||||
(let [{:keys [replace from clock-value] :as message}
|
||||
@@ -118,7 +96,7 @@
|
||||
(defn receive-many
|
||||
[{:keys [db]} ^js response-js]
|
||||
(let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10))
|
||||
{:keys [db senders]}
|
||||
{:keys [db]}
|
||||
(reduce reduce-js-messages
|
||||
{:db db :chats #{} :senders {} :transactions #{}}
|
||||
messages-js)]
|
||||
@@ -128,9 +106,7 @@
|
||||
:utils/dispatch-later
|
||||
(concat [{:ms 20 :dispatch [:process-response response-js]}]
|
||||
(when (and (:current-chat-id db) (= "active" (:app-state db)))
|
||||
[{:ms 100 :dispatch [:chat/mark-all-as-read (:current-chat-id db)]}])
|
||||
(when (seq senders)
|
||||
[{:ms 100 :dispatch [:chat/add-senders-to-chat-users (vals senders)]}]))}))
|
||||
[{:ms 100 :dispatch [:chat/mark-all-as-read (:current-chat-id db)]}]))}))
|
||||
|
||||
(rf/defn update-db-message-status
|
||||
[{:keys [db] :as cofx} chat-id message-id status]
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
[clojure.walk :as walk]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im2.common.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im.ui.components.emoji-thumbnail.styles :as emoji-thumbnail-styles]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.common.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im2.common.toasts.events :as toasts]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def crop-size 1000)
|
||||
|
||||
@@ -71,7 +71,11 @@
|
||||
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
|
||||
:canJoin :can-join?
|
||||
:requestedToJoinAt :requested-to-join-at
|
||||
:isMember :is-member?})
|
||||
:isMember :is-member?
|
||||
:adminSettings :admin-settings})
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
|
||||
(update :members walk/stringify-keys)
|
||||
(update :chats <-chats-rpc)
|
||||
(update :categories <-categories-rpc)))
|
||||
@@ -115,7 +119,7 @@
|
||||
(let [community-name (aget response-js "communities" 0 "name")]
|
||||
(rf/merge cofx
|
||||
(handle-response cofx response-js)
|
||||
(toasts/upsert {:icon :placeholder
|
||||
(toasts/upsert {:icon :correct
|
||||
:icon-color (:positive-01 @colors/theme)
|
||||
:text (i18n/label :t/left-community {:community community-name})})
|
||||
(navigation/navigate-back)
|
||||
@@ -128,7 +132,7 @@
|
||||
community-name (aget response-js "communities" 0 "name")]
|
||||
(rf/merge cofx
|
||||
(handle-response cofx response-js)
|
||||
(toasts/upsert {:icon :placeholder
|
||||
(toasts/upsert {:icon :correct
|
||||
:icon-color (:positive-01 @colors/theme)
|
||||
:text (i18n/label (if (= event-name ::joined)
|
||||
:t/joined-community
|
||||
@@ -427,7 +431,7 @@
|
||||
(navigation/navigate-to :community-create nil)))
|
||||
|
||||
(rf/defn open-edit-community
|
||||
{:events [::open-edit-community]}
|
||||
{:events [::open-edit-community :communities/open-edit-community]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(let [{:keys [name description images permissions color]} (get-in db [:communities id])
|
||||
{:keys [access]} permissions]
|
||||
@@ -742,7 +746,7 @@
|
||||
{:events [:communities/navigate-to-community]}
|
||||
[cofx community-id]
|
||||
(rf/merge cofx
|
||||
(navigation/pop-to-root-tab :shell-stack)
|
||||
(navigation/pop-to-root :shell-stack)
|
||||
(navigation/navigate-to-nav2 :community community-id true)))
|
||||
|
||||
(rf/defn member-role-updated
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
[status-im2.contexts.chat.messages.list.events :as message-list]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im2.contexts.contacts.events :as contacts-store]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(rf/defn clean-up-chat
|
||||
[{:keys [db] :as cofx}
|
||||
[{:keys [db]}
|
||||
public-key
|
||||
{:keys [chat-id
|
||||
unviewed-messages-count
|
||||
@@ -35,18 +35,18 @@
|
||||
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
|
||||
|
||||
(rf/defn contact-blocked
|
||||
{:events [::contact-blocked]}
|
||||
[{:keys [db] :as cofx} {:keys [public-key]} chats]
|
||||
(let [fxs (when chats
|
||||
{:events [:contacts/blocked]}
|
||||
[{:keys [db] :as cofx} {:keys [public-key]} chats-js]
|
||||
(let [fxs (when chats-js
|
||||
(map #(->> (chats-store/<-rpc %)
|
||||
(clean-up-chat public-key))
|
||||
(types/js->clj chats)))]
|
||||
(types/js->clj chats-js)))]
|
||||
(apply rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :chats dissoc public-key)
|
||||
(update :chats-home-list disj public-key)
|
||||
(assoc-in [:contacts/contacts public-key :added] false))
|
||||
(assoc-in [:contacts/contacts public-key :added?] false))
|
||||
:dispatch [:shell/close-switcher-card public-key]
|
||||
:clear-message-notifications
|
||||
[[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
|
||||
@@ -59,34 +59,28 @@
|
||||
(let [contact (-> (contact.db/public-key->contact
|
||||
(:contacts/contacts db)
|
||||
public-key)
|
||||
(assoc :blocked true
|
||||
:added false))
|
||||
(assoc :blocked? true
|
||||
:added? false))
|
||||
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))]
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
;; add the contact to blocked contacts
|
||||
(update :contacts/blocked (fnil conj #{}) public-key)
|
||||
;; update the contact in contacts list
|
||||
(assoc-in [:contacts/contacts public-key] contact))}
|
||||
{:db (assoc-in db [:contacts/contacts public-key] contact)}
|
||||
(contacts-store/block
|
||||
public-key
|
||||
(fn [^js block-contact]
|
||||
(re-frame/dispatch [::contact-blocked contact (.-chats block-contact)])
|
||||
(re-frame/dispatch [:contacts/blocked contact (.-chats block-contact)])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response block-contact])
|
||||
(re-frame/dispatch [:hide-popover])))
|
||||
;; reset navigation to avoid going back to non existing one to one chat
|
||||
(if from-one-to-one-chat?
|
||||
(navigation/pop-to-root-tab :shell-stack)
|
||||
(navigation/pop-to-root :shell-stack)
|
||||
(navigation/navigate-back)))))
|
||||
|
||||
(rf/defn contact-unblocked
|
||||
{:events [::contact-unblocked]}
|
||||
{:events [:contacts/unblocked]}
|
||||
[{:keys [db]} contact-id]
|
||||
(let [contact (-> (get-in db [:contacts/contacts contact-id])
|
||||
(assoc :blocked false))]
|
||||
{:db (-> db
|
||||
(update :contacts/blocked disj contact-id)
|
||||
(assoc-in [:contacts/contacts contact-id] contact))}))
|
||||
(assoc :blocked? false))]
|
||||
{:db (assoc-in db [:contacts/contacts contact-id] contact)}))
|
||||
|
||||
(rf/defn unblock-contact
|
||||
{:events [:contact.ui/unblock-contact-pressed]}
|
||||
@@ -94,4 +88,4 @@
|
||||
(contacts-store/unblock
|
||||
cofx
|
||||
contact-id
|
||||
#(re-frame/dispatch [::contact-unblocked contact-id])))
|
||||
#(re-frame/dispatch [:contacts/unblocked contact-id])))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns status-im.contact.chat
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im2.contexts.contacts.events :as contact]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
|
||||