Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b669db5c45 | ||
|
|
92c39f4e69 | ||
|
|
c960d6e264 | ||
|
|
7db514ba4a | ||
|
|
a94e0a8c98 | ||
|
|
d3394197a2 | ||
|
|
8ec7e07662 |
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
@@ -40,6 +40,9 @@ 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,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
@@ -61,9 +61,10 @@ pipeline {
|
||||
}
|
||||
stage('Build android jsbundle') {
|
||||
steps { script {
|
||||
/* Build/fetch deps required for jsbundle build. */
|
||||
/* build/fetch things required to produce a js-bundle for android
|
||||
* (e.g. maven and node repos) */
|
||||
nix.build(
|
||||
attr: 'targets.mobile.jsbundle',
|
||||
attr: 'targets.mobile.android.jsbundle',
|
||||
sandbox: false,
|
||||
pure: false,
|
||||
link: false
|
||||
@@ -72,7 +73,7 @@ pipeline {
|
||||
}
|
||||
stage('Build android deps') {
|
||||
steps { script {
|
||||
/* Build/fetch deps required to build android release. */
|
||||
/* build/fetch things required to build jsbundle and android */
|
||||
nix.build(
|
||||
attr: 'targets.mobile.android.release.buildInputs',
|
||||
sandbox: false,
|
||||
@@ -83,7 +84,7 @@ pipeline {
|
||||
}
|
||||
stage('Build nix shell deps') {
|
||||
steps { script {
|
||||
/* Build/fetch deps required to start default Nix shell. */
|
||||
/* build/fetch things required to instantiate shell.nix for TARGET=all */
|
||||
nix.build(
|
||||
attr: 'shells.default.buildInputs',
|
||||
sandbox: false,
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.8'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
@@ -182,6 +182,17 @@ 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.'
|
||||
@@ -245,6 +256,27 @@ 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`'
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
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
|
||||
|
||||
@@ -3,21 +3,21 @@ GEM
|
||||
specs:
|
||||
CFPropertyList (3.0.6)
|
||||
rexml
|
||||
addressable (2.8.4)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.768.0)
|
||||
aws-sdk-core (3.173.0)
|
||||
aws-partitions (1.728.0)
|
||||
aws-sdk-core (3.170.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.64.0)
|
||||
aws-sdk-kms (1.63.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.122.0)
|
||||
aws-sdk-s3 (1.119.1)
|
||||
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.7)
|
||||
fastlane (2.212.2)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.212.1)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@@ -105,8 +105,11 @@ 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.42.0)
|
||||
google-apis-androidpublisher_v3 (0.36.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
@@ -137,7 +140,7 @@ GEM
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.5.2)
|
||||
googleauth (1.3.0)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
@@ -145,6 +148,7 @@ 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)
|
||||
@@ -152,12 +156,16 @@ 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)
|
||||
@@ -167,6 +175,11 @@ 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)
|
||||
@@ -213,6 +226,8 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
fastlane (>= 2.131.0)
|
||||
fastlane-plugin-clean_testflight_testers
|
||||
fastlane-plugin-diawi
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.9
|
||||
2.4.6
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Autogenerated by fastlane
|
||||
#
|
||||
# Ensure this file is checked in to source control!
|
||||
|
||||
gem 'fastlane-plugin-clean_testflight_testers'
|
||||
gem 'fastlane-plugin-diawi'
|
||||
@@ -24,6 +24,8 @@ 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; {
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "15s8van7r2ad3dq6i03l3z4hqnvxcq75a3h72kxvf9an53sqma20";
|
||||
sha256 = "1ypdmpdn20hxp5vwxz3zc04r5xcwqc25qszdlg41h8ghdqbllwmw";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.8.4";
|
||||
version = "2.8.1";
|
||||
};
|
||||
artifactory = {
|
||||
groups = ["default"];
|
||||
@@ -45,10 +45,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1256rf6zjh3canwr636w7yczbvhh72cpz2fw5ixljbh4fcfkrvlm";
|
||||
sha256 = "0q3q19insq5ablmr6ypq033qg1gsar5mdphhp7xg80rd615cnq97";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.768.0";
|
||||
version = "1.728.0";
|
||||
};
|
||||
aws-sdk-core = {
|
||||
dependencies = ["aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath"];
|
||||
@@ -56,10 +56,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "10djgbz4k9w3axka8xrhf97h9yh9svi5g5xvncfwnkg6h22w2177";
|
||||
sha256 = "0zc4zhv2wq7s5p8c9iaplama1lpg2kwldg81j83c8w4xydf1wd2r";
|
||||
type = "gem";
|
||||
};
|
||||
version = "3.173.0";
|
||||
version = "3.170.0";
|
||||
};
|
||||
aws-sdk-kms = {
|
||||
dependencies = ["aws-sdk-core" "aws-sigv4"];
|
||||
@@ -67,10 +67,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1bcm0c9f7xy5qj5f0z3gddqslhb2vzrj9smc39pgqyq4jmn5kpj0";
|
||||
sha256 = "0v87zi28dfmrv7bv91yfldccnpd63n295siirbz7wqv1rajn8n02";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.64.0";
|
||||
version = "1.63.0";
|
||||
};
|
||||
aws-sdk-s3 = {
|
||||
dependencies = ["aws-sdk-core" "aws-sdk-kms" "aws-sigv4"];
|
||||
@@ -78,10 +78,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "01cryf8kfkmlsxb327szcwcagsp7lss5gmk6zxlgap65lv8bc7rx";
|
||||
sha256 = "1rpnlzsl52znhcki13jkwdshgwf51pn26267481f4fa842gr7xgp";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.122.0";
|
||||
version = "1.119.1";
|
||||
};
|
||||
aws-sigv4 = {
|
||||
dependencies = ["aws-eventstream"];
|
||||
@@ -357,10 +357,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1pd7pamzhdz2w0fbcvsfn2nyslznvphnwj16zw35g2b28zd2xyzx";
|
||||
sha256 = "0nnggg20za5vamdpkgrxxa32z33d8hf0g2bciswkhqnc6amb3yjr";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.2.7";
|
||||
version = "2.2.6";
|
||||
};
|
||||
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,10 +368,31 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "15sa3v3aaslympg9nmadmpxpbzykdiybzxn3navc7mf0iscb3q7s";
|
||||
sha256 = "0b22m2dkydyv2si55b1jzznzgxf2ycx2aarv1j5p25k861h2gsml";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.212.2";
|
||||
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";
|
||||
};
|
||||
gh_inspector = {
|
||||
groups = ["default"];
|
||||
@@ -389,10 +410,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "0ks2ak4fcvlflhyinykvd88g2ybxwsbc347aww349zhn1mqprbvg";
|
||||
sha256 = "1mbnmn36z1cnsd6ar76p9wvqi0ac6wlpm1p1lqczivain16qma76";
|
||||
type = "gem";
|
||||
};
|
||||
version = "0.42.0";
|
||||
version = "0.36.0";
|
||||
};
|
||||
google-apis-core = {
|
||||
dependencies = ["addressable" "googleauth" "httpclient" "mini_mime" "representable" "retriable" "rexml" "webrick"];
|
||||
@@ -487,10 +508,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1lj5haarpn7rybbq9s031zcn9ji3rlz5bk64bwa2j34q5s1h5gis";
|
||||
sha256 = "1hpwgwhk0lmnknkw8kbdfxn95qqs6aagpq815l5fkw9w6mi77pai";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.5.2";
|
||||
version = "1.3.0";
|
||||
};
|
||||
highline = {
|
||||
groups = ["default"];
|
||||
@@ -502,6 +523,16 @@
|
||||
};
|
||||
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"];
|
||||
@@ -563,6 +594,27 @@
|
||||
};
|
||||
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 = [];
|
||||
@@ -623,6 +675,16 @@
|
||||
};
|
||||
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 = [];
|
||||
@@ -684,6 +746,17 @@
|
||||
};
|
||||
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,8 +119,13 @@ public class PushNotificationHelper {
|
||||
private final BroadcastReceiver notificationActionReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction() == ACTION_DELETE_NOTIFICATION) {
|
||||
if (intent.getAction() == ACTION_TAP_NOTIFICATION ||
|
||||
intent.getAction() == ACTION_DELETE_NOTIFICATION) {
|
||||
String deepLink = intent.getExtras().getString("im.status.ethereum.deepLink");
|
||||
String groupId = intent.getExtras().getString("im.status.ethereum.groupId");
|
||||
if (intent.getAction() == ACTION_TAP_NOTIFICATION) {
|
||||
context.startActivity(getOpenAppIntent(deepLink));
|
||||
}
|
||||
if (groupId != null) {
|
||||
cleanGroup(groupId);
|
||||
}
|
||||
@@ -136,6 +141,7 @@ 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");
|
||||
@@ -695,31 +701,37 @@ public class PushNotificationHelper {
|
||||
|
||||
private StatusMessage createMessage(Bundle data) {
|
||||
Person author = getPerson(data.getBundle("notificationAuthor"));
|
||||
long timeStampLongValue = (long) data.getDouble("timestamp");
|
||||
return new StatusMessage(data.getString("id"), author, timeStampLongValue, data.getString("message"));
|
||||
return new StatusMessage(data.getString("id"), author, data.getLong("timestamp"), 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, flag);
|
||||
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||
}
|
||||
|
||||
private PendingIntent createGroupOnTapIntent(Context context, int notificationId, String groupId, String deepLink) {
|
||||
Intent intent = getOpenAppIntent(deepLink);
|
||||
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
|
||||
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);
|
||||
}
|
||||
|
||||
private PendingIntent createOnTapIntent(Context context, int notificationId, String deepLink) {
|
||||
Intent intent = getOpenAppIntent(deepLink);
|
||||
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
|
||||
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);
|
||||
}
|
||||
|
||||
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, flag);
|
||||
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||
}
|
||||
|
||||
public void removeStatusMessage(Bundle bundle) {
|
||||
|
||||
@@ -103,6 +103,45 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"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",
|
||||
@@ -975,15 +1014,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.logging/1.1.0/tools.logging-1.1.0",
|
||||
"path": "org/clojure/tools.logging/0.4.1/tools.logging-0.4.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "44b6bd9ac74cb5e2254e1f0b258d53c1829b865d",
|
||||
"sha256": "093jy29w5gm9rp9va6qlhb6096jpf5higyk7sgmbwb5nf53qi3qb"
|
||||
"sha1": "483bbfc82aee3c005bb1ad36dec77ba5d6c5f95c",
|
||||
"sha256": "1qhfigr9am90fx527ax6f7z7xahgsd5hzb4pmi40n79nx3jsc9hf"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "84cb5d00caa9df2ee504d46f6107f4708271f619",
|
||||
"sha256": "0x2zzivn38z179lxkw9wbi9n9qwsf466lrd9y27khdz7wbxhscb5"
|
||||
"sha1": "991bebc6e3633b85091ae929d62c116a2584aee7",
|
||||
"sha256": "001sx1ddgx0ys0z1qphzpxjf2w35rikrfjc0h5bvvqbw8ra0vvja"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1313,15 +1352,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "re-frame/re-frame/1.3.0/re-frame-1.3.0",
|
||||
"path": "re-frame/re-frame/0.12.0/re-frame-0.12.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "b1f70463fba018c5464d3fc0843232fe955c1372",
|
||||
"sha256": "0yqq1kg1si0akr7kx7w1l4vvkdai20na6h6627ibqkgwzivkc5n5"
|
||||
"sha1": "41fd34c15c1cf68eec81435e09d0a79fd8a88276",
|
||||
"sha256": "08c3sxi3sdkay3550vb3gbv5czzdh2kyin4mb8cpd2wd5g2c88sq"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "b7135a76432b8141027ba1f4eb6bb15a36acfb7c",
|
||||
"sha256": "16wi01z0j4wn04kldwzxvj0pd9dianjyb000nv5611ikhxk1qrps"
|
||||
"sha1": "3ff92169fe7588ad62dad2d6ea3bf0e5d3e2d224",
|
||||
"sha256": "1m5sjskgjx028s1zpa631bp52y9hjn8l1nr8hrwiwdh09i2kpnk2"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1352,15 +1391,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "reagent/reagent/1.2.0/reagent-1.2.0",
|
||||
"path": "reagent/reagent/1.0.0/reagent-1.0.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "d2279922777793edfc0ae9e01d68a832eb5ce52d",
|
||||
"sha256": "1h1gk4cykidm1jx75dq426lrgf8r7900fcir5jz59zp1ka2a0ywb"
|
||||
"sha1": "93ad5ccb0101108fb0843a3f2c50da28f8fd8336",
|
||||
"sha256": "1l4xzgc4wbd8b29mhj5j336cf8w1zccaia0w413zf3bnj6jf5m38"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "1b9a181b5c7ed3557768d2ea0c66f5616aef5e97",
|
||||
"sha256": "0scvkzfqjs613z10rngh7427v3pxdqablf0fcl65pbpkzz16wgav"
|
||||
"sha1": "a1dd4d40425bb2e1afad0fe72780b43ff394ccfa",
|
||||
"sha256": "1g607s1ymns85923bvhwrsj0y5czyqqq1jmxx0a58fnsm1b318fa"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ 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
|
||||
@@ -73,7 +76,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/1.1.0/tools.logging-1.1.0.jar
|
||||
org/clojure/tools.logging/0.4.1/tools.logging-0.4.1.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
|
||||
@@ -99,10 +102,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/1.3.0/re-frame-1.3.0.jar
|
||||
re-frame/re-frame/0.12.0/re-frame-0.12.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.2.0/reagent-1.2.0.jar
|
||||
reagent/reagent/1.0.0/reagent-1.0.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
|
||||
|
||||
@@ -32,6 +32,18 @@ in {
|
||||
# For parsing gradle.properties into an attrset
|
||||
gradlePropParser = callPackage ./tools/gradlePropParser.nix { };
|
||||
|
||||
# Clojure formatting tool
|
||||
zprint = super.zprint.override rec {
|
||||
buildGraalvmNativeImage = args: super.buildGraalvmNativeImage ( args // rec {
|
||||
inherit (args) pname;
|
||||
version = "1.2.5";
|
||||
src = self.fetchurl {
|
||||
url = "https://github.com/kkinnear/${pname}/releases/download/${version}/${pname}-filter-${version}";
|
||||
sha256 = "sha256-PWdR5jqyzvTk9HoxqDldwtZNik34dmebBtZZ5vtva4A=";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# Fix for missing libarclite_macosx.a in Xcode 14.3.
|
||||
# https://github.com/ios-control/ios-deploy/issues/580
|
||||
ios-deploy = super.darwin.ios-deploy.overrideAttrs (old: rec {
|
||||
@@ -48,8 +60,8 @@ in {
|
||||
gradle = super.gradle_6;
|
||||
nodejs = super.nodejs-18_x;
|
||||
yarn = super.yarn.override { nodejs = super.nodejs-18_x; };
|
||||
openjdk = super.openjdk11_headless;
|
||||
xcodeWrapper = super.xcodeenv.composeXcodeWrapper {
|
||||
openjdk = super.openjdk8_headless;
|
||||
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
|
||||
version = "14.0";
|
||||
allowHigher = true;
|
||||
};
|
||||
|
||||
@@ -11,10 +11,11 @@ let
|
||||
# We follow the master branch of official nixpkgs.
|
||||
nixpkgsSrc = fetchFromGitHub {
|
||||
name = "nixpkgs-source";
|
||||
owner = "NixOS";
|
||||
# FIXME: Fork used to get Cocoapods 1.12.0 and apksigner macOS build.
|
||||
owner = "status-im";
|
||||
repo = "nixpkgs";
|
||||
rev = "e7603eba51f2c7820c0a182c6bbb351181caa8e7";
|
||||
sha256 = "sha256-XJZ/o17eOd2sEsGif+/MQBnfa2DKmndWgJyc7CWajFc=";
|
||||
rev = "d0c06fa3d3982a91aa01bd63ed84020cbde3d3ab";
|
||||
sha256 = "sha256-8blvuUHnuf0hFr/PpBxVohJp5CaGXIXhgJlFN/cv7us=";
|
||||
# To get the compressed Nix sha256, use:
|
||||
# nix-prefetch-url --unpack https://github.com/${ORG}/nixpkgs/archive/${REV}.tar.gz
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# by setting android_sdk.accept_license = true.
|
||||
androidenv.composeAndroidPackages {
|
||||
toolsVersion = "26.1.1";
|
||||
platformToolsVersion = "33.0.3";
|
||||
platformToolsVersion = "33.0.2";
|
||||
buildToolsVersions = [ "30.0.0" ];
|
||||
platformVersions = [ "31" ];
|
||||
cmakeVersions = [ "3.18.1" ];
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
mkShell {
|
||||
name = "android-sdk-shell";
|
||||
buildInputs = [ openjdk ];
|
||||
shellHook = ''
|
||||
export JAVA_HOME="${openjdk}"
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
{ stdenv }:
|
||||
|
||||
{ version ? "11.1"
|
||||
, allowHigher ? false
|
||||
, xcodeBaseDir ? "/Applications/Xcode.app" }:
|
||||
|
||||
assert stdenv.isDarwin;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "xcode-wrapper-${version}${if allowHigher then "-plus" else ""}";
|
||||
# Fix 'xcodebuild: Operation not permitted' when 'sandbox=relaxed' is used.
|
||||
# https://github.com/NixOS/nixpkgs/pull/228696
|
||||
__noChroot = stdenv.isDarwin;
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin
|
||||
cd $out/bin
|
||||
ln -s /usr/bin/xcode-select
|
||||
ln -s /usr/bin/security
|
||||
ln -s /usr/bin/codesign
|
||||
ln -s /usr/bin/xcrun
|
||||
ln -s /usr/bin/plutil
|
||||
ln -s /usr/bin/clang
|
||||
ln -s /usr/bin/lipo
|
||||
ln -s /usr/bin/file
|
||||
ln -s /usr/bin/rev
|
||||
ln -s "${xcodeBaseDir}/Contents/Developer/usr/bin/xcodebuild"
|
||||
ln -s "${xcodeBaseDir}/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator"
|
||||
|
||||
cd ..
|
||||
ln -s "${xcodeBaseDir}/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
|
||||
|
||||
# Check if we have the xcodebuild version that we want
|
||||
currVer=$($out/bin/xcodebuild -version)
|
||||
${if allowHigher then ''
|
||||
if [ -z "$(printf '%s\n' "${version}" "$currVer" | sort -V | head -n1)""" != "${version}" ]
|
||||
'' else ''
|
||||
if [ -z "$(echo $currVer | grep -x 'Xcode ${version}')" ]
|
||||
''}
|
||||
then
|
||||
echo "We require xcodebuild version${if allowHigher then " or higher" else ""}: ${version}"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
}
|
||||
@@ -20,7 +20,7 @@ in mkShell {
|
||||
# lint specific utilities
|
||||
clj-kondo zprint
|
||||
# other nice to have stuff
|
||||
yarn nodejs python310
|
||||
yarn nodejs python27
|
||||
] # and some special cases
|
||||
++ lib.optionals stdenv.isDarwin [ cocoapods clang tcl ]
|
||||
++ lib.optionals (!stdenv.isDarwin) [ gcc8 ]
|
||||
|
||||
@@ -57,7 +57,7 @@ let
|
||||
|
||||
# for 'scripts/generate-keystore.sh'
|
||||
keytool = mkShell {
|
||||
buildInputs = with pkgs; [ openjdk apksigner ];
|
||||
buildInputs = with pkgs; [ openjdk8 apksigner ];
|
||||
};
|
||||
|
||||
# for targets needing 'adb', 'apkanalyzer' and other SDK/NDK tools
|
||||
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1011 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,119 +0,0 @@
|
||||
#!/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()
|
||||
@@ -1,8 +1,8 @@
|
||||
;; shadow-cljs configuration
|
||||
{:source-paths ["src" "test/cljs"]
|
||||
|
||||
:dependencies [[reagent "1.2.0"]
|
||||
[re-frame "1.3.0"]
|
||||
:dependencies [[reagent "1.0.0"]
|
||||
[re-frame "0.12.0"]
|
||||
[binaryage/oops "0.7.0"]
|
||||
[com.andrewmcveigh/cljs-time "0.5.2"]
|
||||
[status-im/timbre "4.10.0-2-status"]
|
||||
|
||||
@@ -220,10 +220,10 @@
|
||||
only icon
|
||||
[button {:icon true} :i/close-circle]"
|
||||
[_ _]
|
||||
(let [pressed-in (reagent/atom false)]
|
||||
(let [pressed (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size before after above icon-secondary-no-color
|
||||
width customization-color override-theme override-background-color pressed
|
||||
[{:keys [on-press disabled type size before after above
|
||||
width customization-color override-theme override-background-color
|
||||
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
|
||||
(or @pressed-in pressed) :pressed
|
||||
:else :default)
|
||||
state (cond disabled :disabled
|
||||
@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-in true)
|
||||
:on-press-out #(reset! pressed-in nil)}
|
||||
:on-press-in #(reset! pressed true)
|
||||
:on-press-out #(reset! pressed nil)}
|
||||
(when on-press
|
||||
{:on-press on-press})
|
||||
(when on-long-press
|
||||
@@ -306,6 +306,5 @@
|
||||
[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,8 +68,7 @@
|
||||
:on-press-out #(reset! pressed? false)
|
||||
:on-press on-press
|
||||
:active-opacity 1
|
||||
:hit-slop {:top 5 :bottom 5 :left 5 :right 5}
|
||||
:pointer-events :auto
|
||||
:style {:padding 5}
|
||||
:accessibility-label type}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
(case type
|
||||
:words
|
||||
[rn/flat-list
|
||||
{:keyboard-should-persist-taps :always
|
||||
:data words
|
||||
{:data words
|
||||
:content-container-style style/word-list
|
||||
:render-fn word-component
|
||||
:render-data {:blur? blur?
|
||||
|
||||
@@ -1,62 +1,53 @@
|
||||
(ns quo2.components.drawers.action-drawers.component-spec
|
||||
(:require [quo2.components.drawers.action-drawers.view :as action-drawer]
|
||||
[test-helpers.component :as h]))
|
||||
(:require ["@testing-library/react-native" :as rtl]
|
||||
[quo2.components.drawers.action-drawers.view :as action-drawer]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(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")))
|
||||
(defn render-action-drawer
|
||||
([options]
|
||||
(rtl/render (reagent/as-element [action-drawer/action-drawer options]))))
|
||||
|
||||
(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 label displaying"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample 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 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 "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 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/fire-event :press (h/get-by-text label-friend))
|
||||
(h/was-not-called on-press-friend)))
|
||||
(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/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"))))
|
||||
(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))))
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
:flex-direction :row})
|
||||
|
||||
(defn container
|
||||
[sub-label disabled?]
|
||||
[sub-label]
|
||||
{:border-radius 12
|
||||
:height (if sub-label 58 50)
|
||||
:opacity (when disabled? 0.3)
|
||||
:margin-horizontal 8})
|
||||
|
||||
(defn row-container
|
||||
|
||||
@@ -18,19 +18,12 @@
|
||||
:accessible true
|
||||
:accessibility-label :divider}])
|
||||
|
||||
(defn- maybe-pressable
|
||||
[disabled? props child]
|
||||
(if disabled?
|
||||
[rn/view (dissoc props :on-press) child]
|
||||
[rn/touchable-highlight props child]))
|
||||
|
||||
(defn- action
|
||||
(defn action
|
||||
[{:keys [icon
|
||||
label
|
||||
sub-label
|
||||
right-icon
|
||||
danger?
|
||||
disabled?
|
||||
on-press
|
||||
add-divider?
|
||||
override-theme
|
||||
@@ -40,9 +33,9 @@
|
||||
[:<> {:key label}
|
||||
(when add-divider?
|
||||
[divider])
|
||||
[maybe-pressable disabled?
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label accessibility-label
|
||||
:style (style/container sub-label disabled?)
|
||||
:style (style/container sub-label)
|
||||
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90 override-theme)
|
||||
:on-press on-press}
|
||||
[rn/view
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
(ns quo2.components.drawers.drawer-buttons.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def outer-container
|
||||
{:height 216
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20
|
||||
:overflow :hidden})
|
||||
{:height 216
|
||||
:border-radius 20})
|
||||
|
||||
(def top-card
|
||||
{:flex 1
|
||||
@@ -13,7 +12,9 @@
|
||||
:padding-horizontal 20
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20
|
||||
:background-color colors/neutral-80-opa-80-blur})
|
||||
:background-color (if platform/ios?
|
||||
colors/neutral-80-opa-80-blur
|
||||
colors/neutral-80)})
|
||||
|
||||
(def bottom-card
|
||||
{:position :absolute
|
||||
@@ -32,11 +33,11 @@
|
||||
:justify-content :space-between})
|
||||
|
||||
(def bottom-icon
|
||||
{:border-radius 32
|
||||
{:border-radius 40
|
||||
:border-width 1
|
||||
:margin-left 24
|
||||
:height 32
|
||||
:width 32
|
||||
:height 28
|
||||
:width 28
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color colors/white-opa-5})
|
||||
@@ -51,4 +52,4 @@
|
||||
(defn heading-text
|
||||
[gap]
|
||||
{:color colors/white
|
||||
:margin-bottom gap})
|
||||
:margin-bottom gap})
|
||||
|
||||
@@ -71,28 +71,14 @@
|
||||
child-2 string, keyword or hiccup
|
||||
"
|
||||
[{:keys [container-style top-card bottom-card]} child-1 child-2]
|
||||
[rn/view
|
||||
[blur/ios-view
|
||||
{:style (merge container-style style/outer-container)}
|
||||
[blur/view
|
||||
{:blur-type :dark
|
||||
:blur-amount 10
|
||||
:style {:flex 1
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20}}]
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:background-color :transparent
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0}}
|
||||
[card
|
||||
(merge {:gap 4
|
||||
:top? true
|
||||
:style style/top-card}
|
||||
top-card) child-1]
|
||||
[card
|
||||
(merge {:style style/bottom-card
|
||||
:gap 20}
|
||||
bottom-card) child-2]]])
|
||||
[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]])
|
||||
|
||||
@@ -1,14 +1,165 @@
|
||||
(ns quo2.components.dropdowns.dropdown
|
||||
(:require [quo2.components.buttons.button :as button]))
|
||||
(: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}]]]))
|
||||
|
||||
(defn dropdown
|
||||
[_ _]
|
||||
(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]))
|
||||
[params]
|
||||
[:f> f-dropdown params])
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
(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))
|
||||
@@ -1,50 +0,0 @@
|
||||
(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,9 +28,8 @@
|
||||
(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-current-word #(>= (count %) 5)
|
||||
:error-pred-written-words #(>= (count %) 5)}
|
||||
{:mark-errors? true
|
||||
:error-pred #(>= (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,27 +15,15 @@
|
||||
text])
|
||||
|
||||
(defn- mark-error-words
|
||||
[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)))
|
||||
[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 #" "))))
|
||||
|
||||
(defn recovery-phrase-input
|
||||
[_ _]
|
||||
@@ -43,11 +31,9 @@
|
||||
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-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)}
|
||||
error-pred word-limit]
|
||||
:or {customization-color :blue
|
||||
error-pred (constantly false)}
|
||||
:as props}
|
||||
text]
|
||||
(let [extra-props (apply dissoc props custom-props)]
|
||||
@@ -67,5 +53,5 @@
|
||||
(when on-blur (on-blur)))}
|
||||
extra-props)
|
||||
(if mark-errors?
|
||||
(mark-error-words error-pred-current-word error-pred-written-words text word-limit)
|
||||
(mark-error-words error-pred text word-limit)
|
||||
text)]]))))
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
:default-value default-value
|
||||
:accessibility-label :profile-title-input
|
||||
:keyboard-appearance (theme/theme-value :light :dark override-theme)
|
||||
:on-focus #(swap! focused? (constantly true))
|
||||
:on-blur #(swap! focused? (constantly false))
|
||||
:on-focus #(swap! focused? (fn [] true))
|
||||
:on-blur #(swap! focused? (fn [] false))
|
||||
:input-mode :text
|
||||
:on-change-text on-change
|
||||
:editable (not disabled?)
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
: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
|
||||
@@ -31,14 +27,14 @@
|
||||
original-style)]
|
||||
[reanimated/view {:style animated-style}
|
||||
;; Left Section
|
||||
[section
|
||||
[rn/view {:style {:flex 1}}
|
||||
[dynamic-button-view :search dynamic-buttons
|
||||
{:position :absolute
|
||||
:right 8}]]
|
||||
;; Mid Section (jump-to)
|
||||
[dynamic-button-view :jump-to dynamic-buttons nil]
|
||||
;; Right Section
|
||||
[section
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:flex-direction :row
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(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]
|
||||
@@ -14,7 +13,7 @@
|
||||
{:on-press on-press
|
||||
:accessibility-label :emoji-reaction-add
|
||||
:style (style/add-reaction)}
|
||||
[icons/icon :i/add-reaction
|
||||
[icons/icon :i/add
|
||||
{:size 20
|
||||
:color (if dark?
|
||||
colors/white
|
||||
@@ -22,17 +21,15 @@
|
||||
|
||||
(defn reaction
|
||||
"Add your emoji as a param here"
|
||||
[{:keys [emoji clicks neutral? on-press accessibility-label on-long-press]}]
|
||||
[{:keys [emoji clicks neutral? on-press accessibility-label]}]
|
||||
(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?)}
|
||||
[rn/image
|
||||
{:style {:width 16 :height 16}
|
||||
:accessibility-label :emoji
|
||||
:source (resource/get-reaction emoji)}]
|
||||
[icons/icon emoji
|
||||
{:no-color true
|
||||
:size 16}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
(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)))
|
||||
@@ -1,12 +0,0 @@
|
||||
(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)))
|
||||
@@ -1,23 +0,0 @@
|
||||
(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)))))
|
||||
@@ -1,11 +0,0 @@
|
||||
(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))})
|
||||
@@ -1,25 +0,0 @@
|
||||
(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}}]]])))
|
||||
@@ -6,8 +6,7 @@
|
||||
[react-native.masked-view :as masked-view]
|
||||
[reagent.core :as reagent]
|
||||
[utils.collection :as utils.collection]
|
||||
[utils.number :as utils.number]
|
||||
[react-native.gesture :as gesture]))
|
||||
[utils.number :as utils.number]))
|
||||
|
||||
(def default-tab-size 32)
|
||||
(def unread-count-offset 3)
|
||||
@@ -132,8 +131,7 @@
|
||||
style
|
||||
size
|
||||
blur?
|
||||
override-theme
|
||||
in-scroll-view?]
|
||||
override-theme]
|
||||
:or {fade-end-percentage fade-end-percentage
|
||||
fade-end? false
|
||||
scrollable? false
|
||||
@@ -144,9 +142,7 @@
|
||||
[rn/view {:style {:margin-top (- (dec unread-count-offset))}}
|
||||
[masked-view-wrapper
|
||||
{:fade-end-percentage (get @fading :fade-end-percentage) :fade-end? fade-end?}
|
||||
[(if in-scroll-view?
|
||||
gesture/flat-list
|
||||
rn/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? (nil? photo)
|
||||
empty-photo? (empty? photo)
|
||||
avatar-size :xxs
|
||||
avatar-outer-size (get-in user-avatar-style/sizes [avatar-size :outer])]
|
||||
[rn/view {:flex-direction :row}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
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
|
||||
@@ -65,7 +64,6 @@
|
||||
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
|
||||
@@ -112,9 +110,6 @@
|
||||
(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)
|
||||
@@ -169,9 +164,6 @@
|
||||
(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)
|
||||
|
||||
@@ -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,7 +30,6 @@
|
||||
[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]))
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
|
||||
;;Solid
|
||||
(def black "#000000")
|
||||
(def black-opa-0 (alpha black 0))
|
||||
(def onboarding-header-black "#000716")
|
||||
|
||||
;;;;Primary
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
(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" %))))
|
||||
@@ -17,7 +17,6 @@
|
||||
(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)))
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
[flat-list
|
||||
(merge props
|
||||
{:data data
|
||||
:render-fn (fn [p1 p2 p3 p4]
|
||||
(if (:header? p1)
|
||||
[render-section-header-fn p1 p2 p3 p4]
|
||||
[render-fn p1 p2 p3 p4]))})]))
|
||||
:render-fn (fn [item]
|
||||
(if (:header? item)
|
||||
(render-section-header-fn item)
|
||||
(render-fn item)))})]))
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
[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]))
|
||||
|
||||
@@ -28,7 +30,13 @@
|
||||
(merge keycard/more-sheet)
|
||||
|
||||
(= view :learn-more)
|
||||
(merge about-app/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))]
|
||||
|
||||
[:f>
|
||||
(fn []
|
||||
|
||||
@@ -1,17 +1,47 @@
|
||||
(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]
|
||||
[react-native.permissions :as permissions]
|
||||
[status-im.ui.components.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
|
||||
@@ -48,6 +78,108 @@
|
||||
#(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]
|
||||
@@ -57,17 +189,81 @@
|
||||
(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]
|
||||
@@ -75,3 +271,25 @@
|
||||
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})
|
||||
|
||||
@@ -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]} on-loaded]
|
||||
[{db :db} chat-id session-id {:keys [cursor messages]}]
|
||||
(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,8 +141,6 @@
|
||||
[: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 %)))
|
||||
@@ -163,7 +161,7 @@
|
||||
|
||||
(rf/defn load-more-messages
|
||||
{:events [:chat.ui/load-more-messages]}
|
||||
[{:keys [db]} chat-id first-request on-loaded]
|
||||
[{:keys [db]} chat-id first-request]
|
||||
(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?]))
|
||||
@@ -177,13 +175,13 @@
|
||||
chat-id
|
||||
cursor
|
||||
constants/default-number-of-messages
|
||||
#(re-frame/dispatch [::messages-loaded chat-id session-id % on-loaded])
|
||||
#(re-frame/dispatch [::messages-loaded chat-id session-id %])
|
||||
#(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} on-loaded]
|
||||
(load-more-messages cofx (:current-chat-id db) false on-loaded))
|
||||
[{:keys [db] :as cofx}]
|
||||
(load-more-messages cofx (:current-chat-id db) false))
|
||||
|
||||
(rf/defn load-messages
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
@@ -193,4 +191,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 nil))))
|
||||
(load-more-messages chat-id true))))
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
[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]
|
||||
[utils.transforms :as transforms]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn update-reaction
|
||||
[acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
|
||||
@@ -16,7 +15,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
|
||||
@@ -24,7 +23,14 @@
|
||||
(fn [acc
|
||||
{:keys [chat-id message-id emoji-id emoji-reaction-id retracted]
|
||||
:as reaction}]
|
||||
(update-reaction acc retracted chat-id message-id emoji-id emoji-reaction-id 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)))
|
||||
reactions
|
||||
new-reactions)))
|
||||
|
||||
@@ -78,6 +84,10 @@
|
||||
(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]
|
||||
@@ -95,42 +105,3 @@
|
||||
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])}]})
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
;;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))))
|
||||
@@ -26,6 +26,10 @@
|
||||
"/c/"
|
||||
community-id))
|
||||
|
||||
(def featured
|
||||
[{:name "Status"
|
||||
:id constants/status-community-id}])
|
||||
|
||||
(defn <-request-to-join-community-rpc
|
||||
[r]
|
||||
(set/rename-keys r
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
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
|
||||
@@ -36,7 +37,7 @@
|
||||
status-im.signals.core
|
||||
status-im.stickers.core
|
||||
status-im.transport.core
|
||||
[react-native.permissions :as permissions]
|
||||
[status-im.ui.components.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]
|
||||
|
||||
@@ -165,15 +165,6 @@
|
||||
(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]}]
|
||||
@@ -303,7 +294,7 @@
|
||||
(re-frame/reg-fx
|
||||
;;TODO: this could be replaced by a single API call on status-go side
|
||||
::initialize-wallet
|
||||
(fn [[network-id network callback]]
|
||||
(fn [[network-id callback]]
|
||||
(-> (js/Promise.all
|
||||
(clj->js
|
||||
[(js/Promise.
|
||||
@@ -311,31 +302,12 @@
|
||||
(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 (fn [_]
|
||||
(resolve nil))})))
|
||||
:on-error #(resolve nil)})))
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "wallet_getCustomTokens"
|
||||
@@ -346,7 +318,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)
|
||||
@@ -393,27 +365,22 @@
|
||||
(rf/defn redirect-to-root
|
||||
"Decides which root should be initialised depending on user and app state"
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pairing-completed? (= (get-in db [:syncing :pairing-status]) :completed)]
|
||||
(cond
|
||||
pairing-completed?
|
||||
{:db (dissoc db :syncing)
|
||||
:dispatch [:init-root :syncing-results]}
|
||||
(cond
|
||||
(get db :onboarding-2/new-account?)
|
||||
{:dispatch [:onboarding-2/finalize-setup]}
|
||||
|
||||
(get db :onboarding-2/new-account?)
|
||||
{:dispatch [:onboarding-2/finalize-setup]}
|
||||
(get db :tos/accepted?)
|
||||
(rf/merge
|
||||
cofx
|
||||
(multiaccounts/switch-theme nil :shell-stack)
|
||||
(navigation/init-root :shell-stack))
|
||||
|
||||
(get db :tos/accepted?)
|
||||
(rf/merge
|
||||
cofx
|
||||
(multiaccounts/switch-theme nil :shell-stack)
|
||||
(navigation/init-root :shell-stack))
|
||||
|
||||
:else
|
||||
{:dispatch [:init-root :tos]})))
|
||||
:else
|
||||
{:dispatch [:init-root :tos]}))
|
||||
|
||||
(rf/defn get-settings-callback
|
||||
{:events [::get-settings-callback]}
|
||||
[{:keys [db] :as cofx} settings]
|
||||
[{:keys [db] :as cofx} settings pairing-in-progress?]
|
||||
(let [{:networks/keys [current-network networks]
|
||||
:as settings}
|
||||
(data-store.settings/rpc->settings settings)
|
||||
@@ -445,7 +412,8 @@
|
||||
(activity-center/notifications-fetch-pending-contact-requests)
|
||||
(activity-center/update-seen-state)
|
||||
(activity-center/notifications-fetch-unread-count)
|
||||
(redirect-to-root))))
|
||||
(when-not pairing-in-progress?
|
||||
(redirect-to-root)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::open-last-chat
|
||||
@@ -481,7 +449,6 @@
|
||||
[{: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?
|
||||
@@ -493,7 +460,6 @@
|
||||
: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]))]
|
||||
@@ -524,8 +490,9 @@
|
||||
|
||||
(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?)]
|
||||
(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?])]
|
||||
(log/debug "[login] login-only-events"
|
||||
"auth-method" auth-method
|
||||
"new-auth-method" new-auth-method)
|
||||
@@ -533,7 +500,7 @@
|
||||
{:db (assoc db :chats/loading? true)
|
||||
:json-rpc/call
|
||||
[{:method "settings_getSettings"
|
||||
:on-success #(re-frame/dispatch [::get-settings-callback %])}]}
|
||||
:on-success #(re-frame/dispatch [::get-settings-callback % pairing-in-progress?])}]}
|
||||
(notifications/load-notification-preferences)
|
||||
(when save-password?
|
||||
(keychain/save-user-password key-uid password))
|
||||
|
||||
@@ -89,9 +89,8 @@
|
||||
{:events [:chat.ui/show-profile]}
|
||||
[{:keys [db]} identity ens-name]
|
||||
(let [my-public-key (get-in db [:multiaccount :public-key])]
|
||||
(if (not= my-public-key identity)
|
||||
(when (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 [:navigate-to :my-profile]})))
|
||||
:dispatch [:contacts/build-contact identity ens-name true]})))
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
[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-im2.constants :as constants]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]))
|
||||
|
||||
(rf/defn status-node-started
|
||||
[{db :db :as cofx} {:keys [error]}]
|
||||
@@ -55,49 +56,36 @@
|
||||
:peers-count (count (:peers peer-stats)))}))
|
||||
|
||||
(rf/defn handle-local-pairing-signals
|
||||
[{:keys [db] :as cofx} {:keys [type action data] :as event}]
|
||||
[{:keys [db] :as cofx} event]
|
||||
(log/info "local pairing signal received"
|
||||
{:event 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
|
||||
(let [connection-success? (and (= (:type event)
|
||||
constants/local-pairing-event-connection-success)
|
||||
(= action
|
||||
(= (:action event)
|
||||
constants/local-pairing-action-connect))
|
||||
error-on-pairing? (contains? constants/local-pairing-event-errors type)
|
||||
completed-pairing? (and (= type
|
||||
error-on-pairing? (contains? constants/local-pairing-event-errors (:type event))
|
||||
completed-pairing? (and (= (:type event)
|
||||
constants/local-pairing-event-transfer-success)
|
||||
(= action
|
||||
(= (:action event)
|
||||
constants/local-pairing-action-pairing-installation))
|
||||
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?)
|
||||
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?))
|
||||
user-in-syncing-devices-screen? (= (:view-id db) :syncing-progress)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
(assoc-in [:syncing :pairing-status] :connected)
|
||||
|
||||
received-account?
|
||||
(assoc-in [:syncing :multiaccount] multiaccount-data)
|
||||
(assoc-in [:syncing :pairing-in-progress?] :connected)
|
||||
|
||||
error-on-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :error)
|
||||
(assoc-in [:syncing :pairing-in-progress?] :error)
|
||||
|
||||
completed-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :completed))}
|
||||
(assoc-in [:syncing :pairing-in-progress?] :completed))}
|
||||
(when (and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||
{:dispatch [:navigate-to :syncing-progress]})
|
||||
(when (and completed-pairing? sender?)
|
||||
{:dispatch [:syncing/clear-states]})
|
||||
(when (and completed-pairing? receiver?)
|
||||
{:dispatch [:multiaccounts.login/local-paired-user]}))))
|
||||
(when completed-pairing?
|
||||
{:dispatch [:syncing/pairing-completed]}))))
|
||||
|
||||
(rf/defn process
|
||||
{:events [:signals/signal-received]}
|
||||
|
||||
@@ -219,10 +219,9 @@
|
||||
(rf/defn update-estimated-gas-success
|
||||
{:events [:signing/update-estimated-gas-success]}
|
||||
[{db :db} gas]
|
||||
(when (contains? db :signing/tx)
|
||||
{:db (-> db
|
||||
(assoc-in [:signing/tx :gas] gas)
|
||||
(assoc-in [:signing/edit-fee :gas-loading?] false))}))
|
||||
{: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]}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
(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)))))
|
||||
@@ -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]
|
||||
[react-native.permissions :as components.permissions]
|
||||
[status-im.ui.components.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]
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
[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.components.react :as react]
|
||||
[status-im.ui.screens.chat.styles.message.sheets :as sheets.styles]))
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
@@ -120,5 +121,29 @@
|
||||
|
||||
: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])}]]))
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
(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])}]])]))))
|
||||
@@ -0,0 +1,340 @@
|
||||
(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])))))
|
||||