Compare commits

...
Author SHA1 Message Date
yqrashawn a440ef3fcd fix: lint 2023-06-06 15:29:38 +08:00
jakub c3065c9d2a nix: upgrade nixpkgs to latest nixos-22.11
Notable upgrades:

* Bash `5.1` to `5.2`
* Git `2.37.3` to `2.40.1`
* Curl `7.85.0` to `8.0.1`
* OpenSSL `3.0.5` to `3.0.8`
* Go `1.18.6` to `1.18.9`
* NodeJS `18.9.1` to `18.16.0`
* Java `1.8.0_322` to `11.0.18`
* Ruby `3.1.2` to `3.1.4`
* Python `2.7.18` to `3.10.11`
* Clojure `1.11.1.1165` to `1.11.1.1273`
* Clj-kondo `v2022.10.05` to `v2023.04.14`
* Zprint `1.2.5` to `1.2.6`
* Bundler `2.3.22` to `2.4.13`
* Gradle `6.9.2` to `6.9.4`
* Android Platform Tools `33.0.2` to `33.0.3`

Removals:

* Zprint since the version in `nixpkgs` was newer than in overlay.
* Xcode wrapper definition was removed since my fixes were merged:
  - https://github.com/NixOS/nixpkgs/pull/204278
  - https://github.com/NixOS/nixpkgs/pull/228696

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-06-05 19:08:09 +02:00
Icaro Motta b385e5ab4b Support unfurling more websites (#16040)
Bumps status-go's version to point to the status-go branch in PR
https://github.com/status-im/status-go/pull/3530.

Fixes https://github.com/status-im/status-mobile/issues/15918
2023-06-05 08:31:27 -03:00
Omar Basem 8407cd66d1 Debug mode fix: photo selector (#16146)
* Debug mode fix: photo selector
2023-06-05 12:39:25 +04:00
flexsurfer ba2f037f48 [#16094] Messaging - In Chat - Implement Options Menu for 1-1 and com… (#16131) 2023-06-05 10:25:13 +02:00
Yevheniia Berdnyk eea737625d e2e: fixes for emoji and xfails added 2023-06-03 02:16:17 +03:00
Alexander 39ea12cf29 Fix for "Rendered more hooks than during the previous render" error on closing group chat/communty channel (#16145)
* "Rendered more hooks than during the previous render" error on closing group chat/communty channel

* Lint fix
2023-06-02 14:49:46 +01:00
Mohamed Javid c5166ac48e [Fix] Open app on push notification tap (#16136)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-06-02 18:03:27 +05:30
Omar Basem c5e6bd790d Lightbox refactoring (#16096)
* refactor: lightbox
2023-06-02 15:56:39 +04:00
Ulises Manuel Cárdenas b29d248a9b [#16077] Empty state component 2023-06-02 04:16:55 -06:00
Alexander 396ee208bf Chat Screen Top Bar UI + new UI for user details (#15204)
* Fixes

* Reformatting + fixes

* Functions rewrite

* f-function

* One more f-function

* Minor constants fixes

* Jump to button removal

* Footer insets fix

* Better loading indicator

* Review fixes

* Fixes for Android

* More fixes

* More fixes

* Fix

* Fixes for scaling

* Overscroll fixes

* Better empty view on Android

* Android fixes, scrolling fixes

* Value fix

* Code style fixes

* Fix for scroll indicator insets

* Fixes

* Accessibility-ids

* Code style fixes

* Footer fix

* Style update
2023-06-01 16:08:47 +01:00
Rahul Pratap adb50fa0ee Feature/15776 slideshow styles (#15933)
* Fixed issues with styling in the slideshow.

* Fixed design feedbacks.
2023-06-01 19:56:36 +05:30
Icaro Motta 5017e13013 Fix reaction images and implement Selectors > Reactions component (#16114)
Fixes reaction images and implements the component Selectors > Reactions that,
for some reason, wasn't implemented as a separate quo2 component as per
Figma https://www.figma.com/file/qLLuMLfpGxK9OfpIavwsmK/Iconset?type=design&node-id=942-218&t=cqTr12Q3zVHaLoap-0

Fixes https://github.com/status-im/status-mobile/issues/16045

Note: Reaction images in the Design System are not icons, so that's why you are
seeing a bunch of icons removed from icons2. The directory
resources/images/reactions already existed, and so I used images from that
directory instead.
2023-06-01 11:14:20 -03:00
Icaro Motta a6fe626d78 Fix reaction images and implement Selectors > Reactions component (#16114)
Fixes reaction images and implements the component Selectors > Reactions that,
for some reason, wasn't implemented as a separate quo2 component as per
Figma https://www.figma.com/file/qLLuMLfpGxK9OfpIavwsmK/Iconset?type=design&node-id=942-218&t=cqTr12Q3zVHaLoap-0

Fixes https://github.com/status-im/status-mobile/issues/16045

Note: Reaction images in the Design System are not icons, so that's why you are
seeing a bunch of icons removed from icons2. The directory
resources/images/reactions already existed, and so I used images from that
directory instead.
2023-06-01 11:13:38 -03:00
Alexander 8f92fe344a Disable translations - only use English for the moment until designs are stable and translations are correct (#16103) 2023-06-01 14:56:25 +01:00
frank 19a76c22d1 fix #16043 (#16126)
* fix #16043

* update status-go-version.json
2023-06-01 21:17:08 +08:00
Ulises Manuel Cárdenas c62204121d [#15759] - Add onboarding recovery phrase screen 2023-06-01 05:23:07 -06:00
flexsurfer a4bc18ee3f improve photo-selector and adjust according to the latest designs (#16053) 2023-06-01 10:35:57 +02:00
Siddarth Kumar 68e53e05bd Adjust padding for QR Images (#15975) 2023-06-01 13:59:12 +05:30
Mohamed Javid d142d58677 Local Pairing Updates (#16065)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-06-01 13:40:22 +05:30
Ibrahem Khalil 56dbb77ee5 [15660] Show who sent message reaction (#15677) 2023-06-01 09:21:33 +02:00
Icaro Motta 0dd3cb51fd Improve option to mark all notifications read (#16044)
- [x] Use correct icon to mark notifications as read
- [x] Add support for the disabled state in action drawer actions
- [x] Update quo2 preview `drawers` > `action-drawers`
- [x] Rewrite the action drawer component spec to use our test helpers

Fixes https://github.com/status-im/status-mobile/issues/14983
2023-05-31 21:25:19 -03:00
Omar Basem 9960a5c958 Fix: jumpy composer (#16051)
* fix: jumpy composer
2023-05-31 18:12:48 +04:00
flexsurfer fb4d484d7d bump reagent 1.2.0 (#16070) 2023-05-31 13:35:31 +02:00
Alexander 98067f8c8e Profile pic on communities and contacts screen (#16042) 2023-05-31 11:35:35 +01:00
Icaro Motta 9dad4716d6 Upgrade re-frame (#15997)
This commit upgrades re-frame to v1.3.0 (latest stable release), released ~9
months ago, in 2022-08-27. This is a solid upgrade, with no breaking changes as
far as I tested status-mobile. It's a great testament of re-frame's stability
and commitment to backwards compatibility, as are many Clojure libs.

Fixes https://github.com/status-im/status-mobile/issues/15963

The big, and truly relevant addition is the introduction of the :fx built-in
effect that was added ~3 years ago in Aug/2020 in v1.1.0.

Relevant changelog:

- Global interceptors are now supported (added in v1.0.0).
- reg-event-fx will just warn (not generate an error) if the effect map returned
  contains an unknown effect key.
- re-frame will now warn us when we are calling subscribe outside of a reactive
  context.
- "re-frame now guarantees that a :db effect, if present, will be actioned
  before any other sibling effects. re-frame continues to provide NO guarantees
  about the order in which other effects will be actioned."
  (https://day8.github.io/re-frame/releases/2020/#110-2020-08-24)
- There's syntactic sugar for trivial reg-sub declarations (added in v1.3.0).
  See the documentation for reg-sub for more details
  https://day8.github.io/re-frame/api-re-frame.core/#reg-sub
- "The built-in effect :dispatch-later can now take a single map value.
  Supplying a sequence of maps is now deprecated in favor of using multiple
  :dispatch-later effects within the new :fx effect."
  https://day8.github.io/re-frame/releases/2020/#111-2020-08-26
2023-05-31 06:08:34 -03:00
Omar Basem 2b701f9af0 refactor: zoomable component (#16022)
refactor: zoomable comp
2023-05-31 10:01:35 +04:00
jakub e8b956d4f4 ci: fix jsbundle target name for nix-cache build
Forgot to update this in:
https://github.com/status-im/status-mobile/pull/15924

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-05-30 18:28:53 +02:00
jakub f30d5b59ca ci: drop references to unused Coveralls
Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-05-30 18:28:52 +02:00
Mohamed Javid 863dac6e6a [Fix] QR scanner scanning QR when user moved to next screen (#16012)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-05-30 21:28:57 +05:30
Omar Basem 9a4f8f97b9 fix send button z-index (#16024)
* fix: send button z-index
2023-05-30 16:46:22 +04:00
Roman Volosovskyi d395ca6cc6 Allign to latest accounts changes 2023-05-30 13:57:09 +02:00
Ajay Sivan 15211865fb fix: floating-shell-button (#16030) 2023-05-29 09:40:21 -07:00
Parvesh Monu 65eb0af191 fix emoji pin in community (#16041) 2023-05-29 17:24:06 +05:30
Parvesh Monu bbdac4e8c6 disable chat swipe back navigation in ios (#16035) 2023-05-29 15:41:10 +05:30
Mohamed Javid abcfaef1a1 [Fix] Error on opening "How to scan" bottom sheet (#16033)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-05-27 12:56:37 +05:30
Mohamed Javid 2d1b37ab7b [Fix] Nav bar in Syncing screen (#16014)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-05-26 21:58:18 +05:30
Roman Volosovskyi a18cf2f786 Old wallet 2023-05-26 09:14:45 +02:00
Mohamed Javid e14ed7a637 [Fix] "View Profile" button behaviour on keyboard open in "Add a contact" modal (#15978)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-05-26 00:32:45 +05:30
170 changed files with 2759 additions and 1878 deletions
-3
View File
@@ -40,9 +40,6 @@ pipeline {
BUILD_ENV = 'prod'
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
FASTLANE_DISABLE_COLORS = 1
/* coverage report identification */
COVERALLS_SERVICE_NAME = "jenkins"
COVERALLS_SERVICE_JOB_ID = "${JOB_NAME}#${BUILD_NUMBER}"
}
stages {
@@ -61,10 +61,9 @@ pipeline {
}
stage('Build android jsbundle') {
steps { script {
/* build/fetch things required to produce a js-bundle for android
* (e.g. maven and node repos) */
/* Build/fetch deps required for jsbundle build. */
nix.build(
attr: 'targets.mobile.android.jsbundle',
attr: 'targets.mobile.jsbundle',
sandbox: false,
pure: false,
link: false
@@ -73,7 +72,7 @@ pipeline {
}
stage('Build android deps') {
steps { script {
/* build/fetch things required to build jsbundle and android */
/* Build/fetch deps required to build android release. */
nix.build(
attr: 'targets.mobile.android.release.buildInputs',
sandbox: false,
@@ -84,7 +83,7 @@ pipeline {
}
stage('Build nix shell deps') {
steps { script {
/* build/fetch things required to instantiate shell.nix for TARGET=all */
/* Build/fetch deps required to start default Nix shell. */
nix.build(
attr: 'shells.default.buildInputs',
sandbox: false,
@@ -67,8 +67,8 @@ public class PushNotificationHelper {
private static final long DEFAULT_VIBRATION = 300L;
private static final String CHANNEL_ID = "status-im-notifications";
public static final String ACTION_DELETE_NOTIFICATION = "im.status.ethereum.module.DELETE_NOTIFICATION";
public static final String ACTION_TAP_NOTIFICATION = "im.status.ethereum.module.TAP_NOTIFICATION";
public static final String ACTION_TAP_STOP = "im.status.ethereum.module.TAP_STOP";
final int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE : PendingIntent.FLAG_CANCEL_CURRENT;
private NotificationManager notificationManager;
@@ -119,13 +119,8 @@ public class PushNotificationHelper {
private final BroadcastReceiver notificationActionReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == ACTION_TAP_NOTIFICATION ||
intent.getAction() == ACTION_DELETE_NOTIFICATION) {
String deepLink = intent.getExtras().getString("im.status.ethereum.deepLink");
if (intent.getAction() == ACTION_DELETE_NOTIFICATION) {
String groupId = intent.getExtras().getString("im.status.ethereum.groupId");
if (intent.getAction() == ACTION_TAP_NOTIFICATION) {
context.startActivity(getOpenAppIntent(deepLink));
}
if (groupId != null) {
cleanGroup(groupId);
}
@@ -141,7 +136,6 @@ public class PushNotificationHelper {
private void registerBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DELETE_NOTIFICATION);
filter.addAction(ACTION_TAP_NOTIFICATION);
filter.addAction(ACTION_TAP_STOP);
context.registerReceiver(notificationActionReceiver, filter);
Log.e(LOG_TAG, "Broadcast Receiver registered");
@@ -701,37 +695,31 @@ public class PushNotificationHelper {
private StatusMessage createMessage(Bundle data) {
Person author = getPerson(data.getBundle("notificationAuthor"));
return new StatusMessage(data.getString("id"), author, data.getLong("timestamp"), data.getString("message"));
long timeStampLongValue = (long) data.getDouble("timestamp");
return new StatusMessage(data.getString("id"), author, timeStampLongValue, data.getString("message"));
}
private PendingIntent createGroupOnDismissedIntent(Context context, int notificationId, String groupId, String deepLink) {
Intent intent = new Intent(ACTION_DELETE_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
intent.putExtra("im.status.ethereum.groupId", groupId);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createGroupOnTapIntent(Context context, int notificationId, String groupId, String deepLink) {
Intent intent = new Intent(ACTION_TAP_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
intent.putExtra("im.status.ethereum.groupId", groupId);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
Intent intent = getOpenAppIntent(deepLink);
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createOnTapIntent(Context context, int notificationId, String deepLink) {
Intent intent = new Intent(ACTION_TAP_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
Intent intent = getOpenAppIntent(deepLink);
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createOnDismissedIntent(Context context, int notificationId, String deepLink) {
Intent intent = new Intent(ACTION_DELETE_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag);
}
public void removeStatusMessage(Bundle bundle) {
+15 -54
View File
@@ -103,45 +103,6 @@
}
},
{
"path": "cljsjs/react-dom-server/17.0.1-0/react-dom-server-17.0.1-0",
"host": "https://repo.clojars.org",
"pom": {
"sha1": "ff154f318e1f63061b5bd42d9a38fc8547360cb4",
"sha256": "166ynlrph7rx3nql0c85c37vcbcsnwbjamk71hw74rz451pgnncr"
},
"jar": {
"sha1": "d5c53eca9f3884402c76268b82e3828223dcbf90",
"sha256": "1530hwqpxzxfjm6dy77whqwjzzx79jpnd9xvnkxy1lnk7l7lj494"
}
},
{
"path": "cljsjs/react-dom/17.0.1-0/react-dom-17.0.1-0",
"host": "https://repo.clojars.org",
"pom": {
"sha1": "077d1a0973c23cbbff52dea7365dca4cf9de5ad5",
"sha256": "1ccm3l19cgy30hr03n8jgkgzmswdbg520zmg97xk8b16ncn964jn"
},
"jar": {
"sha1": "a98b94cbc84d264ba9892c971cfaf5920c2152f1",
"sha256": "0ym20h0h7mw1mxzm1r7smbj65x8nsqj3cszg82mw3aw4a8j32c29"
}
},
{
"path": "cljsjs/react/17.0.1-0/react-17.0.1-0",
"host": "https://repo.clojars.org",
"pom": {
"sha1": "d5d3681281585d981375fe7bb29362bfcd0d4449",
"sha256": "0rskh6mfq5h0l0wybs68w9v585a6zlnnfgrvsf5k3h51fk2p28da"
},
"jar": {
"sha1": "726da8a9305a865df90d81e9a8d58f87ff0ee8bd",
"sha256": "0bfmvw8gk98vdf9azll6041r1jaz1pmb0dyb35cfc8dr3mmr4ag7"
}
},
{
"path": "clout/clout/2.1.2/clout-2.1.2",
"host": "https://repo.clojars.org",
@@ -1014,15 +975,15 @@
},
{
"path": "org/clojure/tools.logging/0.4.1/tools.logging-0.4.1",
"path": "org/clojure/tools.logging/1.1.0/tools.logging-1.1.0",
"host": "https://repo1.maven.org/maven2",
"pom": {
"sha1": "483bbfc82aee3c005bb1ad36dec77ba5d6c5f95c",
"sha256": "1qhfigr9am90fx527ax6f7z7xahgsd5hzb4pmi40n79nx3jsc9hf"
"sha1": "44b6bd9ac74cb5e2254e1f0b258d53c1829b865d",
"sha256": "093jy29w5gm9rp9va6qlhb6096jpf5higyk7sgmbwb5nf53qi3qb"
},
"jar": {
"sha1": "991bebc6e3633b85091ae929d62c116a2584aee7",
"sha256": "001sx1ddgx0ys0z1qphzpxjf2w35rikrfjc0h5bvvqbw8ra0vvja"
"sha1": "84cb5d00caa9df2ee504d46f6107f4708271f619",
"sha256": "0x2zzivn38z179lxkw9wbi9n9qwsf466lrd9y27khdz7wbxhscb5"
}
},
@@ -1352,15 +1313,15 @@
},
{
"path": "re-frame/re-frame/0.12.0/re-frame-0.12.0",
"path": "re-frame/re-frame/1.3.0/re-frame-1.3.0",
"host": "https://repo.clojars.org",
"pom": {
"sha1": "41fd34c15c1cf68eec81435e09d0a79fd8a88276",
"sha256": "08c3sxi3sdkay3550vb3gbv5czzdh2kyin4mb8cpd2wd5g2c88sq"
"sha1": "b1f70463fba018c5464d3fc0843232fe955c1372",
"sha256": "0yqq1kg1si0akr7kx7w1l4vvkdai20na6h6627ibqkgwzivkc5n5"
},
"jar": {
"sha1": "3ff92169fe7588ad62dad2d6ea3bf0e5d3e2d224",
"sha256": "1m5sjskgjx028s1zpa631bp52y9hjn8l1nr8hrwiwdh09i2kpnk2"
"sha1": "b7135a76432b8141027ba1f4eb6bb15a36acfb7c",
"sha256": "16wi01z0j4wn04kldwzxvj0pd9dianjyb000nv5611ikhxk1qrps"
}
},
@@ -1391,15 +1352,15 @@
},
{
"path": "reagent/reagent/1.0.0/reagent-1.0.0",
"path": "reagent/reagent/1.2.0/reagent-1.2.0",
"host": "https://repo.clojars.org",
"pom": {
"sha1": "93ad5ccb0101108fb0843a3f2c50da28f8fd8336",
"sha256": "1l4xzgc4wbd8b29mhj5j336cf8w1zccaia0w413zf3bnj6jf5m38"
"sha1": "d2279922777793edfc0ae9e01d68a832eb5ce52d",
"sha256": "1h1gk4cykidm1jx75dq426lrgf8r7900fcir5jz59zp1ka2a0ywb"
},
"jar": {
"sha1": "a1dd4d40425bb2e1afad0fe72780b43ff394ccfa",
"sha256": "1g607s1ymns85923bvhwrsj0y5czyqqq1jmxx0a58fnsm1b318fa"
"sha1": "1b9a181b5c7ed3557768d2ea0c66f5616aef5e97",
"sha256": "0scvkzfqjs613z10rngh7427v3pxdqablf0fcl65pbpkzz16wgav"
}
},
+3 -6
View File
@@ -6,9 +6,6 @@ camel-snake-kebab/camel-snake-kebab/0.4.3/camel-snake-kebab-0.4.3.jar
cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3.jar
cider/piggieback/0.4.1/piggieback-0.4.1.jar
cljs-bean/cljs-bean/1.3.0/cljs-bean-1.3.0.jar
cljsjs/react-dom-server/17.0.1-0/react-dom-server-17.0.1-0.jar
cljsjs/react-dom/17.0.1-0/react-dom-17.0.1-0.jar
cljsjs/react/17.0.1-0/react-17.0.1-0.jar
clout/clout/2.1.2/clout-2.1.2.jar
com/andrewmcveigh/cljs-time/0.5.2/cljs-time-0.5.2.jar
com/bhauman/cljs-test-display/0.1.1/cljs-test-display-0.1.1.jar
@@ -76,7 +73,7 @@ org/clojure/test.check/1.1.0/test.check-1.1.0.jar
org/clojure/tools.analyzer.jvm/1.1.0/tools.analyzer.jvm-1.1.0.jar
org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0.jar
org/clojure/tools.cli/1.0.194/tools.cli-1.0.194.jar
org/clojure/tools.logging/0.4.1/tools.logging-0.4.1.jar
org/clojure/tools.logging/1.1.0/tools.logging-1.1.0.jar
org/clojure/tools.macro/0.1.5/tools.macro-0.1.5.jar
org/clojure/tools.reader/1.3.3/tools.reader-1.3.3.jar
org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar
@@ -102,10 +99,10 @@ org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final.jar
prismatic/schema/1.1.7/schema-1.1.7.jar
quoin/quoin/0.1.2/quoin-0.1.2.jar
re-com/re-com/2.8.0/re-com-2.8.0.jar
re-frame/re-frame/0.12.0/re-frame-0.12.0.jar
re-frame/re-frame/1.3.0/re-frame-1.3.0.jar
re-frisk-remote/re-frisk-remote/1.6.0/re-frisk-remote-1.6.0.jar
re-frisk/sente/1.15.0/sente-1.15.0.jar
reagent/reagent/1.0.0/reagent-1.0.0.jar
reagent/reagent/1.2.0/reagent-1.2.0.jar
refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
ring-cors/ring-cors/0.1.8/ring-cors-0.1.8.jar
ring/ring-codec/1.1.2/ring-codec-1.1.2.jar
+2 -14
View File
@@ -32,18 +32,6 @@ in {
# For parsing gradle.properties into an attrset
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
# Clojure formatting tool
zprint = super.zprint.override rec {
buildGraalvmNativeImage = args: super.buildGraalvmNativeImage ( args // rec {
inherit (args) pname;
version = "1.2.5";
src = self.fetchurl {
url = "https://github.com/kkinnear/${pname}/releases/download/${version}/${pname}-filter-${version}";
sha256 = "sha256-PWdR5jqyzvTk9HoxqDldwtZNik34dmebBtZZ5vtva4A=";
};
});
};
# Fix for missing libarclite_macosx.a in Xcode 14.3.
# https://github.com/ios-control/ios-deploy/issues/580
ios-deploy = super.darwin.ios-deploy.overrideAttrs (old: rec {
@@ -60,8 +48,8 @@ in {
gradle = super.gradle_6;
nodejs = super.nodejs-18_x;
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
openjdk = super.openjdk8_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
openjdk = super.openjdk11_headless;
xcodeWrapper = super.xcodeenv.composeXcodeWrapper {
version = "14.0";
allowHigher = true;
};
+3 -4
View File
@@ -11,11 +11,10 @@ let
# We follow the master branch of official nixpkgs.
nixpkgsSrc = fetchFromGitHub {
name = "nixpkgs-source";
# FIXME: Fork used to get Cocoapods 1.12.0 and apksigner macOS build.
owner = "status-im";
owner = "NixOS";
repo = "nixpkgs";
rev = "d0c06fa3d3982a91aa01bd63ed84020cbde3d3ab";
sha256 = "sha256-8blvuUHnuf0hFr/PpBxVohJp5CaGXIXhgJlFN/cv7us=";
rev = "e7603eba51f2c7820c0a182c6bbb351181caa8e7";
sha256 = "sha256-XJZ/o17eOd2sEsGif+/MQBnfa2DKmndWgJyc7CWajFc=";
# To get the compressed Nix sha256, use:
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
};
+1 -1
View File
@@ -9,7 +9,7 @@
# by setting android_sdk.accept_license = true.
androidenv.composeAndroidPackages {
toolsVersion = "26.1.1";
platformToolsVersion = "33.0.2";
platformToolsVersion = "33.0.3";
buildToolsVersions = [ "30.0.0" ];
platformVersions = [ "31" ];
cmakeVersions = [ "3.18.1" ];
+1
View File
@@ -2,6 +2,7 @@
mkShell {
name = "android-sdk-shell";
buildInputs = [ openjdk ];
shellHook = ''
export JAVA_HOME="${openjdk}"
@@ -1,44 +0,0 @@
{ stdenv }:
{ version ? "11.1"
, allowHigher ? false
, xcodeBaseDir ? "/Applications/Xcode.app" }:
assert stdenv.isDarwin;
stdenv.mkDerivation {
name = "xcode-wrapper-${version}${if allowHigher then "-plus" else ""}";
# Fix 'xcodebuild: Operation not permitted' when 'sandbox=relaxed' is used.
# https://github.com/NixOS/nixpkgs/pull/228696
__noChroot = stdenv.isDarwin;
buildCommand = ''
mkdir -p $out/bin
cd $out/bin
ln -s /usr/bin/xcode-select
ln -s /usr/bin/security
ln -s /usr/bin/codesign
ln -s /usr/bin/xcrun
ln -s /usr/bin/plutil
ln -s /usr/bin/clang
ln -s /usr/bin/lipo
ln -s /usr/bin/file
ln -s /usr/bin/rev
ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcodebuild"
ln -s "${xcodeBaseDir}/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator"
cd ..
ln -s "${xcodeBaseDir}/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
# Check if we have the xcodebuild version that we want
currVer=$($out/bin/xcodebuild -version)
${if allowHigher then ''
if [ -z "$(printf '%s\n' "${version}" "$currVer" | sort -V | head -n1)""" != "${version}" ]
'' else ''
if [ -z "$(echo $currVer | grep -x 'Xcode ${version}')" ]
''}
then
echo "We require xcodebuild version${if allowHigher then " or higher" else ""}: ${version}"
exit 1
fi
'';
}
+1 -1
View File
@@ -20,7 +20,7 @@ in mkShell {
# lint specific utilities
clj-kondo zprint
# other nice to have stuff
yarn nodejs python27
yarn nodejs python310
] # and some special cases
++ lib.optionals stdenv.isDarwin [ cocoapods clang tcl ]
++ lib.optionals (!stdenv.isDarwin) [ gcc8 ]
+1 -1
View File
@@ -57,7 +57,7 @@ let
# for 'scripts/generate-keystore.sh'
keytool = mkShell {
buildInputs = with pkgs; [ openjdk8 apksigner ];
buildInputs = with pkgs; [ openjdk apksigner ];
};
# for targets needing 'adb', 'apkanalyzer' and other SDK/NDK tools
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1011 B

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

+2 -2
View File
@@ -1,8 +1,8 @@
;; shadow-cljs configuration
{:source-paths ["src" "test/cljs"]
:dependencies [[reagent "1.0.0"]
[re-frame "0.12.0"]
:dependencies [[reagent "1.2.0"]
[re-frame "1.3.0"]
[binaryage/oops "0.7.0"]
[com.andrewmcveigh/cljs-time "0.5.2"]
[status-im/timbre "4.10.0-2-status"]
+9 -8
View File
@@ -220,10 +220,10 @@
only icon
[button {:icon true} :i/close-circle]"
[_ _]
(let [pressed (reagent/atom false)]
(let [pressed-in (reagent/atom false)]
(fn
[{:keys [on-press disabled type size before after above
width customization-color override-theme override-background-color
[{:keys [on-press disabled type size before after above icon-secondary-no-color
width customization-color override-theme override-background-color pressed
on-long-press accessibility-label icon icon-no-color style inner-style test-ID]
:or {type :primary
size 40
@@ -234,17 +234,17 @@
[(or
override-theme
(theme/get-theme)) type])
state (cond disabled :disabled
@pressed :pressed
:else :default)
state (cond disabled :disabled
(or @pressed-in pressed) :pressed
:else :default)
icon-size (when (= 24 size) 12)
icon-secondary-color (or icon-secondary-color icon-color)]
[rn/touchable-without-feedback
(merge {:test-ID test-ID
:disabled disabled
:accessibility-label accessibility-label
:on-press-in #(reset! pressed true)
:on-press-out #(reset! pressed nil)}
:on-press-in #(reset! pressed-in true)
:on-press-out #(reset! pressed-in nil)}
(when on-press
{:on-press on-press})
(when on-long-press
@@ -306,5 +306,6 @@
[quo2.icons/icon after
{:container-style {:margin-left 4
:margin-right (if (= size 40) 12 8)}
:no-color icon-secondary-no-color
:color icon-secondary-color
:size icon-size}]])]]]))))
@@ -68,7 +68,8 @@
:on-press-out #(reset! pressed? false)
:on-press on-press
:active-opacity 1
:style {:padding 5}
:hit-slop {:top 5 :bottom 5 :left 5 :right 5}
:pointer-events :auto
:accessibility-label type}
[rn/view
{:style (merge
@@ -42,7 +42,8 @@
(case type
:words
[rn/flat-list
{:data words
{:keyboard-should-persist-taps :always
:data words
:content-container-style style/word-list
:render-fn word-component
:render-data {:blur? blur?
@@ -1,53 +1,62 @@
(ns quo2.components.drawers.action-drawers.component-spec
(:require ["@testing-library/react-native" :as rtl]
[quo2.components.drawers.action-drawers.view :as action-drawer]
[reagent.core :as reagent]))
(:require [quo2.components.drawers.action-drawers.view :as action-drawer]
[test-helpers.component :as h]))
(defn render-action-drawer
([options]
(rtl/render (reagent/as-element [action-drawer/action-drawer options]))))
(h/describe "action drawer"
(h/test "default render"
(h/render [action-drawer/action-drawer
[[{:icon :i/friend
:label "a sample label"}]]])
(h/is-truthy (h/get-by-text "a sample label")))
(js/global.test "action-drawer renders with elements label displaying"
(fn []
(render-action-drawer [[{:icon :i/friend
:label "a sample label"}]])
(-> (js/expect (rtl/screen.getByText "a sample label"))
(.toBeTruthy))))
(h/test "renders with elements sub-label displaying"
(h/render [action-drawer/action-drawer
[[{:icon :i/friend
:label "a sample label"
:sub-label "a sample sub label"}]]])
(h/is-truthy (h/get-by-text "a sample sub label")))
(js/global.test "action-drawer renders with elements sub-label displaying"
(fn []
(render-action-drawer [[{:icon :i/friend
:label "a sample label"
:sub-label "a sample sub label"}]])
(-> (js/expect (rtl/screen.getByText "a sample sub label"))
(.toBeTruthy))))
(h/test "on click action works on element"
(let [on-press (js/jest.fn)]
(h/render [action-drawer/action-drawer
[[{:icon :i/friend
:label "a sample label"
:on-press on-press}]]])
(h/fire-event :press (h/get-by-text "a sample label"))
(h/was-called on-press)))
(js/global.test "action-drawer on click action works on element"
(let [event (js/jest.fn)]
(fn []
(render-action-drawer [[{:icon :i/friend
:label "a sample label"
:on-press event}]])
(rtl/fireEvent.press (rtl/screen.getByText "a sample label"))
(-> (js/expect event)
(.toHaveBeenCalled)))))
(h/test "disabled state"
(let [on-press-muted (js/jest.fn)
on-press-friend (js/jest.fn)
label-mute "Mute"
label-friend "View member details"]
(h/render [action-drawer/action-drawer
[[{:icon :i/muted
:label label-mute
:on-press on-press-muted}
{:icon :i/friend
:label label-friend
:disabled? true
:on-press on-press-friend}]]])
(h/fire-event :press (h/get-by-text label-mute))
(h/was-called on-press-muted)
(js/global.test "action-drawer renders two icons when set"
(fn []
(render-action-drawer [[{:icon :i/friend
:label "a sample label"
:right-icon :i/friend
:accessibility-label :first-element}]])
(-> (js/expect (rtl/screen.getByLabelText "right-icon-for-action"))
(.toBeTruthy))
(-> (js/expect (rtl/screen.queryByLabelText "left-icon-for-action"))
(.toBeTruthy))))
(h/fire-event :press (h/get-by-text label-friend))
(h/was-not-called on-press-friend)))
(js/global.test "action-drawer renders a divider when the add-divider? prop is true"
(fn []
(render-action-drawer [[{:icon :i/friend
:label "a sample label"
:add-divider? true
:accessibility-label :first-element}]])
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
(.toBeTruthy))))
(h/test "renders two icons when set"
(h/render [action-drawer/action-drawer
[[{:icon :i/friend
:label "a sample label"
:right-icon :i/friend
:accessibility-label :first-element}]]])
(h/is-truthy (h/get-by-label-text "right-icon-for-action"))
(h/is-truthy (h/query-by-label-text "left-icon-for-action")))
(h/test "renders a divider when the add-divider? prop is true"
(h/render [action-drawer/action-drawer
[[{:icon :i/friend
:label "a sample label"
:add-divider? true
:accessibility-label :first-element}]]])
(h/is-truthy (h/get-all-by-label-text "divider"))))
@@ -11,9 +11,10 @@
:flex-direction :row})
(defn container
[sub-label]
[sub-label disabled?]
{:border-radius 12
:height (if sub-label 58 50)
:opacity (when disabled? 0.3)
:margin-horizontal 8})
(defn row-container
@@ -18,12 +18,19 @@
:accessible true
:accessibility-label :divider}])
(defn action
(defn- maybe-pressable
[disabled? props child]
(if disabled?
[rn/view (dissoc props :on-press) child]
[rn/touchable-highlight props child]))
(defn- action
[{:keys [icon
label
sub-label
right-icon
danger?
disabled?
on-press
add-divider?
override-theme
@@ -33,9 +40,9 @@
[:<> {:key label}
(when add-divider?
[divider])
[rn/touchable-highlight
[maybe-pressable disabled?
{:accessibility-label accessibility-label
:style (style/container sub-label)
:style (style/container sub-label disabled?)
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90 override-theme)
:on-press on-press}
[rn/view
@@ -1,10 +1,11 @@
(ns quo2.components.drawers.drawer-buttons.style
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(:require [quo2.foundations.colors :as colors]))
(def outer-container
{:height 216
:border-radius 20})
{:height 216
:border-top-left-radius 20
:border-top-right-radius 20
:overflow :hidden})
(def top-card
{:flex 1
@@ -12,9 +13,7 @@
:padding-horizontal 20
:border-top-left-radius 20
:border-top-right-radius 20
:background-color (if platform/ios?
colors/neutral-80-opa-80-blur
colors/neutral-80)})
:background-color colors/neutral-80-opa-80-blur})
(def bottom-card
{:position :absolute
@@ -33,11 +32,11 @@
:justify-content :space-between})
(def bottom-icon
{:border-radius 40
{:border-radius 32
:border-width 1
:margin-left 24
:height 28
:width 28
:height 32
:width 32
:justify-content :center
:align-items :center
:border-color colors/white-opa-5})
@@ -52,4 +51,4 @@
(defn heading-text
[gap]
{:color colors/white
:margin-bottom gap})
:margin-bottom gap})
@@ -71,14 +71,28 @@
child-2 string, keyword or hiccup
"
[{:keys [container-style top-card bottom-card]} child-1 child-2]
[blur/ios-view
[rn/view
{:style (merge container-style style/outer-container)}
[card
(merge {:gap 4
:top? true
:style style/top-card}
top-card) child-1]
[card
(merge {:style style/bottom-card
:gap 20}
bottom-card) child-2]])
[blur/view
{:blur-type :dark
:blur-amount 10
:style {:flex 1
:border-top-left-radius 20
:border-top-right-radius 20}}]
[rn/view
{:style {:flex 1
:background-color :transparent
:position :absolute
:top 0
:left 0
:right 0
:bottom 0}}
[card
(merge {:gap 4
:top? true
:style style/top-card}
top-card) child-1]
[card
(merge {:style style/bottom-card
:gap 20}
bottom-card) child-2]]])
+11 -162
View File
@@ -1,165 +1,14 @@
(ns quo2.components.dropdowns.dropdown
(:require [quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]))
(defn apply-anim
[dd-height val]
(reanimated/animate-shared-value-with-delay dd-height
val
300
:easing1
0))
(def sizes
{:big {:icon-size 20
:font {:font-size :paragraph-1}
:height 40
:padding {:padding-with-icon {:padding-vertical 9
:padding-horizontal 12}
:padding-with-no-icon {:padding-vertical 9
:padding-left 12
:padding-right 8}}}
:medium {:icon-size 20
:font {:font-size :paragraph-1}
:height 32
:padding {:padding-with-icon {:padding-vertical 5
:padding-horizontal 8}
:padding-with-no-icon {:padding-vertical 5
:padding-left 12
:padding-right 8}}}
:small {:icon-size 15
:font {:font-size :paragraph-2}
:height 24
:padding {:padding-with-icon {:padding-vertical 3
:padding-horizontal 6}
:padding-with-no-icon {:padding-vertical 3
:padding-horizontal 6}}}})
(defn color-by-10
[color]
(colors/alpha color 0.6))
(defn dropdown-comp
[{:keys [icon dd-height size disabled? dd-color use-border? border-color]}]
(let [dark? (colors/dark?)
{:keys [width height width-with-icon padding font icon-size]} (size sizes)
{:keys [padding-with-icon padding-with-no-icon]} padding
font-size (:font-size font)
spacing (case size
:big 4
:medium 2
:small 2)
open? (reagent/atom false)]
(fn []
[rn/touchable-opacity
(cond->
{:on-press (fn []
(if (swap! open? not)
(apply-anim dd-height 120)
(apply-anim dd-height 0)))
:style (cond->
(merge
(if icon
padding-with-icon
padding-with-no-icon)
{:width (if icon
width-with-icon
width)
:height height
:border-radius (case size
:big 12
:medium 10
:small 8)
:flex-direction :row
:align-items :center
:background-color (if @open?
dd-color
(color-by-10 dd-color))})
use-border? (assoc :border-width 1
:border-color (if @open?
border-color
(color-by-10 border-color))))}
disabled? (assoc-in [:style :opacity] 0.3)
disabled? (assoc :disabled true))
(when icon
[icons/icon icon
{:no-color true
:size 20
:container-style {:margin-right spacing
:margin-top 1
:width icon-size
:height icon-size}}])
[text/text
{:size font-size
:weight :medium
:font :font-medium
:color :main} "Dropdown"]
[icons/icon
(if @open?
(if dark?
:main-icons/pullup-dark
:main-icons/pullup)
(if dark?
:main-icons/dropdown-dark
:main-icons/dropdown))
{:size 20
:no-color true
:container-style {:width (+ icon-size 3)
:border-radius 20
:margin-left (if (= :small size)
2
4)
:margin-top 1
:height (+ icon-size 4)}}]])))
(defn items-comp
[{:keys [items on-select]}]
(let [items-count (count items)]
[rn/scroll-view
{:horizontal false
:nestedScrollEnabled true}
(doall
(map-indexed (fn [index item]
[rn/touchable-opacity
{:key (str item index)
:style {:padding 4
:border-bottom-width (if (= index (- items-count 1))
0
1)
:border-color (colors/theme-colors
colors/neutral-100
colors/white)
:text-align :center}
:on-press #(on-select item)}
[text/text {:style {:text-align :center}} item]])
items))]))
(defn- f-dropdown
[{:keys [items icon text default-item on-select size disabled? border-color use-border? dd-color]}]
(let [dd-height (reanimated/use-shared-value 0)]
[rn/view {:style {:flex-grow 1}}
[dropdown-comp
{:items items
:icon icon
:disabled? disabled?
:size size
:dd-color dd-color
:text text
:border-color (colors/custom-color-by-theme border-color 50 60)
:use-border? use-border?
:default-item default-item
:dd-height dd-height}]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:height dd-height}
{})}
[items-comp
{:items items
:on-select on-select}]]]))
(:require [quo2.components.buttons.button :as button]))
(defn dropdown
[params]
[:f> f-dropdown params])
[_ _]
(fn [{:keys [on-change selected] :as opts} children]
[button/button
(merge
opts
{:after (if selected :i/pullup :i/dropdown)
:icon-secondary-no-color true
:pressed selected
:on-press #(when on-change (on-change selected))})
children]))
@@ -0,0 +1,30 @@
(ns quo2.components.empty-state.empty-state.styles
(:require [quo2.foundations.colors :as colors]))
(def container
{:padding 12
:align-items :center})
(def image
{:width 80
:height 80})
(def text-container
{:margin-top 12
:align-items :center})
(defn title
[blur?]
(cond-> {:margin-bottom 2}
blur? (assoc :color colors/white)))
(defn description
[blur?]
(when blur?
{:color colors/white}))
(def button-container {:margin-top 20})
(defn upper-button-color
[customization-color]
(colors/custom-color-by-theme customization-color 50 60))
@@ -0,0 +1,50 @@
(ns quo2.components.empty-state.empty-state.view
(:require [quo2.components.buttons.button :as button]
[quo2.components.empty-state.empty-state.styles :as styles]
[quo2.components.markdown.text :as text]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]))
(defn empty-state
[{:keys [customization-color image title description blur?]
upper-button :upper-button
lower-button :lower-button
:or {customization-color :blue}}]
[rn/view {:style styles/container}
[fast-image/fast-image
{:style styles/image
:source image}]
[rn/view {:style styles/text-container}
[text/text
{:style (styles/title blur?)
:number-of-lines 1
:weight :semi-bold
:size :paragraph-1}
title]
[text/text
{:style (styles/description blur?)
:number-of-lines 1
:text-align :center
:weight :regular
:size :paragraph-2}
description]]
(when-let [{upper-button-text :text
upper-button-on-press :on-press} upper-button]
[rn/view {:style styles/button-container}
[button/button
(cond-> {:type :primary
:size 32
:override-background-color (styles/upper-button-color customization-color)
:on-press upper-button-on-press}
blur? (assoc :override-theme :dark))
upper-button-text]
(when-let [{lower-button-text :text
lower-button-on-press :on-press} lower-button]
[button/button
(cond-> {:style {:margin-top 12}
:size 32
:type :blur-bg
:on-press lower-button-on-press}
blur? (assoc :override-theme :dark))
lower-button-text])])])
@@ -28,8 +28,9 @@
(h/describe "Error text"
(h/test "Marked when words doesn't satisfy a predicate"
(h/render [recovery-phrase/recovery-phrase-input
{:mark-errors? true
:error-pred #(>= (count %) 5)}
{:mark-errors? true
:error-pred-current-word #(>= (count %) 5)
:error-pred-written-words #(>= (count %) 5)}
"Text with some error words that don't satisfy the predicate"])
(let [children-text-nodes (-> (h/get-by-label-text :recovery-phrase-input)
(oops/oget "props" "children" "props" "children")
@@ -15,15 +15,27 @@
text])
(defn- mark-error-words
[pred text word-limit]
(let [word-limit (or word-limit ##Inf)]
(into [:<>]
(comp (map-indexed (fn [idx word]
(if (or (pred word) (>= idx word-limit))
[error-word word]
word)))
(interpose " "))
(string/split text #" "))))
[pred-last-word pred-previous-words text word-limit]
(let [last-index (dec (count (string/split text #"\s+")))
words (map #(apply str %)
(partition-by #(= " " %) text))]
(->> words
(reduce (fn [{:keys [idx] :as acc} word]
(let [error-pred (if (= last-index idx) pred-last-word pred-previous-words)
invalid-word? (and (or (error-pred word)
(>= idx word-limit))
(not (string/blank? word)))
not-blank-spaces? (not (string/blank? word))]
(cond-> acc
not-blank-spaces? (update :idx inc)
:always (update :result
conj
(if invalid-word?
[error-word word]
word)))))
{:result [:<>]
:idx 0})
:result)))
(defn recovery-phrase-input
[_ _]
@@ -31,9 +43,11 @@
set-focused #(reset! state :focused)
set-default #(reset! state :default)]
(fn [{:keys [customization-color override-theme blur? on-focus on-blur mark-errors?
error-pred word-limit]
:or {customization-color :blue
error-pred (constantly false)}
error-pred-current-word error-pred-written-words word-limit]
:or {customization-color :blue
word-limit ##Inf
error-pred-current-word (constantly false)
error-pred-written-words (constantly false)}
:as props}
text]
(let [extra-props (apply dissoc props custom-props)]
@@ -53,5 +67,5 @@
(when on-blur (on-blur)))}
extra-props)
(if mark-errors?
(mark-error-words error-pred text word-limit)
(mark-error-words error-pred-current-word error-pred-written-words text word-limit)
text)]]))))
@@ -40,8 +40,8 @@
:default-value default-value
:accessibility-label :profile-title-input
:keyboard-appearance (theme/theme-value :light :dark override-theme)
:on-focus #(swap! focused? (fn [] true))
:on-blur #(swap! focused? (fn [] false))
:on-focus #(swap! focused? (constantly true))
:on-blur #(swap! focused? (constantly false))
:input-mode :text
:on-change-text on-change
:editable (not disabled?)
@@ -14,6 +14,10 @@
:style style
:customization-color customization-color}]))
(defn- section
[children]
[rn/view {:style {:flex 1} :pointer-events :box-none} children])
(defn- f-floating-shell-button
[dynamic-buttons style opacity-anim]
(let [original-style (merge {:flex-direction :row
@@ -27,14 +31,14 @@
original-style)]
[reanimated/view {:style animated-style}
;; Left Section
[rn/view {:style {:flex 1}}
[section
[dynamic-button-view :search dynamic-buttons
{:position :absolute
:right 8}]]
;; Mid Section (jump-to)
[dynamic-button-view :jump-to dynamic-buttons nil]
;; Right Section
[rn/view {:style {:flex 1}}
[section
[rn/view
{:style {:position :absolute
:flex-direction :row
+8 -5
View File
@@ -1,6 +1,7 @@
(ns quo2.components.reactions.reaction
(:require [quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.components.reactions.resource :as resource]
[quo2.components.reactions.style :as style]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
@@ -13,7 +14,7 @@
{:on-press on-press
:accessibility-label :emoji-reaction-add
:style (style/add-reaction)}
[icons/icon :i/add
[icons/icon :i/add-reaction
{:size 20
:color (if dark?
colors/white
@@ -21,15 +22,17 @@
(defn reaction
"Add your emoji as a param here"
[{:keys [emoji clicks neutral? on-press accessibility-label]}]
[{:keys [emoji clicks neutral? on-press accessibility-label on-long-press]}]
(let [numeric-value (int clicks)]
[rn/touchable-opacity
{:on-press on-press
:on-long-press on-long-press
:accessibility-label accessibility-label
:style (style/reaction neutral?)}
[icons/icon emoji
{:no-color true
:size 16}]
[rn/image
{:style {:width 16 :height 16}
:accessibility-label :emoji
:source (resource/get-reaction emoji)}]
[text/text
{:size :paragraph-2
:weight :semi-bold
@@ -0,0 +1,30 @@
(ns quo2.components.reactions.resource
(:require [clojure.java.io :as io]
[clojure.string :as string]))
(def ^:private reactions-dir "./resources/images/reactions/")
(defn- resolve-reaction
[reaction]
(let [path (str reactions-dir (name reaction) ".png")
file (io/file path)]
(when (.exists file)
`(js/require ~(str "." path)))))
(defn- find-all-image-base-names
[]
(let [dir (io/file reactions-dir)]
(->> dir
file-seq
(filter #(string/ends-with? % "png"))
(map #(.getName %))
(map #(string/replace % #"\.png$" ""))
(map #(first (string/split % #"@")))
distinct)))
(defmacro resolve-all-reactions
[]
(reduce (fn [acc reaction]
(assoc acc reaction (resolve-reaction reaction)))
{}
(find-all-image-base-names)))
@@ -0,0 +1,12 @@
(ns quo2.components.reactions.resource
(:require-macros [quo2.components.reactions.resource :refer [resolve-all-reactions]]))
(def ^:private reactions
(resolve-all-reactions))
(defn get-reaction
[reaction]
(assert (keyword? reaction) "Reaction should be a keyword")
(assert (= "reaction" (namespace reaction))
"Reaction keyword should be namespaced with :reaction")
(get reactions (name reaction)))
@@ -0,0 +1,23 @@
(ns quo2.components.selectors.reactions.component-spec
(:require [quo2.components.selectors.reactions.view :as view]
[test-helpers.component :as h]))
(h/describe "Selectors > Reactions"
(h/test "renders component"
(h/render [view/view :reaction/sad])
(h/is-truthy (h/get-by-label-text :reaction)))
(h/describe "on-press event"
(h/test "starts with released state"
(let [on-press (h/mock-fn)]
(h/render [view/view :reaction/love {:on-press on-press}])
(h/fire-event :press (h/get-by-label-text :reaction))
(h/was-called on-press)))
(h/test "starts with pressed state"
(let [on-press (h/mock-fn)]
(h/render [view/view :reaction/love
{:on-press on-press
:start-pressed? true}])
(h/fire-event :press (h/get-by-label-text :reaction))
(h/was-called on-press)))))
@@ -0,0 +1,11 @@
(ns quo2.components.selectors.reactions.style
(:require [quo2.foundations.colors :as colors]))
(defn container
[pressed?]
{:padding 10
:border-radius 12
:border-width 1
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80)
:background-color (when pressed?
(colors/theme-colors colors/neutral-10 colors/neutral-80-opa-40))})
@@ -0,0 +1,25 @@
(ns quo2.components.selectors.reactions.view
(:require [quo2.components.reactions.resource :as reactions.resource]
[quo2.components.selectors.reactions.style :as style]
[react-native.core :as rn]
[reagent.core :as reagent]))
(defn view
[_ {:keys [start-pressed?]}]
(let [pressed? (reagent/atom start-pressed?)]
(fn [emoji
{:keys [container-style on-press
accessibility-label]
:or {accessibility-label :reaction}}]
[rn/touchable-without-feedback
{:accessibility-label accessibility-label
:on-press (fn [e]
(swap! pressed? not)
(when on-press
(on-press e)))}
[rn/view
{:style (merge (style/container @pressed?)
container-style)}
[rn/image
{:source (reactions.resource/get-reaction emoji)
:style {:width 20 :height 20}}]]])))
+7 -3
View File
@@ -6,7 +6,8 @@
[react-native.masked-view :as masked-view]
[reagent.core :as reagent]
[utils.collection :as utils.collection]
[utils.number :as utils.number]))
[utils.number :as utils.number]
[react-native.gesture :as gesture]))
(def default-tab-size 32)
(def unread-count-offset 3)
@@ -131,7 +132,8 @@
style
size
blur?
override-theme]
override-theme
in-scroll-view?]
:or {fade-end-percentage fade-end-percentage
fade-end? false
scrollable? false
@@ -142,7 +144,9 @@
[rn/view {:style {:margin-top (- (dec unread-count-offset))}}
[masked-view-wrapper
{:fade-end-percentage (get @fading :fade-end-percentage) :fade-end? fade-end?}
[rn/flat-list
[(if in-scroll-view?
gesture/flat-list
rn/flat-list)
(merge
(dissoc props
:default-active
@@ -44,7 +44,7 @@
(let [text-params {:weight :medium
:size :paragraph-2
:style (assoc text-style :justify-content :center)}
empty-photo? (empty? photo)
empty-photo? (nil? photo)
avatar-size :xxs
avatar-outer-size (get-in user-avatar-style/sizes [avatar-size :outer])]
[rn/view {:flex-direction :row}
+8
View File
@@ -30,6 +30,7 @@
quo2.components.drawers.permission-context.view
quo2.components.dropdowns.dropdown
quo2.components.header
quo2.components.empty-state.empty-state.view
quo2.components.icon
quo2.components.info.info-message
quo2.components.info.information-box
@@ -64,6 +65,7 @@
quo2.components.profile.profile-card.view
quo2.components.profile.select-profile.view
quo2.components.reactions.reaction
quo2.components.selectors.reactions.view
quo2.components.record-audio.record-audio.view
quo2.components.record-audio.soundtrack.view
quo2.components.selectors.disclaimer.view
@@ -110,6 +112,9 @@
(def skeleton quo2.components.loaders.skeleton/skeleton)
(def author quo2.components.messages.author.view/author)
;;;; SELECTORS
(def reactions quo2.components.selectors.reactions.view/view)
;;;; AVATAR
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
@@ -164,6 +169,9 @@
(def drawer-buttons quo2.components.drawers.drawer-buttons.view/view)
(def permission-context quo2.components.drawers.permission-context.view/view)
;;;; EMPTY STATE
(def empty-state quo2.components.empty-state.empty-state.view/empty-state)
;;;; INPUTS
(def input quo2.components.inputs.input.view/input)
(def profile-input quo2.components.inputs.profile-input.view/profile-input)
+3 -2
View File
@@ -14,13 +14,13 @@
[quo2.components.drawers.drawer-buttons.component-spec]
[quo2.components.drawers.permission-context.component-spec]
[quo2.components.inputs.input.component-spec]
[quo2.components.keycard.component-spec]
[quo2.components.inputs.profile-input.component-spec]
[quo2.components.inputs.recovery-phrase.component-spec]
[quo2.components.inputs.title-input.component-spec]
[quo2.components.keycard.component-spec]
[quo2.components.links.link-preview.component-spec]
[quo2.components.links.url-preview-list.component-spec]
[quo2.components.links.url-preview.component-spec]
[quo2.components.links.link-preview.component-spec]
[quo2.components.markdown.--tests--.text-component-spec]
[quo2.components.notifications.notification.component-spec]
[quo2.components.onboarding.small-option-card.component-spec]
@@ -30,6 +30,7 @@
[quo2.components.record-audio.soundtrack.--tests--.soundtrack-component-spec]
[quo2.components.selectors.disclaimer.component-spec]
[quo2.components.selectors.filter.component-spec]
[quo2.components.selectors.reactions.component-spec]
[quo2.components.selectors.selectors.component-spec]
[quo2.components.share.share-qr-code.component-spec]
[quo2.components.tags.--tests--.status-tags-component-spec]))
+16
View File
@@ -0,0 +1,16 @@
(ns react-native.cameraroll
(:require ["@react-native-community/cameraroll" :as CameraRoll]
[utils.transforms :as transforms]
[taoensso.timbre :as log]))
(defn get-photos
[opts callback]
(-> (.getPhotos CameraRoll (clj->js opts))
(.then #(callback (transforms/js->clj %)))
(.catch #(log/warn "could not get camera roll photos" %))))
(defn get-albums
[opts callback]
(-> (.getAlbums CameraRoll (clj->js opts))
(.then #(callback (transforms/js->clj %)))
(.catch #(log/warn "could not get camera roll albums" %))))
+1
View File
@@ -17,6 +17,7 @@
(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)))
(defn image-get-size [uri callback] (.getSize ^js (.-Image ^js react-native) uri callback))
(def text (reagent/adapt-react-class (.-Text ^js react-native)))
(def text-input (reagent/adapt-react-class (.-TextInput ^js react-native)))
+4 -4
View File
@@ -91,7 +91,7 @@
[flat-list
(merge props
{:data data
:render-fn (fn [item]
(if (:header? item)
(render-section-header-fn item)
(render-fn item)))})]))
:render-fn (fn [p1 p2 p3 p4]
(if (:header? p1)
[render-section-header-fn p1 p2 p3 p4]
[render-fn p1 p2 p3 p4]))})]))
+1 -219
View File
@@ -1,47 +1,17 @@
(ns status-im.chat.models.images
(:require ["@react-native-community/cameraroll" :as CameraRoll]
["react-native-blob-util" :default ReactNativeBlobUtil]
[clojure.string :as string]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.ui.components.permissions :as permissions]
[react-native.permissions :as permissions]
[status-im.ui.components.react :as react]
[status-im2.config :as config]
[status-im.utils.fs :as fs]
[utils.re-frame :as rf]
[status-im.utils.image-processing :as image-processing]
[status-im.utils.platform :as platform]
[status-im.utils.types :as types]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
(def maximum-image-size-px 2000)
(defn- resize-and-call
[uri cb]
(react/image-get-size
uri
(fn [width height]
(let [resize? (> (max width height) maximum-image-size-px)]
(image-processing/resize
uri
(if resize? maximum-image-size-px width)
(if resize? maximum-image-size-px height)
60
(fn [^js resized-image]
(let [path (.-path resized-image)
path (if (string/starts-with? path "file") path (str "file://" path))]
(cb {:resized-uri path
:width width
:height height})))
#(log/error "could not resize image" %))))))
(defn result->id
[^js result]
(if platform/ios?
(.-localIdentifier result)
(.-path result)))
(def temp-image-url (str (fs/cache-dir) "/StatusIm_Image.jpeg"))
(defn download-image-http
@@ -78,108 +48,6 @@
#(re-frame/dispatch [:chat.ui/image-captured current-chat-id (.-path %)])
{})))
(re-frame/reg-fx
::chat-open-image-picker
(fn [chat-id]
(react/show-image-picker
(fn [^js images]
;; NOTE(Ferossgp): Because we can't highlight the already selected images inside
;; gallery, we just clean previous state and set all newly picked images
(when (and platform/ios? (pos? (count images)))
(re-frame/dispatch [:chat.ui/clear-sending-images chat-id]))
(doseq [^js result (if platform/ios?
(take config/max-images-batch images)
[images])]
(resize-and-call (.-path result)
#(re-frame/dispatch [:chat.ui/image-selected chat-id (result->id result) %]))))
;; NOTE(Ferossgp): On android you cannot set max limit on images, when a user
;; selects too many images the app crashes.
{:media-type "photo"
:multiple platform/ios?})))
(re-frame/reg-fx
::image-selected
(fn [[image chat-id]]
(resize-and-call
(:uri image)
#(re-frame/dispatch [:chat.ui/image-selected chat-id image %]))))
(re-frame/reg-fx
::camera-roll-get-photos
(fn [[num end-cursor album]]
(permissions/request-permissions
{:permissions [:read-external-storage]
:on-allowed (fn []
(-> (if end-cursor
(.getPhotos
CameraRoll
#js
{:first num
:after end-cursor
:assetType "Photos"
:groupTypes (if (= album (i18n/label :t/recent)) "All" "Albums")
:groupName (when (not= album (i18n/label :t/recent)) album)
:include (clj->js ["imageSize"])})
(.getPhotos
CameraRoll
#js
{:first num
:assetType "Photos"
:groupTypes (if (= album (i18n/label :t/recent)) "All" "Albums")
:groupName (when (not= album (i18n/label :t/recent)) album)
:include (clj->js ["imageSize"])}))
(.then #(let [response (types/js->clj %)]
(re-frame/dispatch [:on-camera-roll-get-photos (:edges response)
(:page_info response) end-cursor])))
(.catch #(log/warn "could not get camera roll photos"))))})))
(re-frame/reg-fx
:chat.ui/camera-roll-get-albums
(fn []
(let [albums (atom [{:title :smart-albums :data []}
{:title (i18n/label :t/my-albums) :data []}])]
;; Get the "recent" album first
(->
(.getPhotos CameraRoll
#js
{:first 1
:groupTypes "All"})
(.then
(fn [res]
(let [recent-album {:title (i18n/label :t/recent)
:count "--"
:uri (get-in (first (:edges (types/js->clj res))) [:node :image :uri])}]
(swap! albums update-in [0 :data] conj recent-album)
;; Get albums, then loop over albums and get each one's cover (first photo)
(->
(.getAlbums CameraRoll #js {:assetType "All"})
(.then
(fn [response]
(let [response (types/js->clj response)]
(reduce
(fn [_ album]
(->
(.getPhotos
CameraRoll
#js
{:first 1
:groupTypes "Albums"
:groupName (:title album)})
(.then (fn [res]
(let [uri (get-in (first (:edges (types/js->clj res)))
[:node :image :uri])]
(swap! albums update-in [1 :data] conj (merge album {:uri uri}))
(when (= (count (get-in @albums [1 :data])) (count response))
(swap! albums update-in
[1 :data]
#(->> %
(sort-by :title)))
(re-frame/dispatch [:on-camera-roll-get-albums @albums])))))))
nil
response))))
(.catch #(log/warn "could not get camera roll albums"))))))))))
(rf/defn image-captured
{:events [:chat.ui/image-captured]}
[{:keys [db]} chat-id uri]
@@ -189,81 +57,17 @@
(not (get images uri)))
{::image-selected [uri current-chat-id]})))
(rf/defn on-end-reached
{:events [:camera-roll/on-end-reached]}
[_ end-cursor selected-album loading? has-next-page?]
(when (and (not loading?) has-next-page?)
(re-frame/dispatch [:chat.ui/camera-roll-loading-more true])
(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20 end-cursor selected-album])))
(rf/defn camera-roll-get-photos
{:events [:chat.ui/camera-roll-get-photos]}
[_ num end-cursor selected-album]
{::camera-roll-get-photos [num end-cursor selected-album]})
(rf/defn camera-roll-get-albums
{:events [:chat.ui/camera-roll-get-albums]}
[_]
{:chat.ui/camera-roll-get-albums []})
(rf/defn camera-roll-loading-more
{:events [:chat.ui/camera-roll-loading-more]}
[{:keys [db]} is-loading]
{:db (assoc db :camera-roll/loading-more is-loading)})
(rf/defn on-camera-roll-get-photos
{:events [:on-camera-roll-get-photos]}
[{:keys [db] :as cofx} photos page-info end-cursor]
(let [photos_x (when end-cursor (:camera-roll/photos db))]
{:db (-> db
(assoc :camera-roll/photos (concat photos_x (map #(get-in % [:node :image]) photos)))
(assoc :camera-roll/end-cursor (:end_cursor page-info))
(assoc :camera-roll/has-next-page (:has_next_page page-info))
(assoc :camera-roll/loading-more false))}))
(rf/defn on-camera-roll-get-albums
{:events [:on-camera-roll-get-albums]}
[{:keys [db]} albums]
{:db (-> db
(assoc :camera-roll/albums albums)
(assoc :camera-roll/loading-albums false))})
(rf/defn clear-sending-images
{:events [:chat.ui/clear-sending-images]}
[{:keys [db]}]
{:db (update-in db [:chat/inputs (:current-chat-id db) :metadata] assoc :sending-image {})})
(rf/defn cancel-sending-image
{:events [:chat.ui/cancel-sending-image]}
[{:keys [db] :as cofx} chat-id]
(clear-sending-images cofx))
(rf/defn image-selected
{:events [:chat.ui/image-selected]}
[{: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 resized-uri
:width width
:height height})})
(rf/defn image-unselected
{:events [:chat.ui/image-unselected]}
[{:keys [db]} original]
(let [current-chat-id (:current-chat-id db)]
{:db (update-in db [:chat/inputs current-chat-id :metadata :sending-image] dissoc (:uri original))}))
(rf/defn chat-open-image-picker
{:events [:chat.ui/open-image-picker]}
[{:keys [db]} chat-id]
(let [current-chat-id (or chat-id (:current-chat-id db))
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(when (< (count images) config/max-images-batch)
{::chat-open-image-picker current-chat-id})))
(rf/defn chat-show-image-picker-camera
{:events [:chat.ui/show-image-picker-camera]}
[{:keys [db]} chat-id]
@@ -271,25 +75,3 @@
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(when (< (count images) config/max-images-batch)
{::chat-open-image-picker-camera current-chat-id})))
(rf/defn camera-roll-pick
{:events [:chat.ui/camera-roll-pick]}
[{:keys [db]} image chat-id]
(let [current-chat-id (or chat-id (:current-chat-id db))
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(if (get-in db [:chats current-chat-id :timeline?])
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-image] {})
::image-selected [image current-chat-id]}
(when (and (< (count images) config/max-images-batch)
(not (some #(= (:uri image) (:uri %)) images)))
{::image-selected [image current-chat-id]}))))
(rf/defn camera-roll-select-album
{:events [:chat.ui/camera-roll-select-album]}
[{:keys [db]} album]
{:db (assoc db :camera-roll/selected-album album)})
(rf/defn save-image-to-gallery
{:events [:chat.ui/save-image-to-gallery]}
[_ base64-uri]
{::save-image-to-gallery base64-uri})
+8 -6
View File
@@ -103,7 +103,7 @@
(rf/defn messages-loaded
"Loads more messages for current chat"
{:events [::messages-loaded]}
[{db :db} chat-id session-id {:keys [cursor messages]}]
[{db :db} chat-id session-id {:keys [cursor messages]} on-loaded]
(when-not (and (get-in db [:pagination-info chat-id :messages-initialized?])
(not= session-id
(get-in db [:pagination-info chat-id :messages-initialized?])))
@@ -141,6 +141,8 @@
[:pagination-info chat-id
:cursor-clock-value])
clock-value (when cursor (cursor->clock-value cursor))]
(when on-loaded
(on-loaded (count new-messages)))
{:db (-> db
(update-in [:pagination-info chat-id :cursor-clock-value]
#(if (and (seq cursor) (or (not %) (< clock-value %)))
@@ -161,7 +163,7 @@
(rf/defn load-more-messages
{:events [:chat.ui/load-more-messages]}
[{:keys [db]} chat-id first-request]
[{:keys [db]} chat-id first-request on-loaded]
(when-let [session-id (get-in db [:pagination-info chat-id :messages-initialized?])]
(when (and
(not (get-in db [:pagination-info chat-id :all-loaded?]))
@@ -175,13 +177,13 @@
chat-id
cursor
constants/default-number-of-messages
#(re-frame/dispatch [::messages-loaded chat-id session-id %])
#(re-frame/dispatch [::messages-loaded chat-id session-id % on-loaded])
#(re-frame/dispatch [::failed-loading-messages chat-id session-id %]))))))))
(rf/defn load-more-messages-for-current-chat
{:events [:chat.ui/load-more-messages-for-current-chat]}
[{:keys [db] :as cofx}]
(load-more-messages cofx (:current-chat-id db) false))
[{:keys [db] :as cofx} on-loaded]
(load-more-messages cofx (:current-chat-id db) false on-loaded))
(rf/defn load-messages
[{:keys [db now] :as cofx} chat-id]
@@ -191,4 +193,4 @@
:utils/dispatch-later [{:ms 50 :dispatch [:chat.ui/mark-all-read-pressed chat-id]}
(when-not (get-in cofx [:db :chats chat-id :public?])
{:ms 100 :dispatch [:pin-message/load-pin-messages chat-id]})]}
(load-more-messages chat-id true))))
(load-more-messages chat-id true nil))))
+41 -1
View File
@@ -4,7 +4,8 @@
[status-im.data-store.reactions :as data-store.reactions]
[status-im.transport.message.protocol :as message.protocol]
[utils.re-frame :as rf]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
(defn update-reaction
[acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
@@ -94,3 +95,42 @@
acc))
[]
reactions))
(defn- <-rpc
[{compressed-key :compressedKey
emoji-id :emojiId
:keys [from]}]
{:compressed-key compressed-key
:emoji-id emoji-id
:from from})
(defn- format-response
[response]
(->> (transforms/js->clj response)
(map <-rpc)
(group-by :emoji-id)))
(rf/defn save-emoji-reaction-details
{:events [:chat/save-emoji-reaction-details]}
[{:keys [db]} message-reactions long-pressed-emoji]
{:db (assoc db
:chat/reactions-authors
{:reaction-authors-list message-reactions
:selected-reaction long-pressed-emoji})})
(rf/defn clear-emoji-reaction-details
{:events [:chat/clear-emoji-reaction-author-details]}
[{:keys [db]} message-reactions]
{:db (update db dissoc :chat/reactions-authors)})
(rf/defn emoji-reactions-by-message-id
{:events [:chat.ui/emoji-reactions-by-message-id]}
[{:keys [db]} {:keys [message-id long-pressed-emoji]}]
{:json-rpc/call [{:method "wakuext_emojiReactionsByChatIDMessageID"
:params [(:current-chat-id db) message-id]
:js-response true
:on-error #(log/error "failed to fetch emoji reaction by message-id: "
{:message-id message-id :error %})
:on-success #(rf/dispatch [:chat/save-emoji-reaction-details
(format-response %) long-pressed-emoji])}]})
+1 -1
View File
@@ -36,7 +36,7 @@
status-im.signals.core
status-im.stickers.core
status-im.transport.core
[status-im.ui.components.permissions :as permissions]
[react-native.permissions :as permissions]
[status-im.ui.components.react :as react]
status-im.ui.screens.privacy-and-security-settings.events
[status-im.utils.dimensions :as dimensions]
+53 -20
View File
@@ -165,6 +165,15 @@
(wallet/request-current-block-update))
(prices/update-prices)))
(rf/defn login-local-paired-user
{:events [:multiaccounts.login/local-paired-user]}
[{:keys [db]}]
(let [{:keys [key-uid name password]} (get-in db [:syncing :multiaccount])]
{::login [key-uid
(types/clj->json {:name name
:key-uid key-uid})
password]}))
(rf/defn login
{:events [:multiaccounts.login.ui/password-input-submitted]}
[{:keys [db]}]
@@ -294,7 +303,7 @@
(re-frame/reg-fx
;;TODO: this could be replaced by a single API call on status-go side
::initialize-wallet
(fn [[network-id callback]]
(fn [[network-id network callback]]
(-> (js/Promise.all
(clj->js
[(js/Promise.
@@ -302,12 +311,31 @@
(json-rpc/call {:method "accounts_getAccounts"
:on-success resolve
:on-error reject})))
(js/Promise.
(fn [resolve _]
(json-rpc/call
{:method "wallet_addEthereumChain"
:params
[{:isTest false
:tokenOverrides []
:rpcUrl (get-in network [:config :UpstreamConfig :URL])
:chainColor "green"
:chainName (:name network)
:nativeCurrencyDecimals 10
:shortName "erc20"
:layer 1
:chainId (int network-id)
:enabled false
:fallbackURL (get-in network [:config :UpstreamConfig :URL])}]
:on-success resolve
:on-error (fn [_] (resolve nil))})))
(js/Promise.
(fn [resolve _]
(json-rpc/call {:method "wallet_getTokens"
:params [(int network-id)]
:on-success resolve
:on-error #(resolve nil)})))
:on-error (fn [_]
(resolve nil))})))
(js/Promise.
(fn [resolve reject]
(json-rpc/call {:method "wallet_getCustomTokens"
@@ -318,7 +346,7 @@
(json-rpc/call {:method "wallet_getSavedAddresses"
:on-success resolve
:on-error reject})))]))
(.then (fn [[accounts tokens custom-tokens favourites]]
(.then (fn [[accounts _ tokens custom-tokens favourites]]
(callback accounts
(normalize-tokens network-id tokens)
(mapv #(update % :symbol keyword) custom-tokens)
@@ -365,22 +393,27 @@
(rf/defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
[{:keys [db] :as cofx}]
(cond
(get db :onboarding-2/new-account?)
{:dispatch [:onboarding-2/finalize-setup]}
(let [pairing-completed? (= (get-in db [:syncing :pairing-status]) :completed)]
(cond
pairing-completed?
{:db (dissoc db :syncing)
:dispatch [:init-root :syncing-results]}
(get db :tos/accepted?)
(rf/merge
cofx
(multiaccounts/switch-theme nil :shell-stack)
(navigation/init-root :shell-stack))
(get db :onboarding-2/new-account?)
{:dispatch [:onboarding-2/finalize-setup]}
:else
{:dispatch [:init-root :tos]}))
(get db :tos/accepted?)
(rf/merge
cofx
(multiaccounts/switch-theme nil :shell-stack)
(navigation/init-root :shell-stack))
:else
{:dispatch [:init-root :tos]})))
(rf/defn get-settings-callback
{:events [::get-settings-callback]}
[{:keys [db] :as cofx} settings pairing-in-progress?]
[{:keys [db] :as cofx} settings]
(let [{:networks/keys [current-network networks]
:as settings}
(data-store.settings/rpc->settings settings)
@@ -412,8 +445,7 @@
(activity-center/notifications-fetch-pending-contact-requests)
(activity-center/update-seen-state)
(activity-center/notifications-fetch-unread-count)
(when-not pairing-in-progress?
(redirect-to-root)))))
(redirect-to-root))))
(re-frame/reg-fx
::open-last-chat
@@ -449,6 +481,7 @@
[{:keys [db] :as cofx}]
(let [{:networks/keys [current-network networks]} db
notifications-enabled? (get-in db [:multiaccount :notifications-enabled?])
current-network-config (get networks current-network)
network-id (str (get-in networks
[current-network :config :NetworkId]))
remote-push-notifications-enabled?
@@ -460,6 +493,7 @@
:on-disabled #(log/info "eip1559 is not activated")}
::initialize-wallet
[network-id
current-network-config
(fn [accounts tokens custom-tokens favourites]
(re-frame/dispatch [::initialize-wallet
accounts tokens custom-tokens favourites]))]
@@ -490,9 +524,8 @@
(rf/defn login-only-events
[{:keys [db] :as cofx} key-uid password save-password?]
(let [auth-method (:auth-method db)
new-auth-method (get-new-auth-method auth-method save-password?)
pairing-in-progress? (get-in db [:syncing :pairing-in-progress?])]
(let [auth-method (:auth-method db)
new-auth-method (get-new-auth-method auth-method save-password?)]
(log/debug "[login] login-only-events"
"auth-method" auth-method
"new-auth-method" new-auth-method)
@@ -500,7 +533,7 @@
{:db (assoc db :chats/loading? true)
:json-rpc/call
[{:method "settings_getSettings"
:on-success #(re-frame/dispatch [::get-settings-callback % pairing-in-progress?])}]}
:on-success #(re-frame/dispatch [::get-settings-callback %])}]}
(notifications/load-notification-preferences)
(when save-password?
(keychain/save-user-password key-uid password))
+3 -2
View File
@@ -89,8 +89,9 @@
{:events [:chat.ui/show-profile]}
[{:keys [db]} identity ens-name]
(let [my-public-key (get-in db [:multiaccount :public-key])]
(when (not= my-public-key identity)
(if (not= my-public-key identity)
{:db (-> db
(assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name))
:dispatch [:contacts/build-contact identity ens-name true]})))
:dispatch [:contacts/build-contact identity ens-name true]}
{:dispatch [:navigate-to :my-profile]})))
+29 -17
View File
@@ -10,8 +10,7 @@
[utils.re-frame :as rf]
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
[taoensso.timbre :as log]
[status-im2.constants :as constants]
[status-im.multiaccounts.model :as multiaccounts.model]))
[status-im2.constants :as constants]))
(rf/defn status-node-started
[{db :db :as cofx} {:keys [error]}]
@@ -56,36 +55,49 @@
:peers-count (count (:peers peer-stats)))}))
(rf/defn handle-local-pairing-signals
[{:keys [db] :as cofx} event]
[{:keys [db] :as cofx} {:keys [type action data] :as event}]
(log/info "local pairing signal received"
{:event event})
(let [connection-success? (and (= (:type event)
(let [{:keys [account password]} data
role (get-in db [:syncing :role])
receiver? (= role constants/local-pairing-role-receiver)
sender? (= role constants/local-pairing-role-sender)
connection-success? (and (= type
constants/local-pairing-event-connection-success)
(= (:action event)
(= action
constants/local-pairing-action-connect))
error-on-pairing? (contains? constants/local-pairing-event-errors (:type event))
completed-pairing? (and (= (:type event)
error-on-pairing? (contains? constants/local-pairing-event-errors type)
completed-pairing? (and (= type
constants/local-pairing-event-transfer-success)
(= (:action event)
(= action
constants/local-pairing-action-pairing-installation))
logged-in? (multiaccounts.model/logged-in? db)
;; since `connection-success` event is received on both sender and receiver devices
;; we check the `logged-in?` status to identify the receiver and take the user to next screen
navigate-to-syncing-devices? (and connection-success? (not logged-in?))
received-account? (and (= type
constants/local-pairing-event-received-account)
(= action
constants/local-pairing-action-pairing-account)
(and (some? account) (some? password)))
multiaccount-data (when received-account?
(merge account {:password password}))
navigate-to-syncing-devices? (and connection-success? receiver?)
user-in-syncing-devices-screen? (= (:view-id db) :syncing-progress)]
(merge {:db (cond-> db
connection-success?
(assoc-in [:syncing :pairing-in-progress?] :connected)
(assoc-in [:syncing :pairing-status] :connected)
received-account?
(assoc-in [:syncing :multiaccount] multiaccount-data)
error-on-pairing?
(assoc-in [:syncing :pairing-in-progress?] :error)
(assoc-in [:syncing :pairing-status] :error)
completed-pairing?
(assoc-in [:syncing :pairing-in-progress?] :completed))}
(assoc-in [:syncing :pairing-status] :completed))}
(when (and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
{:dispatch [:navigate-to :syncing-progress]})
(when completed-pairing?
{:dispatch [:syncing/pairing-completed]}))))
(when (and completed-pairing? sender?)
{:dispatch [:syncing/clear-states]})
(when (and completed-pairing? receiver?)
{:dispatch [:multiaccounts.login/local-paired-user]}))))
(rf/defn process
{:events [:signals/signal-received]}
+4 -3
View File
@@ -219,9 +219,10 @@
(rf/defn update-estimated-gas-success
{:events [:signing/update-estimated-gas-success]}
[{db :db} gas]
{:db (-> db
(assoc-in [:signing/tx :gas] gas)
(assoc-in [:signing/edit-fee :gas-loading?] false))})
(when (contains? db :signing/tx)
{:db (-> db
(assoc-in [:signing/tx :gas] gas)
(assoc-in [:signing/edit-fee :gas-loading?] false))}))
(rf/defn update-gas-price-success
{:events [:signing/update-gas-price-success]}
@@ -1,34 +0,0 @@
(ns status-im.ui.components.permissions
(:require ["react-native-permissions" :refer (requestMultiple PERMISSIONS RESULTS)]
[status-im.utils.platform :as platform]))
(def permissions-map
{:read-external-storage (cond
platform/android? (.-READ_EXTERNAL_STORAGE (.-ANDROID PERMISSIONS)))
:write-external-storage (cond
platform/low-device? (.-WRITE_EXTERNAL_STORAGE (.-ANDROID PERMISSIONS)))
:camera (cond
platform/android? (.-CAMERA (.-ANDROID PERMISSIONS))
platform/ios? (.-CAMERA (.-IOS PERMISSIONS)))
:record-audio (cond
platform/android? (.-RECORD_AUDIO (.-ANDROID PERMISSIONS))
platform/ios? (.-MICROPHONE (.-IOS PERMISSIONS)))})
(defn all-granted?
[permissions]
(let [permission-vals (distinct (vals permissions))]
(and (= (count permission-vals) 1)
(not (#{(.-BLOCKED RESULTS) (.-DENIED RESULTS)} (first permission-vals))))))
(defn request-permissions
[{:keys [permissions on-allowed on-denied]
:or {on-allowed #()
on-denied #()}}]
(let [permissions (remove nil? (mapv #(get permissions-map %) permissions))]
(if (empty? permissions)
(on-allowed)
(-> (requestMultiple (clj->js permissions))
(.then #(if (all-granted? (js->clj %))
(on-allowed)
(on-denied)))
(.catch on-denied)))))
+1 -1
View File
@@ -11,7 +11,7 @@
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.connectivity.view :as connectivity]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.permissions :as components.permissions]
[react-native.permissions :as components.permissions]
[status-im.ui.components.react :as react]
[status-im.ui.components.tooltip.views :as tooltip]
[status-im.ui.components.webview :as components.webview]
+3 -4
View File
@@ -384,8 +384,7 @@
(fn [prices wallet-currency amount amount-error display-symbol fee-display-symbol prices-loading?]
(let [converted-value (* amount
(get-in prices
[(keyword display-symbol) (keyword (:code wallet-currency))
:price]))]
[(keyword display-symbol) (keyword (:code wallet-currency))]))]
[quo/list-item
{:size :small
:title (if amount-error
@@ -412,8 +411,8 @@
show-error (reagent/atom false)]
(let [converted-fee-value (* fee
(get-in prices
[(keyword fee-display-symbol) (keyword (:code wallet-currency))
:price]))]
[(keyword fee-display-symbol)
(keyword (:code wallet-currency))]))]
[quo/list-item
{:size :small
:title (if (and (not (or gas-price-loading? gas-loading?)) gas-error)
@@ -1,12 +1,15 @@
(ns status-im.ui.screens.wallet.account.styles
(:require [quo.design-system.colors :as colors]
(:require [clojure.string :as string]
[quo.design-system.colors :as colors]
[status-im.ui.components.animation :as animation]))
(defn card
[window-width color]
{:width (- window-width 30)
:height 161
:background-color color
:background-color (if (string/blank? color)
colors/blue
color)
:shadow-offset {:width 0 :height 2}
:shadow-radius 8
:shadow-opacity 1
@@ -92,4 +92,4 @@
:accessibility-label (str (:symbol token) "-asset-value")
:icon (if icon
[wallet.components/token-icon icon]
[chat-icon/custom-icon-view-list (:name token) color])}])
[chat-icon/custom-icon-view-list (:name token) color])}])
@@ -1,5 +1,6 @@
(ns status-im.ui.screens.wallet.accounts.styles
(:require [quo.animated :as animated]
(:require [clojure.string :as string]
[quo.animated :as animated]
[quo.design-system.colors :as colors]))
(def dot-size 6)
@@ -68,7 +69,9 @@
(defn card
[color card-width]
(merge (card-common card-width)
{:background-color color
{:background-color (if (string/blank? color)
colors/blue
color)
:justify-content :space-between
:padding-horizontal 12
:padding-top 12
@@ -120,7 +120,6 @@
{:horizontal true
:deceleration-rate "fast"
:snap-to-interval page-width
:snap-to-alignment "left"
:shows-horizontal-scroll-indicator false
:scroll-event-throttle 64
:on-scroll #(let [x (.-nativeEvent.contentOffset.x ^js %)]
@@ -80,7 +80,7 @@
[react/scroll-view
{:horizontal true
:deceleration-rate "fast"
:snap-to-alignment "left"
:snap-to-alignment "start"
:shows-horizontal-scroll-indicator
false
:scroll-event-throttle 64
@@ -8,16 +8,22 @@
[status-im.ui.components.react :as react]
[status-im.ui.screens.wallet.accounts.common :as common]))
(defn asset
[currency token]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:wallet.send/set-symbol (:symbol token)])}
[common/render-asset token nil nil (:code currency)]])
(views/defview assets
[address]
(views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address]
currency [:wallet/currency]]
[:<>
(for [token tokens]
^{:key (str (:symbol token))}
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:wallet.send/set-symbol (:symbol token)])}
[common/render-asset token nil nil (:code currency)]])]))
[react/view
{:style {:height 300}}
[list/flat-list
{:data tokens
:key-fn :symbol
:render-fn (partial asset currency)}]]))
(defn render-account
[account _ _ {:keys [field event]}]
@@ -1,6 +1,7 @@
(ns status-im.ui.screens.wallet.send.views
(:require-macros [status-im.utils.views :refer [defview letsubs] :as views])
(:require [quo.core :as quo]
[quo2.core :as quo2]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[status-im.commands.core :as commands]
@@ -234,6 +235,17 @@
(let [to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[:<>
[quo2/page-nav
{:align-mid? true
:mid-section {:type :text-only
:main-text (i18n/label :t/send-transaction)}
:left-section {:on-press #(do
(re-frame/dispatch [:navigate-back])
(re-frame/dispatch
[:wallet/cancel-transaction-command]))
:icon :i/arrow-left
:accessibility-label :back-button}}]
[react/scroll-view
{:style {:flex 1}
:keyboard-should-persist-taps :handled}
+1 -1
View File
@@ -199,7 +199,7 @@
(-> amount-str
(js/parseFloat)
bignumber
(crypto->fiat (get-in prices [from to :price] ^js (bignumber 0)))
(crypto->fiat (get-in prices [from to] ^js (bignumber 0)))
(with-precision 2)
str))
+6 -14
View File
@@ -4,22 +4,14 @@
(defn- format-price-resp
[resp to mainnet?]
(if mainnet?
(when (seq resp)
(into {}
(for [[from price] resp]
{from {(keyword to) {:from (name from)
:to to
:price price}}})))
resp
{:ETH (into {}
(for [[_ price] resp]
{(keyword to) {:from "ETH"
:to to
:price price}}))}))
{(keyword to) price}))}))
(defn get-prices
[from to mainnet? on-success on-error]
(let [to (first to)]
(json-rpc/call {:method "wallet_fetchPrices"
:params [from to]
:on-success (fn [resp] (on-success (format-price-resp resp to mainnet?)))
:on-error on-error})))
(json-rpc/call {:method "wallet_fetchPrices"
:params [from to]
:on-success (fn [resp] (on-success (format-price-resp resp to mainnet?)))
:on-error on-error}))
+29 -8
View File
@@ -71,7 +71,7 @@
(defn derive-and-store-account
[key-uid path hashed-password type accounts]
(fn [value]
(let [{:keys [id error]} (types/json->clj value)]
(let [{:keys [id error keyUid]} (types/json->clj value)]
(if error
(re-frame/dispatch [::new-account-error :password-error error])
(native-module/multiaccount-derive-addresses
@@ -96,6 +96,7 @@
[:wallet.accounts/account-stored
{:address address
:public-key publicKey
:key-uid keyUid
:type type
:path (normalize-path path)}])))))))))))))
@@ -192,13 +193,33 @@
(rf/defn save-new-account
[{:keys [db] :as cofx}]
(let [{:keys [latest-derived-path]} (:multiaccount db)
{:keys [account type]} (:add-account db)
accounts (:multiaccount/accounts db)
new-accounts (conj accounts account)]
{:keys [account type]} (:add-account db)
{:keys [address name key-uid]} account
main-key-uid (or key-uid (get-in db [:multiaccount :key-uid]))
accounts (:multiaccount/accounts db)
new-accounts (conj accounts account)
;; Note(rasom): in case if a new account is created using a mnemonic or
;; a private key we add a new keypair to the database, otherwise we just
;; keep using "profile" keypair
[method params]
(if key-uid
["accounts_saveKeypair"
[{:key-uid main-key-uid
:name name
:type (if (= type :seed)
"seed"
"key")
:derived-from address
:last-used-derivation-index 0
:synced-from ""
:clock 0
:accounts [account]}]]
["accounts_saveAccount"
[(assoc account :key-uid key-uid)]])]
(when account
(rf/merge cofx
{:json-rpc/call [{:method "accounts_saveAccounts"
:params [[account]]
{:json-rpc/call [{:method method
:params params
:on-success #(re-frame/dispatch [::wallet/restart])}]
:db (-> db
(assoc :multiaccount/accounts new-accounts)
@@ -293,8 +314,8 @@
color (assoc :color color)
(not (nil? hidden)) (assoc :hidden hidden))
new-accounts (replace {account new-account} accounts)]
{:json-rpc/call [{:method "accounts_saveAccounts"
:params [[new-account]]
{:json-rpc/call [{:method "accounts_saveAccount"
:params [new-account]
:on-success #()}]
:db (assoc db :multiaccount/accounts new-accounts)}))
+24 -23
View File
@@ -381,30 +381,31 @@
(rf/defn wallet-send-gas-price-success
{:events [:wallet.send/update-gas-price-success]}
[{db :db} tx-entry price {:keys [maxFeePerGas maxPriorityFeePerGas gasPrice]}]
(if (eip1559/sync-enabled?)
(let [{:keys [slow-base-fee normal-base-fee fast-base-fee
current-base-fee max-priority-fee]}
price
max-priority-fee-bn (money/with-precision (signing.gas/get-suggested-tip max-priority-fee) 0)
fee-cap (-> normal-base-fee
money/bignumber
(money/add max-priority-fee-bn)
money/to-hex)
tip-cap (money/to-hex max-priority-fee-bn)]
(when (contains? db tx-entry)
(if (eip1559/sync-enabled?)
(let [{:keys [slow-base-fee normal-base-fee fast-base-fee
current-base-fee max-priority-fee]}
price
max-priority-fee-bn (money/with-precision (signing.gas/get-suggested-tip max-priority-fee) 0)
fee-cap (-> normal-base-fee
money/bignumber
(money/add max-priority-fee-bn)
money/to-hex)
tip-cap (money/to-hex max-priority-fee-bn)]
{:db (-> db
(update tx-entry
assoc
:maxFeePerGas (or maxFeePerGas fee-cap)
:maxPriorityFeePerGas (or maxPriorityFeePerGas tip-cap))
(assoc :wallet/current-base-fee current-base-fee
:wallet/normal-base-fee normal-base-fee
:wallet/slow-base-fee slow-base-fee
:wallet/fast-base-fee fast-base-fee
:wallet/current-priority-fee max-priority-fee)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})
{:db (-> db
(update tx-entry
assoc
:maxFeePerGas (or maxFeePerGas fee-cap)
:maxPriorityFeePerGas (or maxPriorityFeePerGas tip-cap))
(assoc :wallet/current-base-fee current-base-fee
:wallet/normal-base-fee normal-base-fee
:wallet/slow-base-fee slow-base-fee
:wallet/fast-base-fee fast-base-fee
:wallet/current-priority-fee max-priority-fee)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})
{:db (-> db
(assoc-in [:wallet/prepare-transaction :gasPrice] (or gasPrice price))
(assoc-in [:signing/edit-fee :gas-price-loading?] false))}))
(assoc-in [:wallet/prepare-transaction :gasPrice] (or gasPrice price))
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})))
(rf/defn set-max-amount
{:events [:wallet.send/set-max-amount]}
@@ -13,7 +13,7 @@
:margin-vertical 8})
(defn sheet
[{:keys [top bottom]} window-height override-theme shell?]
[{:keys [top bottom]} window-height override-theme padding-bottom-override shell?]
{:position :absolute
:max-height (- window-height top 20)
:z-index 1
@@ -22,9 +22,9 @@
:right 0
:border-top-left-radius 20
:border-top-right-radius 20
:overflow :hidden
:overflow (when shell? :hidden)
:flex 1
:padding-bottom (max 20 bottom)
:padding-bottom (or padding-bottom-override (max 20 bottom))
:background-color (if shell?
:transparent
(colors/theme-colors colors/white colors/neutral-90 override-theme))})
+16 -9
View File
@@ -13,7 +13,9 @@
(def timing-options #js {:duration duration})
(defn hide
[translate-y bg-opacity window-height]
[translate-y bg-opacity window-height on-close]
(when (fn? on-close)
(on-close))
;; it will be better to use animation callback, but it doesn't work
;; so we have to use timeout, also we add 50ms for safety
(js/setTimeout #(rf/dispatch [:bottom-sheet-hidden]) (+ duration 50))
@@ -29,7 +31,7 @@
(def gesture-values (atom {}))
(defn get-sheet-gesture
[translate-y bg-opacity window-height]
[translate-y bg-opacity window-height on-close]
(-> (gesture/gesture-pan)
(gesture/on-start
(fn [_]
@@ -47,17 +49,22 @@
(fn [_]
(if (< (:dy @gesture-values) 0)
(show translate-y bg-opacity)
(hide translate-y bg-opacity window-height))))))
(hide translate-y bg-opacity window-height on-close))))))
(defn view
[{:keys [hide? insets]} {:keys [content override-theme selected-item shell?]}]
[{:keys [hide? insets]}
{:keys [content override-theme selected-item padding-bottom-override on-close shell?]}]
(let [{window-height :height} (rn/get-window)
bg-opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value window-height)
sheet-gesture (get-sheet-gesture translate-y bg-opacity window-height)]
(rn/use-effect #(if hide? (hide translate-y bg-opacity window-height) (show translate-y bg-opacity))
[hide?])
(hooks/use-back-handler #(do (rf/dispatch [:hide-bottom-sheet]) true))
sheet-gesture (get-sheet-gesture translate-y bg-opacity window-height on-close)]
(rn/use-effect
#(if hide? (hide translate-y bg-opacity window-height on-close) (show translate-y bg-opacity))
[hide?])
(hooks/use-back-handler #(do (when (fn? on-close)
(on-close))
(rf/dispatch [:hide-bottom-sheet])
true))
[rn/view {:flex 1}
;; backdrop
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:hide-bottom-sheet])}
@@ -70,7 +77,7 @@
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
(styles/sheet insets window-height override-theme shell?))}
(styles/sheet insets window-height override-theme padding-bottom-override shell?))}
(when shell?
[blur/ios-view
@@ -15,10 +15,10 @@
:right 0}))
(defn main-view
[translate-y]
[translate-y override-theme]
(reanimated/apply-animations-to-style
{:transform [{:translate-y translate-y}]}
{:background-color (colors/theme-colors colors/white colors/neutral-95)
{:background-color (colors/theme-colors colors/white colors/neutral-95 override-theme)
:border-top-left-radius 20
:border-top-right-radius 20
:flex 1
@@ -36,8 +36,8 @@
:align-items :center})
(defn handle
[]
[override-theme]
{:width 32
:height 4
:border-radius 100
:background-color (colors/theme-colors colors/neutral-100-opa-30 colors/white-opa-30)})
:background-color (colors/theme-colors colors/neutral-100-opa-30 colors/white-opa-30 override-theme)})
@@ -45,8 +45,9 @@
(defn f-view
[content skip-background?]
(let [scroll-enabled (reagent/atom true)
curr-scroll (atom 0)]
(let [scroll-enabled (reagent/atom true)
curr-scroll (atom 0)
{:keys [override-theme]} (rf/sub [:get-screen-params])]
(fn []
(let [insets (safe-area/get-insets)
{:keys [height]} (rn/get-window)
@@ -70,9 +71,9 @@
[reanimated/view {:style (style/background opacity)}])
[gesture/gesture-detector
{:gesture (drag-gesture translate-y opacity scroll-enabled curr-scroll close)}
[reanimated/view {:style (style/main-view translate-y)}
[reanimated/view {:style (style/main-view translate-y override-theme)}
[rn/view {:style style/handle-container}
[rn/view {:style (style/handle)}]]
[rn/view {:style (style/handle override-theme)}]]
[content
{:insets insets
:close close
+16 -13
View File
@@ -71,7 +71,7 @@
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}])}]))
(defn delete-chat-action
[{:keys [chat-id] :as item}]
[{:keys [chat-id] :as item} inside-chat?]
(hide-sheet-and-dispatch
[:show-bottom-sheet
{:content (fn []
@@ -81,7 +81,10 @@
:context item
:accessibility-label :delete-chat-confirm
:button-text (i18n/label :t/delete-chat)
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}])}]))
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])
(when inside-chat?
(rf/dispatch [:navigate-back])))}])}]))
(defn leave-group-action
[item chat-id]
@@ -94,10 +97,10 @@
:context item
:accessibility-label :leave-group
:button-text (i18n/label :t/leave-group)
:on-press #(do
(rf/dispatch [:navigate-back])
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed
chat-id]))}])}]))
:on-press (fn []
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed
chat-id])
(rf/dispatch [:navigate-back]))}])}]))
(defn block-user-action
[{:keys [public-key] :as item}]
@@ -152,10 +155,10 @@
:add-divider? true}))
(defn delete-chat-entry
[item]
[item inside-chat?]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action item)
:on-press #(delete-chat-action item inside-chat?)
:danger? true
:accessibility-label :delete-chat
:sub-label nil
@@ -393,11 +396,11 @@
:chevron? false}))
(defn destructive-actions
[{:keys [group-chat] :as item}]
[{:keys [group-chat] :as item} inside-chat?]
[(clear-history-entry item)
(if group-chat
(leave-group-entry item nil)
(delete-chat-entry item))])
(delete-chat-entry item inside-chat?))])
(defn notification-actions
[{:keys [chat-id group-chat public?]} inside-chat?]
@@ -431,14 +434,14 @@
[[(view-profile-entry chat-id)
(edit-nickname-entry chat-id)]
(notification-actions item inside-chat?)
(destructive-actions item)]])
(destructive-actions item inside-chat?)]])
(defn private-group-chat-actions
[item inside-chat?]
[quo/action-drawer
[(group-actions item inside-chat?)
(notification-actions item inside-chat?)
(destructive-actions item)]])
(destructive-actions item inside-chat?)]])
(defn contact-actions
[{:keys [public-key] :as contact} {:keys [chat-id admin?] :as extra-data}]
@@ -471,4 +474,4 @@
[quo/action-drawer
[(when admin? [(edit-name-image-entry)])
[(notifications-entry admin?)]
(destructive-actions group)]]))
(destructive-actions group false)]]))
+3 -1
View File
@@ -23,7 +23,9 @@
:discover (js/require "../resources/images/ui2/discover.png")
:invite-friends (js/require "../resources/images/ui2/invite-friends.png")
:no-contacts-light (js/require "../resources/images/ui2/no-contacts-light.png")
:no-contacts-dark (js/require "../resources/images/ui2/no-contacts-dark.png")})
:no-contacts-dark (js/require "../resources/images/ui2/no-contacts-dark.png")
:no-messages-light (js/require "../resources/images/ui2/no-messages-light.png")
:no-messages-dark (js/require "../resources/images/ui2/no-messages-dark.png")})
(def mock-images
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
+8 -7
View File
@@ -71,12 +71,12 @@
(def request-to-join-pending-state 1)
(def reactions
{emoji-reaction-love :i/love
emoji-reaction-thumbs-up :i/thumbs-up
emoji-reaction-thumbs-down :i/thumbs-down
emoji-reaction-laugh :i/laugh
emoji-reaction-sad :i/sad
emoji-reaction-angry :i/angry})
{emoji-reaction-love :reaction/love
emoji-reaction-thumbs-up :reaction/thumbs-up
emoji-reaction-thumbs-down :reaction/thumbs-down
emoji-reaction-laugh :reaction/laugh
emoji-reaction-sad :reaction/sad
emoji-reaction-angry :reaction/angry})
(def ^:const invitation-state-unknown 0)
(def ^:const invitation-state-requested 1)
@@ -277,9 +277,10 @@
(def ^:const local-pairing-event-transfer-error "transfer-error")
;; receiver events
(def ^:const local-pairing-event-received-amount "received-account")
(def ^:const local-pairing-event-received-account "received-account")
(def ^:const local-pairing-event-process-success "process-success")
(def ^:const local-pairing-event-process-error "process-error")
(def ^:const local-pairing-event-received-installation "received-installation")
(def ^:const local-pairing-event-errors
#{local-pairing-event-connection-error
@@ -38,22 +38,18 @@
[]
(let [unread-count (rf/sub [:activity-center/unread-count])]
[quo/action-drawer
[[{:icon :i/check
[[{:icon :i/mark-as-read
:override-theme :dark
:label (i18n/label :t/mark-all-notifications-as-read)
:disabled? (zero? unread-count)
:on-press (fn []
(if (pos? unread-count)
(rf/dispatch [:activity-center.notifications/mark-all-as-read-locally
(fn []
{:icon :up-to-date
:icon-color colors/success-50
:text (i18n/label :t/notifications-marked-as-read
{:count unread-count})
:override-theme :dark})])
;; Need design improvements if there is NO unread
;; notifications to mark as read
;; https://github.com/status-im/status-mobile/issues/14983
(js/alert "No unread notifications to mark as read"))
(rf/dispatch [:activity-center.notifications/mark-all-as-read-locally
(fn []
{:icon :up-to-date
:icon-color colors/success-50
:text (i18n/label :t/notifications-marked-as-read
{:count unread-count})
:override-theme :dark})])
(rf/dispatch [:hide-bottom-sheet]))}]]]))
(defn empty-tab
@@ -1,11 +1,12 @@
(ns status-im2.contexts.add-new-contact.style
(:require [quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]
[react-native.platform :as platform]
[quo2.foundations.typography :as typography]))
[react-native.safe-area :as safe-area]))
(defn container-outer
[]
{:style {:flex (if platform/ios? 4.5 5)
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)
:justify-content :space-between
:align-items :center
@@ -171,7 +172,7 @@
:size 40
:width 335
:style {:margin-top 24
:margin-bottom 24}
:margin-bottom (+ (safe-area/get-bottom) 12)}
:accessibility-label :new-contact-button
:before :i/profile
:disabled (not= state :valid)})
@@ -51,64 +51,68 @@
show-paste-button? (and (not (string/blank? @clipboard))
(string/blank? @default-value)
(string/blank? input))]
[rn/view (style/container-outer)
[rn/view style/container-inner
[quo/button
(merge (style/button-close)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back]))}) :i/close]
[quo/text (style/text-title)
(i18n/label :t/add-a-contact)]
[quo/text (style/text-subtitle)
(i18n/label :t/find-your-friends)]
[quo/text (style/text-description)
(i18n/label :t/ens-or-chat-key)]
[rn/view style/container-text-input
[rn/view (style/text-input-container invalid?)
[rn/text-input
(merge (style/text-input)
{:default-value (or scanned @default-value input)
:placeholder (i18n/label :t/type-some-chat-key)
:on-change-text (fn [v]
(reset! default-value v)
(debounce/debounce-and-dispatch
[:contacts/set-new-identity v nil]
600))})]
(when show-paste-button?
[quo/button
(merge style/button-paste
{:on-press
(fn []
(reset! default-value @clipboard)
(rf/dispatch
[:contacts/set-new-identity @clipboard nil]))})
(i18n/label :t/paste)])]
[rn/keyboard-avoiding-view
{:style {:flex 1}}
[rn/touchable-without-feedback
{:on-press rn/dismiss-keyboard!}
[rn/view (style/container-outer)
[rn/view style/container-inner
[quo/button
(merge (style/button-close)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back]))}) :i/close]
[quo/text (style/text-title)
(i18n/label :t/add-a-contact)]
[quo/text (style/text-subtitle)
(i18n/label :t/find-your-friends)]
[quo/text (style/text-description)
(i18n/label :t/ens-or-chat-key)]
[rn/view style/container-text-input
[rn/view (style/text-input-container invalid?)
[rn/text-input
(merge (style/text-input)
{:default-value (or scanned @default-value input)
:placeholder (i18n/label :t/type-some-chat-key)
:on-change-text (fn [v]
(reset! default-value v)
(debounce/debounce-and-dispatch
[:contacts/set-new-identity v nil]
600))
:blur-on-submit true
:return-key-type :done})]
(when show-paste-button?
[quo/button
(merge style/button-paste
{:on-press
(fn []
(reset! default-value @clipboard)
(rf/dispatch
[:contacts/set-new-identity @clipboard nil]))})
(i18n/label :t/paste)])]
[quo/button
(merge style/button-qr
{:on-press #(rf/dispatch
[::qr-scanner/scan-code
{:handler :contacts/qr-code-scanned}])})
:i/scan]]
(when invalid?
[rn/view style/container-invalid
[quo/icon :i/alert style/icon-invalid]
[quo/text style/text-invalid
(i18n/label (or msg :t/invalid-ens-or-key))]])
(when (= state :valid)
[found-contact public-key])]
[quo/button
(merge style/button-qr
{:on-press #(rf/dispatch
[::qr-scanner/scan-code
{:handler :contacts/qr-code-scanned}])})
:i/scan]]
(when invalid?
[rn/view style/container-invalid
[quo/icon :i/alert style/icon-invalid]
[quo/text style/text-invalid
(i18n/label (or msg :t/invalid-ens-or-key))]])
(when (= state :valid)
[found-contact public-key])]
[rn/view
[quo/button
(merge (style/button-view-profile state)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile public-key ens]))})
(i18n/label :t/view-profile)]]]))))
(merge (style/button-view-profile state)
{:on-press
(fn []
(reset! clipboard nil)
(reset! default-value nil)
(rf/dispatch [:contacts/clear-new-identity])
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile public-key ens]))})
(i18n/label :t/view-profile)]]]]))))
@@ -14,7 +14,8 @@
[status-im2.contexts.chat.composer.actions.style :as style]))
(defn send-message
[{:keys [text-value focused? maximized?]}
[{:keys [sending-images? sending-links?]}
{:keys [text-value focused? maximized?]}
{:keys [height saved-height last-height opacity background-y container-opacity]}
window-height]
(reanimated/animate height constants/input-height)
@@ -32,10 +33,12 @@
(rf/dispatch [:chat.ui/set-chat-input-text nil])
(reset! maximized? false)
(reset! text-value "")
(reset! sending-links? false)
(reset! sending-images? false)
(messages.list/scroll-to-bottom))
(defn f-send-button
[{:keys [text-value] :as state}
[props {:keys [text-value] :as state}
animations window-height images?
btn-opacity z-index]
(rn/use-effect (fn []
@@ -54,14 +57,14 @@
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press #(send-message state animations window-height)}
:on-press #(send-message props state animations window-height)}
:i/arrow-up]])
(defn send-button
[{:keys [text-value] :as state} animations window-height images?]
[props {:keys [text-value] :as state} animations window-height images?]
(let [btn-opacity (reanimated/use-shared-value 0)
z-index (reagent/atom (if (and (empty? @text-value) (not images?)) 0 1))]
[:f> f-send-button state animations window-height images? btn-opacity z-index]))
[:f> f-send-button props state animations window-height images? btn-opacity z-index]))
(defn audio-button
[{:keys [record-reset-fn input-ref]}
@@ -197,6 +200,6 @@
[image-button props animations insets]
[reaction-button]
[format-button]]
[:f> send-button state animations window-height images]
[:f> send-button props state animations window-height images]
(when (and (not edit) (not images))
[audio-button props state animations])])

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