Compare commits

..
48 Commits
Author SHA1 Message Date
Ibrahem 10de3c9759 [16153] Remove scrolling to first message(s) 2023-06-03 16:12:02 +03: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
Ajay Sivan 682eb841ff fix: setup syncing timer not working (#15852) 2023-05-25 05:24:03 -07:00
Ajay Sivan b45632d2fd Bump release to 1.23.0 (#15999) 2023-05-25 04:48:57 -07:00
Mohamed Javid 877ee14bcc Add default customization color (#16026)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-05-25 16:53:26 +05:30
Omar Basem 7ec5117f54 fix mentions delay (#16025)
* fix mentions delay
2023-05-25 13:56:22 +04:00
Parvesh Monu b7cc54a356 fix pin image in community leads to error (#16017) 2023-05-25 14:01:42 +05:30
Volodymyr Kozieiev e1e596cf5f Bottom sheet background on Android changed to overcome issues with blur (#16009) 2023-05-24 19:58:47 +01:00
Omar Basem 0cc631ce2e refactor: lightbox screen (#15996)
* refactor: lightbox screen
2023-05-24 22:32:31 +04:00
Omar Basem 24eaec80bd Fix composer opacity on reenter screen (#16010)
* fix: composer opacity on re-enter screen
2023-05-24 22:10:33 +04:00
Ajay Sivan 7fc05bc069 new icons (#15937) 2023-05-24 05:59:55 -07:00
Omar Basem 45da1a28df fix calc lines (#16005)
fix composer `calc-lines`
2023-05-24 14:22:44 +04:00
jakub 6415c06398 ios: drop fastlane-plugin-clean_testflight_testers
We are not using it for anything, just wastes time and space.

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-05-24 11:52:01 +02:00
flexsurfer 2c44882c35 clean old onboarding and communities (#15994) 2023-05-24 11:16:12 +02:00
jakub 2493b8ad4b ios: replace Diawi Fastlane plugin that disappered
For an unknown reason the original Diawi plugin for Fastlane has been
removed from GitHub and RubyGems pages and can no longer be used.

This replaces it with a Node.js script which does the same job.

I tried using `diawi` and `diawi-nodejs-uploader` but both had issues,
one of them being depending on far too many useless packages.

Resolves: https://github.com/status-im/status-mobile/issues/15951

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-05-24 10:55:38 +02:00
220 changed files with 3214 additions and 5202 deletions
+1 -4
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -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 {
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
agent { label 'macos' }
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
agent { label params.AGENT_LABEL }
@@ -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,
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,4 +1,4 @@
library 'status-jenkins-lib@v1.7.8'
library 'status-jenkins-lib@v1.7.9'
pipeline {
agent {
-32
View File
@@ -182,17 +182,6 @@ def build_ios_e2e
)
end
def upload_to_diawi(source)
diawi(
file: source,
timeout: 120,
check_status_delay: 5,
token: ENV['DIAWI_TOKEN']
)
# save the URL to a file for use in CI
File.write('diawi.out', lane_context[SharedValues::UPLOADED_FILE_LINK_TO_DIAWI])
end
platform :ios do
desc '`fastlane ios adhoc` - ad-hoc lane for iOS.'
desc 'This lane is used for PRs, Releases, etc.'
@@ -256,27 +245,6 @@ platform :ios do
)
end
desc '`fastlane ios clean` - remove inactive TestFlight users'
lane :clean do
clean_testflight_testers(
username: ENV['FASTLANE_APPLE_ID'],
days_of_inactivity: 30
)
# In the future we can try using 'oldest_build_allowed'
end
desc '`fastlane ios upload-diawi` - upload .ipa to diawi'
desc 'expects to have an .ipa prepared: `status-ios/StatusIm.ipa`'
desc 'expects to have a diawi token as DIAWI_TOKEN env variable'
desc 'expects to have a github token as GITHUB_TOKEN env variable'
desc "will fails if file isn't there"
desc '---'
desc 'Output: writes `fastlane/diawi.out` file url of the uploded file'
lane :upload_diawi do
ipa = ENV['DIAWI_IPA'] || 'status-ios/StatusIm.ipa'
upload_to_diawi(ipa)
end
desc '`fastlane ios saucelabs` - upload .app to sauce labs'
desc 'also notifies in a GitHub comments'
desc 'expects to have an .apk prepared: `result/app.apk`'
-4
View File
@@ -1,7 +1,3 @@
source 'https://rubygems.org'
gem 'fastlane', '>= 2.131.0'
plugins_path = ENV['FASTLANE_PLUGINFILE_PATH'] ||
File.join(__dir__, 'Pluginfile')
eval_gemfile(plugins_path) if plugins_path
+10 -25
View File
@@ -3,21 +3,21 @@ GEM
specs:
CFPropertyList (3.0.6)
rexml
addressable (2.8.1)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.728.0)
aws-sdk-core (3.170.0)
aws-partitions (1.768.0)
aws-sdk-core (3.173.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.63.0)
aws-sdk-kms (1.64.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.119.1)
aws-sdk-s3 (1.122.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
@@ -65,8 +65,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.212.1)
fastimage (2.2.7)
fastlane (2.212.2)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -105,11 +105,8 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-clean_testflight_testers (0.3.0)
fastlane-plugin-diawi (2.1.0)
rest-client (>= 2.0.0)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.36.0)
google-apis-androidpublisher_v3 (0.42.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.0)
addressable (~> 2.5, >= 2.5.1)
@@ -140,7 +137,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.3.0)
googleauth (1.5.2)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
@@ -148,7 +145,6 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-accept (1.7.0)
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
@@ -156,16 +152,12 @@ GEM
json (2.6.3)
jwt (2.7.0)
memoist (0.16.2)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.0218.1)
mini_magick (4.12.0)
mini_mime (1.1.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.1)
netrc (0.11.0)
optparse (0.1.1)
os (1.1.4)
plist (3.7.0)
@@ -175,11 +167,6 @@ GEM
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
@@ -226,8 +213,6 @@ PLATFORMS
DEPENDENCIES
fastlane (>= 2.131.0)
fastlane-plugin-clean_testflight_testers
fastlane-plugin-diawi
BUNDLED WITH
2.4.6
2.3.9
-6
View File
@@ -1,6 +0,0 @@
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
gem 'fastlane-plugin-clean_testflight_testers'
gem 'fastlane-plugin-diawi'
-2
View File
@@ -24,8 +24,6 @@ let
shellHook = ''
[ -z "$STATUS_MOBILE_HOME" ] && echo "STATUS_MOBILE_HOME is empty!" && exit 1
export FASTLANE_PLUGINFILE_PATH=$STATUS_MOBILE_HOME/fastlane/Pluginfile
'';
meta = with lib; {
+18 -91
View File
@@ -5,10 +5,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1ypdmpdn20hxp5vwxz3zc04r5xcwqc25qszdlg41h8ghdqbllwmw";
sha256 = "15s8van7r2ad3dq6i03l3z4hqnvxcq75a3h72kxvf9an53sqma20";
type = "gem";
};
version = "2.8.1";
version = "2.8.4";
};
artifactory = {
groups = ["default"];
@@ -45,10 +45,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0q3q19insq5ablmr6ypq033qg1gsar5mdphhp7xg80rd615cnq97";
sha256 = "1256rf6zjh3canwr636w7yczbvhh72cpz2fw5ixljbh4fcfkrvlm";
type = "gem";
};
version = "1.728.0";
version = "1.768.0";
};
aws-sdk-core = {
dependencies = ["aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath"];
@@ -56,10 +56,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0zc4zhv2wq7s5p8c9iaplama1lpg2kwldg81j83c8w4xydf1wd2r";
sha256 = "10djgbz4k9w3axka8xrhf97h9yh9svi5g5xvncfwnkg6h22w2177";
type = "gem";
};
version = "3.170.0";
version = "3.173.0";
};
aws-sdk-kms = {
dependencies = ["aws-sdk-core" "aws-sigv4"];
@@ -67,10 +67,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0v87zi28dfmrv7bv91yfldccnpd63n295siirbz7wqv1rajn8n02";
sha256 = "1bcm0c9f7xy5qj5f0z3gddqslhb2vzrj9smc39pgqyq4jmn5kpj0";
type = "gem";
};
version = "1.63.0";
version = "1.64.0";
};
aws-sdk-s3 = {
dependencies = ["aws-sdk-core" "aws-sdk-kms" "aws-sigv4"];
@@ -78,10 +78,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1rpnlzsl52znhcki13jkwdshgwf51pn26267481f4fa842gr7xgp";
sha256 = "01cryf8kfkmlsxb327szcwcagsp7lss5gmk6zxlgap65lv8bc7rx";
type = "gem";
};
version = "1.119.1";
version = "1.122.0";
};
aws-sigv4 = {
dependencies = ["aws-eventstream"];
@@ -357,10 +357,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0nnggg20za5vamdpkgrxxa32z33d8hf0g2bciswkhqnc6amb3yjr";
sha256 = "1pd7pamzhdz2w0fbcvsfn2nyslznvphnwj16zw35g2b28zd2xyzx";
type = "gem";
};
version = "2.2.6";
version = "2.2.7";
};
fastlane = {
dependencies = ["CFPropertyList" "addressable" "artifactory" "aws-sdk-s3" "babosa" "colored" "commander" "dotenv" "emoji_regex" "excon" "faraday" "faraday-cookie_jar" "faraday_middleware" "fastimage" "gh_inspector" "google-apis-androidpublisher_v3" "google-apis-playcustomapp_v1" "google-cloud-storage" "highline" "json" "jwt" "mini_magick" "multipart-post" "naturally" "optparse" "plist" "rubyzip" "security" "simctl" "terminal-notifier" "terminal-table" "tty-screen" "tty-spinner" "word_wrap" "xcodeproj" "xcpretty" "xcpretty-travis-formatter"];
@@ -368,31 +368,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0b22m2dkydyv2si55b1jzznzgxf2ycx2aarv1j5p25k861h2gsml";
sha256 = "15sa3v3aaslympg9nmadmpxpbzykdiybzxn3navc7mf0iscb3q7s";
type = "gem";
};
version = "2.212.1";
};
fastlane-plugin-clean_testflight_testers = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0qkcjf7xrnki4v94mcgcm3v2f89vq8clwxx1d5ipv0wwm5ri26c9";
type = "gem";
};
version = "0.3.0";
};
fastlane-plugin-diawi = {
dependencies = ["rest-client"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1sjznx9hwlfa7ndv7av870dvl0cvmh68yk381r55ylw4jjvk5mwl";
type = "gem";
};
version = "2.1.0";
version = "2.212.2";
};
gh_inspector = {
groups = ["default"];
@@ -410,10 +389,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1mbnmn36z1cnsd6ar76p9wvqi0ac6wlpm1p1lqczivain16qma76";
sha256 = "0ks2ak4fcvlflhyinykvd88g2ybxwsbc347aww349zhn1mqprbvg";
type = "gem";
};
version = "0.36.0";
version = "0.42.0";
};
google-apis-core = {
dependencies = ["addressable" "googleauth" "httpclient" "mini_mime" "representable" "retriable" "rexml" "webrick"];
@@ -508,10 +487,10 @@
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1hpwgwhk0lmnknkw8kbdfxn95qqs6aagpq815l5fkw9w6mi77pai";
sha256 = "1lj5haarpn7rybbq9s031zcn9ji3rlz5bk64bwa2j34q5s1h5gis";
type = "gem";
};
version = "1.3.0";
version = "1.5.2";
};
highline = {
groups = ["default"];
@@ -523,16 +502,6 @@
};
version = "2.0.3";
};
http-accept = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "09m1facypsdjynfwrcv19xcb1mqg8z6kk31g8r33pfxzh838c9n6";
type = "gem";
};
version = "1.7.0";
};
http-cookie = {
dependencies = ["domain_name"];
groups = ["default"];
@@ -594,27 +563,6 @@
};
version = "0.16.2";
};
mime-types = {
dependencies = ["mime-types-data"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0ipw892jbksbxxcrlx9g5ljq60qx47pm24ywgfbyjskbcl78pkvb";
type = "gem";
};
version = "3.4.1";
};
mime-types-data = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1pky3vzaxlgm9gw5wlqwwi7wsw3jrglrfflrppvvnsrlaiz043z9";
type = "gem";
};
version = "3.2023.0218.1";
};
mini_magick = {
groups = ["default"];
platforms = [];
@@ -675,16 +623,6 @@
};
version = "2.2.1";
};
netrc = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0gzfmcywp1da8nzfqsql2zqi648mfnx6qwkig3cv36n9m0yy676y";
type = "gem";
};
version = "0.11.0";
};
optparse = {
groups = ["default"];
platforms = [];
@@ -746,17 +684,6 @@
};
version = "3.2.0";
};
rest-client = {
dependencies = ["http-accept" "http-cookie" "mime-types" "netrc"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1qs74yzl58agzx9dgjhcpgmzfn61fqkk33k1js2y5yhlvc5l19im";
type = "gem";
};
version = "2.1.0";
};
retriable = {
groups = ["default"];
platforms = [];
@@ -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
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

+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env node
import https from 'node:https'
import { basename } from 'node:path'
import { promisify } from 'node:util'
import { createReadStream } from 'node:fs'
import log from 'npmlog'
import FormData from 'form-data'
const UPLOAD_URL = 'https://upload.diawi.com/'
const STATUS_URL = 'https://upload.diawi.com/status'
const POLL_MAX_COUNT = 10
const POLL_INTERVAL_MS = 700
const sleep = (ms) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, (ms))
})
}
const getRequest = async (url) => {
return new Promise((resolve, reject) => {
let data = []
https.get(url, res => {
res.on('error', err => reject(err))
res.on('data', chunk => { data.push(chunk) })
res.on('end', () => {
let payload = Buffer.concat(data).toString()
resolve({
code: res.statusCode,
message: res.statusMessage,
payload: payload,
})
})
})
})
}
const uploadIpa = async (ipaPath, comment, token) => {
let form = new FormData()
form.append('token', token)
form.append('file', createReadStream(ipaPath))
form.append('comment', comment || basename(ipaPath))
const formSubmitPromise = promisify(form.submit.bind(form))
const res = await formSubmitPromise(UPLOAD_URL)
if (res.statusCode != 200) {
log.error('uploadIpa', 'Upload failed: %d %s', res.statusCode, res.statusMessage)
process.exit(1)
}
return new Promise((resolve) => {
const jobId = res.on('data', async (data) => {
resolve(JSON.parse(data)['job'])
})
})
}
const checkStatus = async (jobId, token) => {
let params = new URLSearchParams({
token: token, job: jobId,
})
let rval = await getRequest(`${STATUS_URL}?${params.toString()}`)
if (rval.code != 200) {
log.error('checkStatus', 'Check query failed: %d %s', rval.code, rval.message)
process.exit(1)
}
return JSON.parse(rval.payload)
}
const pollStatus = async (jobId, token) => {
let interval = POLL_INTERVAL_MS
for (let i = 0; i <= POLL_MAX_COUNT; i++) {
let json = await checkStatus(jobId, token)
switch (json.status) {
case 2000:
return json
case 2001:
log.verbose('pollStatus', 'Waiting: %s', json.message)
break /* Nothing, just poll again. */
case 4000000:
log.warning('pollStatus', 'Doubling polling interval: %s', json.message)
interval *= 2
break
default:
log.error('pollStatus', `Error in status response: ${json.message}`)
process.exit(1)
}
await sleep(interval)
}
}
const main = async () => {
const token = process.env.DIAWI_TOKEN
const targetFile = process.argv[2]
const comment = process.argv[3]
log.level = process.env.VERBOSE ? 'verbose' : 'info'
if (token === undefined) {
log.error('main', 'No DIAWI_TOKEN env var provided!')
process.exit(1)
}
if (targetFile === undefined) {
log.error('main', 'No file path provided!')
process.exit(1)
}
log.info('main', 'Uploading: %s', targetFile)
let jobId = await uploadIpa(targetFile, comment, token)
log.info('main', 'Polling upload job status: %s', jobId)
let uploadMeta = await pollStatus(jobId, token)
console.log(uploadMeta)
}
main()
+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)]]))))
@@ -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]))
+1
View File
@@ -130,6 +130,7 @@
;;Solid
(def black "#000000")
(def black-opa-0 (alpha black 0))
(def onboarding-header-black "#000716")
;;;;Primary
+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 -9
View File
@@ -3,8 +3,6 @@
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.keycard.views :as keycard]
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[status-im.bottom-sheet.view :as bottom-sheet]
[react-native.core :as rn]))
@@ -30,13 +28,7 @@
(merge keycard/more-sheet)
(= view :learn-more)
(merge about-app/learn-more)
(= view :recover-sheet)
(merge recover.views/bottom-sheet)
(= view :migrate-account-password)
(merge key-storage/migrate-account-password))]
(merge about-app/learn-more))]
[:f>
(fn []
+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))))
+43 -14
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]
@@ -15,7 +16,7 @@
(assoc-in acc [chat-id message-id emoji-id emoji-reaction-id] reaction)))
(defn process-reactions
[chats]
[_]
(fn [reactions new-reactions]
;; TODO(Ferossgp): handling own reaction in subscription could be expensive,
;; for better performance we can here separate own reaction into 2 maps
@@ -23,14 +24,7 @@
(fn [acc
{:keys [chat-id message-id emoji-id emoji-reaction-id retracted]
:as reaction}]
(cond-> (update-reaction acc retracted chat-id message-id emoji-id emoji-reaction-id reaction)
(get-in chats [chat-id :profile-public-key])
(update-reaction retracted
constants/timeline-chat-id
message-id
emoji-id
emoji-reaction-id
reaction)))
(update-reaction acc retracted chat-id message-id emoji-id emoji-reaction-id reaction))
reactions
new-reactions)))
@@ -84,10 +78,6 @@
(message.protocol/send-retract-reaction cofx
(update reaction :chat-id #(or % current-chat-id))))
(rf/defn receive-one
{:events [::receive-one]}
[{:keys [db]} reaction]
{:db (update db :reactions (process-reactions (:chats db)) [reaction])})
(defn message-reactions
[current-public-key reactions]
@@ -105,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])}]})
-14
View File
@@ -1,14 +0,0 @@
;;this ns is needed because of cycled deps
(ns status-im.chat.models.transport
(:require [status-im.chat.models.message :as chat.message]
[status-im.transport.message.core :as transport.message]
[utils.re-frame :as rf]))
(rf/defn chat-ui-resend-message
{:events [:chat.ui/resend-message]}
[{:keys [db] :as cofx} chat-id message-id]
(let [message (get-in db [:messages chat-id message-id])]
(rf/merge
cofx
(transport.message/set-message-envelope-hash chat-id message-id (:message-type message))
(chat.message/resend-message chat-id message-id))))
-4
View File
@@ -26,10 +26,6 @@
"/c/"
community-id))
(def featured
[{:name "Status"
:id constants/status-community-id}])
(defn <-request-to-join-community-rpc
[r]
(set/rename-keys r
+1 -2
View File
@@ -10,7 +10,6 @@
status-im.chat.models.images
status-im.chat.models.input
status-im.chat.models.loading
status-im.chat.models.transport
[status-im2.constants :as constants]
status-im.contact.block
status-im.contact.chat
@@ -37,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]
+1 -26
View File
@@ -4,8 +4,7 @@
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.message.sheets :as sheets.styles]))
[status-im.ui.components.react :as react]))
(defn hide-sheet-and-dispatch
[event]
@@ -121,29 +120,5 @@
:else [one-to-one-chat-accents chat-id]))
(defn current-chat-actions
[]
[actions @(re-frame/subscribe [:chats/current-chat])])
(defn chat-actions
[chat-id]
[actions @(re-frame/subscribe [:chat-by-id chat-id])])
(defn options
[chat-id message-id]
(fn []
[react/view
[react/i18n-text {:style sheets.styles/sheet-text :key :message-not-sent}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/resend-message)
:icon :main-icons/refresh
:accessibility-label :resend-message-button
:on-press #(hide-sheet-and-dispatch [:chat.ui/resend-message chat-id message-id])}]
[quo/list-item
{:theme :negative
:title (i18n/label :t/delete-message)
:icon :main-icons/delete
:accessibility-label :delete-transaccent-button
:on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message-not-used-any-more chat-id
message-id])}]]))
@@ -1,66 +0,0 @@
(ns status-im.ui.screens.communities.channel-details
(:require [clojure.string :as string]
[quo.core :as quo]
[status-im.communities.core :as communities]
[utils.i18n :as i18n]
[status-im.ui.components.profile-header.view :as profile-header]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [chat-id]} (rf/sub [:get-screen-params])]
(fn []
(let [current-chat (rf/sub [:chat-by-id chat-id])
{:keys [chat-name color description community-id emoji]} current-chat
{:keys [position]} (rf/sub [:chats/community-chat-by-id
community-id chat-id])
category (rf/sub [:chats/category-by-chat-id
community-id chat-id])
{:keys [admin]} (rf/sub [:communities/community
community-id])
pinned-messages (rf/sub [:chats/pinned chat-id])]
[quo/animated-header
{:left-accessories [{:icon :main-icons/arrow-left
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}]
:right-accessories (when admin
[{:icon :edit
:accessibility-label :invite-button
:on-press #(rf/dispatch [::communities/edit-channel-pressed
community-id
chat-name
description
color
emoji
chat-id
(:id category)
position])}])
:extended-header (profile-header/extended-header
{:title chat-name
:color color
:emoji emoji
:subtitle (i18n/label :t/public-channel)})
:use-insets true}
(when-not (string/blank? description)
[:<>
[quo/list-footer {:color :main}
description]
[quo/separator {:style {:margin-vertical 8}}]
(when admin
[quo/list-item
{:title (i18n/label :t/category)
:on-press #(rf/dispatch [:open-modal :select-category
{:chat current-chat
:category category
:community-id community-id}])
:chevron true
:accessory :text
:accessory-text (if category
(:name category)
(i18n/label :t/none))}])
[quo/list-item
{:title (i18n/label :t/pinned-messages)
:accessory :text
:accessory-text (count pinned-messages)
:chevron true
:on-press #(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id])}]])]))))
@@ -1,340 +0,0 @@
(ns status-im.ui.screens.communities.community
(:require
[utils.i18n :as i18n]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo2.components.community.style :as styles]
[quo2.components.navigation.floating-shell-button :as floating-shell-button]
[react-native.core :as rn]
[status-im.communities.core :as communities]
[status-im2.constants :as constants]
[status-im.react-native.resources :as resources]
[status-im.ui.components.accordion :as accordion]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.utils.core :as utils]
[utils.datetime :as datetime]
[utils.re-frame :as rf]
[status-im.ui.screens.home.views.inner-item :as inner-item]))
(def request-cooldown-ms (* 24 60 60 1000))
(defn can-request-access-again?
[requested-at]
(> (datetime/timestamp) (+ (* requested-at 1000) request-cooldown-ms)))
(defn toolbar-content
[id display-name color images show-members-count? members]
(let [thumbnail-image (get-in images [:thumbnail :uri])]
[rn/view
{:style {:flex 1
:align-items :center
:flex-direction :row}}
[rn/view {:padding-right 10}
(cond
(= id constants/status-community-id)
[rn/image
{:source (resources/get-image :status-logo)
:style {:width 40
:height 40}}]
(seq thumbnail-image)
[photos/photo thumbnail-image {:size 40}]
:else
[chat-icon.screen/chat-icon-view-toolbar
id
true
display-name
(or color (rand-nth colors/chat-colors)) nil 36])]
[rn/view {:style {:flex 1 :justify-content :center}}
[quo/text
{:number-of-lines 1
:accessibility-label :community-name-text}
display-name]
[quo/text
{:number-of-lines 1
:size :small
:color :secondary}
(if show-members-count?
(i18n/label-pluralize members :t/community-members {:count members})
(i18n/label :t/open-membership))]]]))
(defn hide-sheet-and-dispatch
[event]
(rf/dispatch [:bottom-sheet/hide-old])
(rf/dispatch event))
(defn community-plus-actions
[{:keys [id permissions can-manage-users?]}]
(let [can-invite? (and can-manage-users?
(not= (:access permissions) constants/community-no-membership-access))
can-share? (not= (:access permissions) constants/community-invitation-only-access)]
[:<>
[quo/list-item
{:theme :accent
:title (i18n/label :t/create-channel)
:accessibility-label :community-create-channel
:icon :main-icons/channel
:on-press #(hide-sheet-and-dispatch [::communities/create-channel-pressed id])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/create-category)
:accessibility-label :community-create-category
:icon :main-icons/channel-category
:on-press #(hide-sheet-and-dispatch [:open-modal :create-community-category
{:community-id id}])}]
[quo/separator]
(when can-invite?
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-people)
:icon :main-icons/share
:accessibility-label :community-invite-people
:on-press #(rf/dispatch [:communities/invite-people-pressed id])}])
(when (and can-share? (not can-invite?))
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-people)
:icon :main-icons/share
:accessibility-label :community-share
:on-press #(rf/dispatch [:communities/share-community-pressed id])}])]))
(defn community-actions
[{:keys [id name images color can-manage-users?]}]
(let [thumbnail-image (get-in images [:thumbnail :uri])]
[:<>
[quo/list-item
{:title name
:subtitle (i18n/label :t/community-info)
:on-press #(hide-sheet-and-dispatch [:navigate-to :community-management {:community-id id}])
:chevron true
:icon (cond
(= id constants/status-community-id)
[rn/image
{:source (resources/get-image :status-logo)
:style {:width 40
:height 40}}]
(seq thumbnail-image)
[photos/photo thumbnail-image {:size 40}]
:else
[chat-icon.screen/chat-icon-view-chat-sheet
name
true
name
(or color (rand-nth colors/chat-colors))])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/mark-all-read)
:accessibility-label :mark-all-read-button
:icon :main-icons/check
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-in-community-pressed id])}]
(when can-manage-users?
[:<>
[quo/list-item
{:theme :accent
:title (i18n/label :t/export-key)
:accessibility-label :community-export-key
:icon :main-icons/objects
:on-press #(hide-sheet-and-dispatch [::communities/export-pressed id])}]
[quo/separator]
[quo/list-item
{:theme :accent
:title (i18n/label :t/edit-chats)
:accessibility-label :community-edit-chats
:icon :main-icons/edit
:on-press #(hide-sheet-and-dispatch
[:open-modal :community-reorder-categories {:community-id id}])}]])]))
(defn blank-page
[text]
[rn/view
{:style {:padding 16 :flex 1 :flex-direction :row :align-items :center :justify-content :center}}
[quo/text
{:align :center
:color :secondary}
text]])
(defn community-chat-item
[{:keys [chat-id] :as home-item} _ _ _]
[inner-item/home-list-item-old
;; We want communities to behave as public chats when it comes to
;; unread indicator
(assoc home-item :public? true)
{:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:chat/navigate-to-chat chat-id])
(rf/dispatch [:search/home-filter-changed nil]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[sheets/actions home-item])}])}])
(defn categories-accordion
[community-id chats categories data]
[:<>
(for [{:keys [name id state]} categories]
^{:key (str "cat" name id)}
[:<>
[accordion/section
{:on-open #(rf/dispatch [::communities/store-category-state community-id id true])
:on-close #(rf/dispatch [::communities/store-category-state community-id id false])
:default state
:title [rn/view styles/category-item
[icons/icon :main-icons/channel-category {:color colors/gray}]
[rn/text {:style {:font-size 17 :margin-left 10 :color colors/black}} name]]
:content [:<>
(for [chat (get chats id)]
^{:key (str "chat" chat id)}
[community-chat-item chat nil nil data])]}]
[quo/separator]])])
(defn community-chat-list
[community-id categories from-chat]
(let [chats (rf/sub [:chats/sorted-categories-by-community-id community-id])]
(if (and (empty? categories) (empty? chats))
[blank-page (i18n/label :t/welcome-community-blank-message)]
[list/flat-list
{:key-fn :chat-id
:content-container-style {:padding-bottom 8}
:keyboard-should-persist-taps :always
:data (get chats "")
:render-data {:from-chat from-chat}
:render-fn community-chat-item
:header [categories-accordion community-id chats categories
{:from-chat from-chat}]
:footer [rn/view {:height 68}]}])))
(defn channel-preview-item
[{:keys [id name]}]
(let [color colors/default-community-color]
[quo/list-item
{:icon [chat-icon.screen/chat-icon-view-chat-list
id true name color false false]
:title [rn/view
{:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
[icons/icon :main-icons/tiny-group
{:color colors/black
:width 15
:height 15
:container-style {:width 15
:height 15
:margin-right 2}}]
[quo/text
{:weight :medium
:accessibility-label :chat-name-text
:ellipsize-mode :tail
:number-of-lines 1}
(utils/truncate-str name 30)]]
:title-accessibility-label :chat-name-text}]))
(defn community-channel-preview-list
[_ chats-without-id]
(let [chats (reduce-kv
(fn [acc k v]
(conj acc (assoc v :id (name k))))
[]
chats-without-id)]
[list/flat-list
{:key-fn :id
:content-container-style {:padding-vertical 8}
:keyboard-should-persist-taps :always
:data chats
:render-fn channel-preview-item}]))
(defn unknown-community
[community-id]
(let [fetching (rf/sub [:communities/fetching-community community-id])]
[:<> {:style {:flex 1}}
[topbar/topbar {:title (if fetching (i18n/label :t/fetching-community) (i18n/label :t/not-found))}]
[rn/view
{:style {:padding 16 :flex 1 :flex-direction :row :align-items :center :justify-content :center}}
[quo/button
{:on-press (when-not fetching #(rf/dispatch [:chat.ui/resolve-community-info community-id]))
:disabled fetching
:color :secondary}
(if fetching
[react/small-loading-indicator]
(i18n/label :t/fetch-community))]]]))
(defn community
[]
(let [{:keys [community-id from-chat]} (rf/sub [:get-screen-params :community])]
(fn []
(let [{:keys [id chats name images members permissions color joined
can-request-access? can-join? requested-to-join-at admin]
:as community}
(rf/sub [:communities/community community-id])
categories (rf/sub [:communities/sorted-categories community-id])]
(if community
[rn/view {:style {:flex 1}}
[topbar/topbar
{:content
[toolbar-content
id
name
color
images
(not= (:access permissions) constants/community-no-membership-access)
(count members)]
:right-accessories
(when (or admin joined)
[{:icon :main-icons/more
:accessibility-label :community-menu-button
:on-press #(rf/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[community-actions community])}])}])}]
(if joined
[community-chat-list id categories false from-chat]
[community-channel-preview-list id chats])
(when admin
[components.plus-button/plus-button-old
{:on-press #(rf/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[community-plus-actions community])}])
:accessibility-label :new-chat-button}])
(when-not joined
(cond
can-join?
[toolbar/toolbar
{:show-border? true
:center [quo/button
{:on-press #(rf/dispatch [:communities/join id])
:type :secondary}
(i18n/label :t/join)]}]
can-request-access?
(if (and (pos? requested-to-join-at)
(not (can-request-access-again? requested-to-join-at)))
[toolbar/toolbar
{:show-border? true
:left [quo/text {:color :secondary}
(i18n/label :t/membership-request-pending)]}]
[toolbar/toolbar
{:show-border? true
:center [quo/button
{:on-press #(rf/dispatch [:communities/request-to-join id])
:type :secondary}
(i18n/label :t/request-access)]}])
:else
[toolbar/toolbar
{:show-border? true
:center [quo/button
{:on-press #(rf/dispatch [:communities/join id])
:type :secondary}
(i18n/label :t/follow)]}]))
[floating-shell-button/floating-shell-button
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:label (i18n/label :t/jump-to)}}
{:position :absolute
:bottom 70}]]
[unknown-community community-id])))))
@@ -1,55 +0,0 @@
(ns status-im.ui.screens.communities.community-emoji-thumbnail-picker
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.react-native :as rn]
[status-im.communities.core :as communities]
[status-im.ui.components.emoji-thumbnail.color-picker :as color-picker]
[status-im.ui.components.emoji-thumbnail.preview :as emoji-thumbnail-preview]
[status-im.ui.components.emoji-thumbnail.styles :as styles]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.react :as react]
[utils.re-frame :as rf]))
(defn thumbnail-preview-section
[]
(let [{:keys [color emoji]} (rf/sub [:communities/create-channel])
size styles/emoji-thumbnail-preview-size]
[rn/view styles/emoji-thumbnail-preview
[emoji-thumbnail-preview/emoji-thumbnail
emoji color size]]))
(defn color-circle
[item]
(let [{:keys [color]} (rf/sub [:communities/create-channel])
item-color (:color item)
key (:key key)
color-selected? (= (string/lower-case item-color) (string/lower-case color))]
[react/touchable-opacity
{:key key
:accessibility-label :color-circle
:on-press #(rf/dispatch [::communities/create-channel-field :color item-color])}
[rn/view {:style (styles/emoji-picker-color-border item-color color-selected?)}
[rn/view {:style (styles/emoji-picker-color item-color)}]]]))
(defn update-emoji
[emoji]
(when-not (string/blank? emoji)
(rf/dispatch [::communities/create-channel-field :emoji emoji])))
(defn emoji-keyboard-section
[]
(let [{:keys [width height]} (rf/sub [:dimensions/window])
keyboard_height (if (> width height)
400
(- height styles/emoji-picker-upper-components-size))]
[rn/view {:style {:height keyboard_height} :accessibility-label :emoji-keyboard-container}
[rn/emoji-keyboard (styles/emoji-keyboard #(update-emoji (.-emoji ^js %)))]]))
(defn view
[]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[rn/scroll-view
[quo/separator]
[thumbnail-preview-section]
[color-picker/color-picker-section color-circle]
[emoji-keyboard-section]]])
@@ -8,7 +8,6 @@
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.communities.membership :as memberships]
[utils.re-frame :as rf]
[status-im.utils.image :as utils.image]
[utils.debounce :as debounce]))
@@ -151,7 +150,7 @@
(defn form
[]
(let [{:keys [name description membership editing?]} (rf/sub [:communities/create])]
(let [{:keys [name description editing?]} (rf/sub [:communities/create])]
[rn/scroll-view
{:keyboard-should-persist-taps :handled
:style {:flex 1}
@@ -189,17 +188,11 @@
[:<>
[quo/separator {:style {:margin-vertical 10}}]
[quo/list-item
{:title (i18n/label :t/membership-button)
:accessory-text (i18n/label (get-in memberships/options
[membership :title]
:t/membership-none))
:accessory :text
:on-press #(rf/dispatch [:navigate-to :community-membership])
:chevron true
:size :small}]
[quo/list-footer
(i18n/label
(get-in memberships/options [membership :description] :t/membership-none-placeholder))]])]))
{:title (i18n/label :t/membership-button)
:accessory :text
:on-press #(rf/dispatch [:navigate-to :community-membership])
:chevron true
:size :small}]])]))
(defn view
[]
@@ -1,73 +0,0 @@
(ns status-im.ui.screens.communities.create-category
(:require [clojure.string :as string]
[quo.core :as quo]
[reagent.core :as reagent]
[status-im.communities.core :as communities]
[utils.i18n :as i18n]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[utils.re-frame :as rf]
[utils.debounce :as debounce]))
(defn valid?
[category-name]
(and (not (string/blank? category-name))
(<= (count category-name) 30)))
(def selected-items (reagent/atom #{}))
(defn render-fn
[{:keys [chat-id] :as home-item}]
(let [selected (get @selected-items chat-id)
on-change (fn []
(swap! selected-items #(if selected (disj % chat-id) (conj % chat-id))))]
[react/view {:flex-direction :row :flex 1 :align-items :center}
[react/view {:padding-left 16}
[quo/checkbox
{:value selected
:on-change on-change}]]
[react/view {:flex 1}
[inner-item/home-list-item-old
(assoc home-item :public? true)
{:on-press on-change}]]]))
(defn view
[]
(let [{:keys [community-id]} (rf/sub [:get-screen-params])
category-name (reagent/atom "")
_ (reset! selected-items #{})]
(fn []
(let [chats (rf/sub [:chats/with-empty-category-by-community-id community-id])]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[react/view {:flex 1}
[react/view {:padding-horizontal 16}
[quo/text-input
{:placeholder (i18n/label :t/category-title)
:on-change-text #(reset! category-name %)
:auto-focus true}]]
[quo/separator {:style {:margin-vertical 10}}]
(when (seq chats)
[:<>
[quo/list-header (i18n/label :t/include)]
[list/flat-list
{:key-fn :chat-id
:content-container-style {:padding-vertical 8}
:keyboard-should-persist-taps :always
:data chats
:render-fn render-fn}]])]
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:disabled (not (valid? @category-name))
:type :secondary
:on-press #(debounce/dispatch-and-chill
[::communities/create-category-confirmation-pressed
community-id
@category-name
(vec @selected-items)]
3000)}
(i18n/label :t/create)]}]]))))
@@ -1,72 +0,0 @@
(ns status-im.ui.screens.communities.create-channel
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.react-native :as rn]
[status-im.communities.core :as communities]
[utils.i18n :as i18n]
[status-im.ui.components.emoji-thumbnail.preview :as emoji-thumbnail-preview]
[status-im.ui.components.emoji-thumbnail.styles :as styles]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.communities.create :as create]
[utils.re-frame :as rf]
[utils.debounce :as debounce]))
(defn valid?
[channel-name channel-description]
(and (not (string/blank? channel-name))
(not (string/blank? channel-description))
(<= (count channel-name) create/max-name-length)
(<= (count channel-description) create/max-description-length)))
(defn thumbnail
[]
(let [{:keys [color emoji]} (rf/sub [:communities/create-channel])
size styles/emoji-thumbnail-preview-size]
[rn/view styles/emoji-thumbnail-preview
[emoji-thumbnail-preview/emoji-thumbnail-touchable
emoji color size
#(rf/dispatch [:open-modal :community-emoji-thumbnail-picker nil])]]))
(defn form
[]
(let [{:keys [name description]} (rf/sub [:communities/create-channel])]
[rn/scroll-view
{:style {:flex 1}
:content-container-style {:padding-bottom 16}}
[:<>
[thumbnail]
[rn/view {:padding-horizontal 16}
[quo/text-input
{:placeholder (i18n/label :t/name-your-channel-placeholder)
:on-change-text #(rf/dispatch [::communities/create-channel-field :name %])
:default-value name
:auto-focus false}]]
[quo/separator {:style {:margin-vertical 16}}]
[rn/view {:padding-horizontal 16}
[create/countable-label
{:label (i18n/label :t/description)
:text description
:max-length create/max-description-length}]
[quo/text-input
{:placeholder (i18n/label :t/give-a-short-description-community)
:multiline true
:default-value description
:on-change-text #(rf/dispatch [::communities/create-channel-field :description %])}]]]]))
(defn view
[]
(let [{:keys [name description]} (rf/sub [:communities/create-channel])]
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[quo/separator]
[form]
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:disabled (not (valid? name description))
:type :secondary
:on-press #(debounce/dispatch-and-chill
[::communities/create-channel-confirmation-pressed]
3000)}
(i18n/label :t/create)]}]]))
@@ -1,21 +0,0 @@
(ns status-im.ui.screens.communities.edit
(:require [quo.core :as quo]
[status-im.communities.core :as communities]
[utils.i18n :as i18n]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.communities.create :as community.create]
[utils.re-frame :as rf]))
(defn edit
[]
(let [{:keys [name description]} (rf/sub [:communities/create])]
[:<>
[community.create/form]
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:disabled (not (community.create/valid? name description))
:type :secondary
:on-press #(rf/dispatch [::communities/edit-confirmation-pressed])}
(i18n/label :t/save)]}]]))
@@ -1,30 +0,0 @@
(ns status-im.ui.screens.communities.edit-channel
(:require [clojure.string :as string]
[quo.core :as quo]
[status-im.communities.core :as communities]
[utils.i18n :as i18n]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.screens.communities.create-channel :as create-channel]
[utils.re-frame :as rf]
[utils.debounce :as debounce]))
(defn valid?
[community-name]
(not (string/blank? community-name)))
(defn view
[]
(let [{:keys [name]} (rf/sub [:communities/create-channel])]
(fn []
[:<>
[create-channel/form]
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:disabled (not (valid? name))
:type :secondary
:on-press #(debounce/dispatch-and-chill
[::communities/edit-channel-confirmation-pressed]
3000)}
(i18n/label :t/save)]}]])))
@@ -1,43 +0,0 @@
(ns status-im.ui.screens.communities.icon
(:require [quo.design-system.colors :as colors]
[status-im2.constants :as constants]
[status-im.react-native.resources :as resources]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.photos :as photos]))
(defn community-icon
[{:keys [id name images color]}]
(let [color (or color (rand-nth colors/chat-colors))
thumbnail-image (get-in images [:thumbnail :uri])]
(cond
(= id constants/status-community-id)
[react/image
{:source (resources/get-image :status-logo) ;; TODO replace with real data (or remove this code)
:style {:width 40
:height 40}}]
(seq thumbnail-image)
[photos/photo {:uri thumbnail-image} {:size 40}]
:else
[chat-icon.screen/chat-icon-view-chat-list
id true name color false false])))
;; TODO (flexsurfer) reimplement with new design, its still old design, photos and chat-icon components
;; from old design
(defn community-icon-redesign
[{:keys [id name images color]} size]
(let [color (or color (rand-nth colors/chat-colors))
thumbnail-image (get-in images [:thumbnail :uri])]
(cond
(= id constants/status-community-id)
[react/image
{:source (resources/get-image :status-logo) ;; TODO replace with real data
:style {:width size
:height size}}]
(seq thumbnail-image)
[photos/photo thumbnail-image {:size size}]
:else
[chat-icon.screen/chat-icon-view-chat-list-redesign
id true name color size])))
@@ -1,127 +0,0 @@
(ns status-im.ui.screens.communities.profile
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo.react-native :as rn]
[reagent.core :as reagent]
[status-im.communities.core :as communities]
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[status-im.react-native.resources :as resources]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.profile-header.view :as profile-header]
[status-im.ui.components.react :as react]
[status-im.ui.components.unviewed-indicator :as unviewed-indicator]
[utils.re-frame :as rf]))
(defn management
[]
(let [{:keys [community-id]} (rf/sub [:get-screen-params])]
(fn []
(let [requests-to-join (rf/sub [:communities/requests-to-join-for-community community-id])
community (rf/sub [:communities/community community-id])
{:keys [color members permissions description
name admin]} community
roles false
notifications false
show-members-count? (not= (:access permissions) constants/community-no-membership-access)
request-membership? (= (:access permissions) constants/community-on-request-access)
members-count (count members)]
[:<>
[quo/animated-header
{:left-accessories [{:icon :main-icons/arrow-left
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}]
:right-accessories [{:icon :main-icons/share
:accessibility-label :invite-button
:on-press #(rf/dispatch [:communities/share-community-pressed
community-id])}]
:extended-header (profile-header/extended-header
{:title name
:color (or color (rand-nth colors/chat-colors))
:photo (if (= community-id constants/status-community-id)
(:uri
(rn/resolve-asset-source
(resources/get-image :status-logo)))
(get-in community [:images :large :uri]))
:membership (when request-membership?
(i18n/label :t/membership-approval))
:subtitle (if show-members-count?
(i18n/label-pluralize members-count
:t/community-members
{:count members-count})
(i18n/label :t/open-membership))
:community? true})
:use-insets true}
[:<>
(when-not (string/blank? description)
[:<>
[quo/list-footer {:color :main}
description]
[quo/separator {:style {:margin-vertical 8}}]])
[:<>
(let [link (communities/universal-link community-id)]
[react/view
{:padding-vertical 10
:padding-horizontal 16}
[react/view {:margin-bottom 20}
[quo/text {:color :secondary} (i18n/label :t/community-link)]]
[copyable-text/copyable-text-view
{:copied-text link}
[react/view
{:border-radius 16
:padding-horizontal 16
:padding-vertical 11
:background-color colors/blue-light}
[quo/text {:color :link} (subs link 8)]]]])
[quo/separator {:style {:margin-vertical 8}}]]
(when show-members-count?
[quo/list-item
{:chevron true
:accessory
[react/view {:flex-direction :row}
(when (pos? members-count)
[quo/text {:color :secondary} (str members-count)])
[unviewed-indicator/unviewed-indicator (count requests-to-join)]]
:on-press #(rf/dispatch [:navigate-to :community-members {:community-id community-id}])
:title (i18n/label :t/members-label)
:icon :main-icons/group-chat}])
(when (and admin roles)
[quo/list-item
{:chevron true
:title (i18n/label :t/commonuity-role)
:icon :main-icons/objects}])
(when notifications
[quo/list-item
{:chevron true
:title (i18n/label :t/chat-notification-preferences)
:icon :main-icons/notification}])
(when (or show-members-count? notifications (and admin roles))
[quo/separator {:style {:margin-vertical 8}}])
(when admin
[quo/list-item
{:theme :accent
:icon :main-icons/edit
:title (i18n/label :t/edit-community)
:on-press #(rf/dispatch [::communities/open-edit-community community-id])}])
[quo/list-item
{:theme :accent
:icon :main-icons/arrow-left
:title (i18n/label :t/leave-community)
:on-press #(rf/dispatch [:communities/leave community-id])}]
;; Disable as not implemented yet
(when false
[quo/list-item
{:theme :negative
:icon :main-icons/delete
:title (i18n/label :t/delete)
:on-press #(rf/dispatch [::communities/delete-community community-id])}])]]]))))
(defn management-container
[]
(reagent/create-class
{:display-name "community-profile-view"
:component-did-mount (fn []
(communities/fetch-requests-to-join! (get (rf/sub [:get-screen-params])
:community-id)))
:reagent-render management}))

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