Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6221b42f2a |
@@ -5,6 +5,7 @@ project-board:
|
||||
min-reviewers: 1
|
||||
tested-pr-label-name: 'Tested - Issues'
|
||||
contributor-column-name: 'CONTRIBUTOR'
|
||||
to-rebase-column-name: 'TO REBASE'
|
||||
review-column-name: 'REVIEW'
|
||||
test-column-name: 'E2E Tests'
|
||||
|
||||
|
||||
@@ -218,18 +218,23 @@ release-android: keystore build-android ##@build Build signed Android APK
|
||||
|
||||
release-ios: export TARGET := ios
|
||||
release-ios: export BUILD_ENV ?= prod
|
||||
release-ios: watchman-clean ios-clean jsbundle ##@build Build release for iOS release
|
||||
xcodebuild \
|
||||
-scheme StatusIm \
|
||||
-configuration Release \
|
||||
-workspace ios/StatusIm.xcworkspace \
|
||||
-destination 'generic/platform=iOS' \
|
||||
-UseModernBuildSystem=N clean archive
|
||||
release-ios: watchman-clean ##@build Build release for iOS release
|
||||
@git clean -dxf -f target/ios && \
|
||||
$(MAKE) jsbundle-ios && \
|
||||
xcodebuild -workspace ios/StatusIm.xcworkspace -scheme StatusIm -configuration Release -destination 'generic/platform=iOS' -UseModernBuildSystem=N clean archive
|
||||
|
||||
jsbundle: SHELL := /bin/sh
|
||||
jsbundle: export BUILD_ENV ?= prod
|
||||
jsbundle: ##@build Build JavaScript and Clojurescript bundle for iOS and Android
|
||||
nix/scripts/build.sh targets.mobile.jsbundle
|
||||
jsbundle-android: SHELL := /bin/sh
|
||||
jsbundle-android: export TARGET := android
|
||||
jsbundle-android: export BUILD_ENV ?= prod
|
||||
jsbundle-android: ##@jsbundle Compile JavaScript and Clojurescript into app directory
|
||||
# Call nix-build to build the 'targets.mobile.android.jsbundle' attribute and copy the.js files to the project root
|
||||
nix/scripts/build.sh targets.mobile.android.jsbundle && \
|
||||
mv result/*.js ./
|
||||
|
||||
jsbundle-ios: export TARGET := ios
|
||||
jsbundle-ios: export BUILD_ENV ?= prod
|
||||
jsbundle-ios: ##@jsbundle Compile JavaScript and Clojure into index.ios.js
|
||||
yarn shadow-cljs release mobile
|
||||
|
||||
#--------------
|
||||
# status-go lib
|
||||
@@ -360,7 +365,6 @@ component-test: ##@test Run component tests once in NodeJS
|
||||
yarn shadow-cljs compile component-test && \
|
||||
jest --config=test/jest/jest.config.js
|
||||
|
||||
#--------------
|
||||
# Other
|
||||
#--------------
|
||||
|
||||
@@ -369,10 +373,6 @@ geth-connect: ##@other Connect to Geth on the device
|
||||
adb forward tcp:8545 tcp:8545 && \
|
||||
build/bin/geth attach http://localhost:8545
|
||||
|
||||
ios-clean: SHELL := /bin/sh
|
||||
ios-clean: ##@prepare Clean iOS build artifacts
|
||||
git clean -dxf -f target/ios
|
||||
|
||||
android-clean: export TARGET := gradle
|
||||
android-clean: ##@prepare Clean Gradle state
|
||||
git clean -dxf -f ./android/app/build; \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
@@ -49,6 +49,7 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
utils.doGitRebasePR()
|
||||
utils.symlinkEnv()
|
||||
println("Build Number: ${utils.genBuildNumber()}")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
@@ -48,6 +48,7 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
utils.doGitRebasePR()
|
||||
utils.symlinkEnv()
|
||||
println("Build Number: ${utils.genBuildNumber()}")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
@@ -41,6 +41,13 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
utils.doGitRebasePR()
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Checks') {
|
||||
parallel {
|
||||
stage('Lint') {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.7.9'
|
||||
library 'status-jenkins-lib@v1.7.3'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
@@ -365,43 +365,6 @@ dispatch.
|
||||
(str "Hello " username)]])
|
||||
```
|
||||
|
||||
### Registering effects
|
||||
|
||||
When registering re-frame effects (`reg-fx`), prefer to expose a data-only
|
||||
interface because that will allow event handlers to stay pure.
|
||||
|
||||
For instance, if an effect needs a `on-success` callback, allow it to receive a
|
||||
*re-frame event vector*. This approach is used by us in the [json-rpc/call
|
||||
effect](src/status_im2/common/json_rpc/events.cljs), but also by third-party
|
||||
effects, such as https://github.com/Day8/re-frame-http-fx. For the complete
|
||||
rationale, see [PR #15936](https://github.com/status-im/status-mobile/pull/15936).
|
||||
|
||||
### Using the effect `:json-rpc/call`
|
||||
|
||||
Prefer the pure version of `:json-rpc/call` (no callbacks).
|
||||
|
||||
```clojure
|
||||
;; not as good
|
||||
(rf/defn accept-contact-request
|
||||
{:events [:activity-center.contact-requests/accept]}
|
||||
[_ contact-id]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id contact-id}]
|
||||
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(rf/dispatch [:activity-center.contact-requests/accept-error contact-id %])}]})
|
||||
|
||||
;; better
|
||||
(rf/defn accept-contact-request
|
||||
{:events [:activity-center.contact-requests/accept]}
|
||||
[_ contact-id]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id contact-id}]
|
||||
:on-success [:sanitize-messages-and-process-response]
|
||||
:on-error [:activity-center.contact-requests/accept-error contact-id]}]})
|
||||
```
|
||||
|
||||
### Registering event handlers
|
||||
|
||||
Events must always be declared with the `utils.fx/defn` macro. Also, don't use
|
||||
|
||||
@@ -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.'
|
||||
@@ -254,6 +265,18 @@ platform :ios do
|
||||
# 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`'
|
||||
|
||||
@@ -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.766.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)
|
||||
@@ -66,7 +66,7 @@ GEM
|
||||
faraday_middleware (1.2.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.212.2)
|
||||
fastlane (2.212.1)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@@ -106,8 +106,10 @@ GEM
|
||||
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)
|
||||
@@ -138,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)
|
||||
@@ -146,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)
|
||||
@@ -153,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)
|
||||
@@ -168,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)
|
||||
@@ -215,6 +227,7 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
fastlane (>= 2.131.0)
|
||||
fastlane-plugin-clean_testflight_testers
|
||||
fastlane-plugin-diawi
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.9
|
||||
2.4.6
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
# Ensure this file is checked in to source control!
|
||||
|
||||
gem 'fastlane-plugin-clean_testflight_testers'
|
||||
gem 'fastlane-plugin-diawi'
|
||||
|
||||
@@ -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 = "0x7v4v8hj0pbzw3x1iv07x8v93fcs74svlhzv7vl6laxm4mc6858";
|
||||
sha256 = "0q3q19insq5ablmr6ypq033qg1gsar5mdphhp7xg80rd615cnq97";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.766.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"];
|
||||
@@ -368,10 +368,10 @@
|
||||
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"];
|
||||
@@ -383,6 +383,17 @@
|
||||
};
|
||||
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"];
|
||||
platforms = [];
|
||||
@@ -399,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"];
|
||||
@@ -497,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"];
|
||||
@@ -512,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"];
|
||||
@@ -573,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 = [];
|
||||
@@ -633,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 = [];
|
||||
@@ -694,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 = [];
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
import "node-libs-react-native/globals";
|
||||
import "./result/index.js";
|
||||
import "./app/index.js";
|
||||
|
||||
@@ -55,12 +55,12 @@ The [`nix/scripts/shell.sh`](./scripts/shell.sh) script is essentially a wrapper
|
||||
|
||||
# Building
|
||||
|
||||
We will use the `make jsbundle` target as an example of a derivation you can build using Nix:
|
||||
We will use the `make jsbundle-android` target as an example of a derivation you can build using Nix:
|
||||
|
||||
1. `make jsbundle` is called by developer
|
||||
2. `make` calls `nix/scripts/build.sh targets.mobile.jsbundle`
|
||||
3. [`build.sh`](/nix/scripts/build.sh) calls `nix-build --attr targets.mobile.jsbundle` with extra arguments
|
||||
4. `nix-build` builds the derivation from [`nix/mobile/jsbundle/default.nix`](/nix/mobile/jsbundle/default.nix)
|
||||
1. `make jsbundle-android` is called by developer
|
||||
2. `make` calls `nix/scripts/build.sh targets.mobile.android.jsbundle`
|
||||
3. [`build.sh`](/nix/scripts/build.sh) calls `nix-build --attr targets.mobile.android.jsbundle` with extra arguments
|
||||
4. `nix-build` builds the derivation from [`nix/mobile/android/jsbundle/default.nix`](/nix/mobile/android/jsbundle/default.nix)
|
||||
|
||||
The same can be done for other targets like `targets.mobile.android.release`.
|
||||
Except in that case extra arguments are required which is why the [`scripts/release-android.sh`](/scripts/release-android.sh) is used in the `make release-android` target.
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
{ pkgs, deps, callPackage, mkShell
|
||||
, jsbundle, status-go, androidPkgs, androidShell }:
|
||||
, status-go, androidPkgs, androidShell }:
|
||||
|
||||
rec {
|
||||
release = callPackage ./release.nix {
|
||||
inherit jsbundle status-go;
|
||||
};
|
||||
let
|
||||
# Import a jsbundle compiled out of clojure codebase
|
||||
jsbundle = callPackage ./jsbundle { };
|
||||
|
||||
release = callPackage ./release.nix { inherit jsbundle status-go; };
|
||||
in {
|
||||
# TARGETS
|
||||
inherit release jsbundle;
|
||||
|
||||
shell = mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
{ secretsFile ? "" }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "status-mobile-jsbundle";
|
||||
name = "status-mobile-build-jsbundle-android";
|
||||
src =
|
||||
let path = ./../../..;
|
||||
let path = ./../../../..;
|
||||
# We use builtins.path so that we can name the resulting derivation,
|
||||
# otherwise the name would be taken from the checkout directory,
|
||||
# which is outside of our control inherit path;
|
||||
@@ -25,7 +25,7 @@ stdenv.mkDerivation {
|
||||
ignoreVCS = false;
|
||||
include = [
|
||||
"VERSION" "BUILD_NUMBER" "scripts/version/.*"
|
||||
"src/.*" "shadow-cljs.edn"
|
||||
"src/.*" "shadow-cljs.edn" "index.js"
|
||||
# I want to avoid including the whole .git directory
|
||||
".git/HEAD" ".git/objects" ".git/refs/heads/.*"
|
||||
# shadow-cljs expects these for deps resolution
|
||||
@@ -77,6 +77,6 @@ stdenv.mkDerivation {
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r result/* $out/
|
||||
cp -r index.js app $out/
|
||||
'';
|
||||
}
|
||||
@@ -46,7 +46,7 @@ in stdenv.mkDerivation rec {
|
||||
root = path;
|
||||
include = [
|
||||
"package.json" "yarn.lock" "metro.config.js" "babel.config.js"
|
||||
"resources/.*" "translations/.*" "src/js/.*" "index.js"
|
||||
"resources/.*" "translations/.*" "src/js/.*"
|
||||
"modules/react-native-status/android.*" "android/.*"
|
||||
envFileName "VERSION" "status-go-version.json" "react-native.config.js"
|
||||
];
|
||||
@@ -94,10 +94,8 @@ in stdenv.mkDerivation rec {
|
||||
# Export all vars from .env file
|
||||
export $(cut -d= -f1 .env)
|
||||
|
||||
# Symlink React Native entrypoint.
|
||||
cp -Lr ${builtJsBundle} ./result
|
||||
pwd
|
||||
find -L result
|
||||
# Copy index.js and app/ input files
|
||||
cp -ra --no-preserve=ownership ${builtJsBundle}/* ./
|
||||
|
||||
# Copy android/ directory
|
||||
mkdir -p ./android/build
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
let
|
||||
fastlane = callPackage ./fastlane { };
|
||||
|
||||
jsbundle = callPackage ./jsbundle { };
|
||||
|
||||
android = callPackage ./android {
|
||||
inherit jsbundle;
|
||||
status-go = status-go.mobile.android;
|
||||
};
|
||||
|
||||
@@ -29,5 +26,5 @@ in {
|
||||
};
|
||||
|
||||
# TARGETS
|
||||
inherit android ios fastlane jsbundle;
|
||||
inherit android ios fastlane;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.3-status",
|
||||
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.0",
|
||||
"@react-native-community/clipboard": "^1.2.2",
|
||||
"@react-native-community/hooks": "^3.0.0",
|
||||
"@react-native-community/hooks": "^2.5.1",
|
||||
"@react-native-community/masked-view": "^0.1.6",
|
||||
"@react-native-community/netinfo": "^4.4.0",
|
||||
"@react-native-community/push-notification-ios": "^1.4.1",
|
||||
|
||||
|
Before Width: | Height: | Size: 838 B After Width: | Height: | Size: 944 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 784 B After Width: | Height: | Size: 692 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 685 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 834 B After Width: | Height: | Size: 771 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 880 B After Width: | Height: | Size: 744 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1017 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 745 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 868 B After Width: | Height: | Size: 801 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 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()
|
||||
@@ -37,8 +37,7 @@
|
||||
:builds
|
||||
{:mobile
|
||||
{:target :react-native
|
||||
;; To match the folder created by Nix build of JSBundle.
|
||||
:output-dir "result"
|
||||
:output-dir "app"
|
||||
:init-fn status-im2.core/init
|
||||
;; When false, the Shadow-CLJS watcher won't automatically refresh
|
||||
;; the target files (a.k.a hot reload). When false, you can manually
|
||||
@@ -54,13 +53,8 @@
|
||||
;; @testing-library/react-native.
|
||||
test-helpers.component]}
|
||||
:closure-defines
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"}
|
||||
:compiler-options {:output-feature-set :es5
|
||||
:closure-defines
|
||||
{re-frame.trace/trace-enabled? true}
|
||||
@@ -73,13 +67,8 @@
|
||||
:chunks {:fleets status-im.fleet.default-fleet/default-fleets}
|
||||
:release
|
||||
{:closure-defines
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"}
|
||||
:compiler-options {:output-feature-set :es6
|
||||
;;disable for android build as there
|
||||
;;is an intermittent warning with deftype
|
||||
@@ -106,13 +95,8 @@
|
||||
:ui-driven
|
||||
true
|
||||
:closure-defines
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im2.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im2.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"}
|
||||
:compiler-options
|
||||
{;; needed because we override require and it
|
||||
;; messes with source-map which reports callstack
|
||||
|
||||
@@ -57,18 +57,10 @@
|
||||
(def initials-avatar-text
|
||||
{:color colors/white-opa-70})
|
||||
|
||||
(defn inner-dot
|
||||
[size online?]
|
||||
(let [background (if online? colors/success-50 colors/neutral-40)
|
||||
dimensions (get-in sizes [size :status-indicator])]
|
||||
{:width (- dimensions 4)
|
||||
:height (- dimensions 4)
|
||||
:border-radius (- dimensions 4)
|
||||
:background-color background}))
|
||||
|
||||
(defn dot
|
||||
[size ring?]
|
||||
(let [dimensions (get-in sizes [size :status-indicator])
|
||||
[size online? ring?]
|
||||
(let [background (if online? colors/success-50 colors/neutral-40)
|
||||
dimensions (get-in sizes [size :status-indicator])
|
||||
border-width (get-in sizes [size :status-indicator-border])
|
||||
right (case size
|
||||
:big 2
|
||||
@@ -81,13 +73,11 @@
|
||||
:small -2
|
||||
0)]
|
||||
{:position :absolute
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:bottom bottom
|
||||
:right right
|
||||
:width dimensions
|
||||
:height dimensions
|
||||
:border-width border-width
|
||||
:border-radius dimensions
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-100)
|
||||
:border-color (colors/theme-colors colors/white colors/neutral-100)}))
|
||||
:border-color (colors/theme-colors colors/white colors/neutral-100)
|
||||
:background-color background}))
|
||||
|
||||
@@ -38,22 +38,18 @@
|
||||
uses `ring-background` to display the ring behind the initials when given. Otherwise,
|
||||
shows the `profile-picture` which already comes with the ring drawn."
|
||||
[{:keys [full-name status-indicator? online? size profile-picture ring-background
|
||||
customization-color static?]
|
||||
customization-color]
|
||||
:or {status-indicator? true
|
||||
online? true
|
||||
size :big
|
||||
customization-color :turquoise}}]
|
||||
(let [full-name (or full-name "empty name")
|
||||
draw-ring? (and ring-background (valid-ring-sizes size))
|
||||
outer-styles (style/outer size)
|
||||
;; Once image is loaded, fast image rerenders view with the help of reagent atom,
|
||||
;; But dynamic updates don't work when user-avatar is used inside hole-view
|
||||
;; https://github.com/status-im/status-mobile/issues/15553
|
||||
image-view (if static? rn/image fast-image/fast-image)]
|
||||
outer-styles (style/outer size)]
|
||||
[rn/view {:style outer-styles :accessibility-label :user-avatar}
|
||||
;; The `profile-picture` already has the ring in it
|
||||
(when-let [image (or profile-picture ring-background)]
|
||||
[image-view
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label (if draw-ring? :ring-background :profile-picture)
|
||||
:style outer-styles
|
||||
:source image}])
|
||||
@@ -66,7 +62,4 @@
|
||||
(when status-indicator?
|
||||
[rn/view
|
||||
{:accessibility-label :status-indicator
|
||||
:style (style/dot size draw-ring?)}
|
||||
[rn/view
|
||||
{:accessibility-label :inner-status-indicator-dot
|
||||
:style (style/inner-dot size online?)}]])]))
|
||||
:style (style/dot size online? draw-ring?)}])]))
|
||||
|
||||
@@ -8,142 +8,134 @@
|
||||
|
||||
(defn themes
|
||||
[customization-color]
|
||||
{:light
|
||||
{:primary {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 50)
|
||||
:pressed (colors/custom-color customization-color 60)
|
||||
:disabled (colors/custom-color customization-color 50)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-40
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-20
|
||||
:disabled colors/neutral-10}}
|
||||
:dark-grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-30
|
||||
:disabled colors/neutral-20}}
|
||||
:outline {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-30
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-30}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:pressed colors/neutral-10}}
|
||||
:danger {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-50
|
||||
:pressed colors/danger-60
|
||||
:disabled colors/danger-50}}
|
||||
:positive {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-50
|
||||
:pressed colors/success-60
|
||||
:disabled colors/success-50-opa-30}}
|
||||
:photo-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/white-opa-40
|
||||
:pressed colors/white-opa-50
|
||||
:disabled colors/white-opa-40}}
|
||||
:blur-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-80-opa-5
|
||||
:pressed colors/neutral-80-opa-10
|
||||
:disabled colors/neutral-80-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-80-opa-10
|
||||
:pressed colors/neutral-80-opa-20
|
||||
:disabled colors/neutral-80-opa-10}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95
|
||||
:pressed colors/neutral-95
|
||||
:disabled colors/neutral-95}}}
|
||||
:dark
|
||||
{:primary {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 60)
|
||||
:pressed (colors/custom-color customization-color 50)
|
||||
:disabled (colors/custom-color customization-color 60)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-30
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-90
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-90}}
|
||||
:dark-grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:outline {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:ghost {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:pressed colors/neutral-80}}
|
||||
:danger {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-60
|
||||
:pressed colors/danger-50
|
||||
:disabled colors/danger-60}}
|
||||
:positive {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-60
|
||||
:pressed colors/success-50
|
||||
:disabled colors/success-60-opa-30}}
|
||||
:photo-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-30
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80-opa-40
|
||||
:pressed colors/neutral-80-opa-50
|
||||
:disabled colors/neutral-80-opa-40}}
|
||||
:blur-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/white-opa-5
|
||||
:pressed colors/white-opa-10
|
||||
:disabled colors/white-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/white-opa-10
|
||||
:pressed colors/white-opa-20
|
||||
:disabled colors/white-opa-5}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95}}}})
|
||||
{:light {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 50)
|
||||
:pressed (colors/custom-color customization-color 60)
|
||||
:disabled (colors/custom-color customization-color 50)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-40
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-20
|
||||
:disabled colors/neutral-10}}
|
||||
:dark-grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-30
|
||||
:disabled colors/neutral-20}}
|
||||
:outline {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-30
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-30}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:pressed colors/neutral-10}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-50
|
||||
:pressed colors/danger-60
|
||||
:disabled colors/danger-50}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-50
|
||||
:pressed colors/success-60
|
||||
:disabled colors/success-50-opa-30}}
|
||||
:photo-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/white-opa-40
|
||||
:pressed colors/white-opa-50
|
||||
:disabled colors/white-opa-40}}
|
||||
:blur-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-80-opa-5
|
||||
:pressed colors/neutral-80-opa-10
|
||||
:disabled colors/neutral-80-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-80-opa-10
|
||||
:pressed colors/neutral-80-opa-20
|
||||
:disabled colors/neutral-80-opa-10}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95
|
||||
:pressed colors/neutral-95
|
||||
:disabled colors/neutral-95}}}
|
||||
:dark {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 60)
|
||||
:pressed (colors/custom-color customization-color 50)
|
||||
:disabled (colors/custom-color customization-color 60)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-30
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-80}}
|
||||
:dark-grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:outline {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:ghost {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:pressed colors/neutral-80}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-60
|
||||
:pressed colors/danger-50
|
||||
:disabled colors/danger-60}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-60
|
||||
:pressed colors/success-50
|
||||
:disabled colors/success-60-opa-30}}
|
||||
:photo-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-30
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80-opa-40
|
||||
:pressed colors/neutral-80-opa-50
|
||||
:disabled colors/neutral-80-opa-40}}
|
||||
:blur-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/white-opa-5
|
||||
:pressed colors/white-opa-10
|
||||
:disabled colors/white-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/white-opa-10
|
||||
:pressed colors/white-opa-20
|
||||
:disabled colors/white-opa-5}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95}}}})
|
||||
|
||||
(defn shape-style-container
|
||||
[type icon size]
|
||||
@@ -204,13 +196,17 @@
|
||||
(when disabled
|
||||
{:opacity 0.3})))
|
||||
|
||||
(defn community-themed?
|
||||
[type community-color]
|
||||
(and (= type :community) (string? community-color)))
|
||||
|
||||
(defn button
|
||||
"with label
|
||||
[button opts \"label\"]
|
||||
opts
|
||||
{:type :primary/:secondary/:grey/:dark-grey/:outline/:ghost/
|
||||
:danger/:photo-bg/:blur-bg/:blur-bg-outline/:shell/:community
|
||||
:size 40 [default] /32/24
|
||||
:size 40/32/24
|
||||
:icon true/false
|
||||
:community-color '#FFFFFF'
|
||||
:community-text-color '#000000'
|
||||
@@ -222,8 +218,9 @@
|
||||
[_ _]
|
||||
(let [pressed (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size before after above
|
||||
width customization-color override-theme override-background-color
|
||||
[{:keys [on-press disabled type size community-color community-text-color 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
|
||||
@@ -242,13 +239,18 @@
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label
|
||||
:on-press-in #(reset! pressed true)
|
||||
:on-press-out #(reset! pressed nil)}
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press on-press})
|
||||
{:on-press (fn []
|
||||
(on-press))})
|
||||
(when on-long-press
|
||||
{:on-long-press on-long-press}))
|
||||
{:on-long-press (fn []
|
||||
(on-long-press))})
|
||||
{:on-press-in (fn []
|
||||
(reset! pressed true))}
|
||||
{:on-press-out (fn []
|
||||
(reset! pressed nil))})
|
||||
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(shape-style-container type icon size)
|
||||
@@ -267,7 +269,11 @@
|
||||
width
|
||||
before
|
||||
after)
|
||||
(when (= state :pressed) {:opacity 0.9})
|
||||
(when
|
||||
(community-themed? type community-color)
|
||||
(merge
|
||||
{:background-color community-color}
|
||||
(when (= state :pressed) {:opacity 0.9})))
|
||||
inner-style)}
|
||||
(when above
|
||||
[rn/view
|
||||
@@ -295,7 +301,12 @@
|
||||
{:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color label-color}}
|
||||
:style {:color (if
|
||||
(and
|
||||
(community-themed? type community-color)
|
||||
(string? community-text-color))
|
||||
community-text-color
|
||||
label-color)}}
|
||||
|
||||
children]
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
(ns quo2.components.community.banner.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn community-card
|
||||
[radius]
|
||||
{:shadow-offset {:width 0
|
||||
:height 2}
|
||||
:shadow-radius radius
|
||||
:shadow-opacity 1
|
||||
:shadow-color colors/shadow
|
||||
:elevation 1
|
||||
:border-radius radius
|
||||
:justify-content :space-between
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(def banner-content
|
||||
{:flex 1
|
||||
:padding-top 8
|
||||
:padding-bottom 8
|
||||
:border-radius 12})
|
||||
|
||||
(def banner-title
|
||||
{:flex 1
|
||||
:padding-horizontal 12})
|
||||
|
||||
(def banner-card
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:margin-vertical 8
|
||||
:height 56
|
||||
:padding-right 12})
|
||||
|
||||
(def discover-illustration
|
||||
{:position :absolute
|
||||
:top -4
|
||||
:right 0})
|
||||
@@ -1,46 +0,0 @@
|
||||
(ns quo2.components.community.banner.view
|
||||
(:require [quo2.components.community.banner.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- card-title-and-description
|
||||
[title description]
|
||||
[rn/view
|
||||
{:style style/banner-content}
|
||||
[rn/view
|
||||
{:style style/banner-title}
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
title]
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
description]]])
|
||||
|
||||
(defn view
|
||||
[{:keys [title description on-press accessibility-label banner]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view
|
||||
(merge (style/community-card 16)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)}
|
||||
style/banner-card)
|
||||
[card-title-and-description title description]
|
||||
[rn/image
|
||||
{:style style/discover-illustration
|
||||
:source banner
|
||||
:accessibility-label :discover-communities-illustration}]]])
|
||||
@@ -0,0 +1,108 @@
|
||||
(ns quo2.components.community.discover-card
|
||||
(:require [quo2.components.community.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
;; Discover card placeholders images.
|
||||
;; TODO replaced when real data is available
|
||||
(def images
|
||||
{:images [{:id 1 :column-images [{:id 1 :image ""}]}
|
||||
{:id 2 :column-images [{}]}]})
|
||||
|
||||
(defn card-title-and-description
|
||||
[title description]
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:padding-top 8
|
||||
:padding-bottom 8
|
||||
:border-radius 12}
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:padding-horizontal 12}
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
title]
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
description]]])
|
||||
|
||||
(defn placeholder-list-images
|
||||
[{:keys [images width height border-radius]}]
|
||||
[rn/view
|
||||
[rn/view {:justify-content :center}
|
||||
(for [{:keys [id]} images]
|
||||
^{:key id}
|
||||
[rn/view
|
||||
{:border-radius border-radius
|
||||
:margin-top 4
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])]])
|
||||
|
||||
(defn placeholder-row-images
|
||||
[{:keys [first-image last-image images width height
|
||||
border-radius]}]
|
||||
[rn/view
|
||||
(when first-image
|
||||
[rn/view
|
||||
{:border-bottom-right-radius 6
|
||||
:border-bottom-left-radius 6
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])
|
||||
(when images
|
||||
[placeholder-list-images
|
||||
{:images images
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 6}])
|
||||
(when last-image
|
||||
[rn/view
|
||||
{:border-top-left-radius border-radius
|
||||
:border-top-right-radius 6
|
||||
:margin-top 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])])
|
||||
|
||||
(defn discover-card
|
||||
[{:keys [title description on-press accessibility-label]}]
|
||||
(let [on-joined-images (get images :images)]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view
|
||||
(merge (style/community-card 16)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)}
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:margin-vertical 8
|
||||
:height 56
|
||||
:padding-right 12})
|
||||
[card-title-and-description title description]
|
||||
(for [{:keys [id column-images]} on-joined-images]
|
||||
^{:key id}
|
||||
[placeholder-row-images
|
||||
{:images (when (= id 1)
|
||||
column-images)
|
||||
:width 32
|
||||
:height (if (= id 1) 8 26)
|
||||
:border-radius 6
|
||||
:first-image "" ; TODO replace with real data
|
||||
:last-image ""}])]])) ; TODO replace with real data
|
||||
@@ -112,39 +112,3 @@
|
||||
{:position :absolute
|
||||
:top 8
|
||||
:right 8})
|
||||
|
||||
(def token-tag-spacing
|
||||
{:margin-top 10
|
||||
:margin-right 8})
|
||||
|
||||
(defn token-row
|
||||
[padding?]
|
||||
(merge
|
||||
{:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:align-items :center}
|
||||
(when padding?
|
||||
{:padding-horizontal 12})))
|
||||
|
||||
(def token-row-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-bottom 12})
|
||||
|
||||
(defn token-row-or-text
|
||||
[padding?]
|
||||
(merge
|
||||
{:margin-top 4
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)}
|
||||
(when padding?
|
||||
{:padding-left 12})))
|
||||
|
||||
(defn token-row-or-border
|
||||
[]
|
||||
{:height 1
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-20
|
||||
colors/neutral-80)})
|
||||
|
||||
|
||||
@@ -1,45 +1,295 @@
|
||||
(ns quo2.components.community.token-gating
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
(:require [quo2.components.avatars.channel-avatar :as channel-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.info.information-box :as information-box]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.tags.token-tag :as token-tag]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[utils.i18n :as i18n]
|
||||
[clojure.string :as string]
|
||||
[quo2.components.community.style :as style]))
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private token-tag-horizontal-spacing 7)
|
||||
(def token-tag-vertical-spacing 5)
|
||||
|
||||
(def styles
|
||||
{:container {:flex 1
|
||||
:padding-horizontal 20}
|
||||
:header-container {:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-spacing-community {:margin-bottom 16}
|
||||
:header-spacing-channel {:margin-bottom 24}
|
||||
:header-avatar {:margin-right 8}
|
||||
:header-community-avatar-image {:width 32 :height 32}
|
||||
:header-title-container {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-title-lock {:margin-left 6}
|
||||
:header-info-button {:margin-left 8}
|
||||
:token-requirement-text-spacing {:margin-vertical 8}
|
||||
:token-requirement-list-spacing {:padding-vertical (- 8 token-tag-vertical-spacing)}
|
||||
:token-row {:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:align-items :center}
|
||||
:token-row-container {:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-horizontal (- token-tag-horizontal-spacing)}
|
||||
:token-row-container-no-shift {:margin-left 0}
|
||||
:token-row-or-text {:margin-right 3}
|
||||
:token-tag-spacing {:margin-horizontal token-tag-horizontal-spacing
|
||||
:margin-vertical token-tag-vertical-spacing}
|
||||
:divider {:height 1
|
||||
:margin-horizontal -20
|
||||
:margin-top (- 12 token-tag-vertical-spacing)
|
||||
:margin-bottom 8}
|
||||
:membership-request-denied {:margin-top 13}
|
||||
:enter-button {:margin-top 16}
|
||||
:info-text {:margin-top 12
|
||||
:text-align :center
|
||||
:padding-horizontal 20}})
|
||||
|
||||
(defn multiple-token-requirements?
|
||||
[token-requirement-lists]
|
||||
(when (vector? (first token-requirement-lists))
|
||||
(> (count token-requirement-lists) 1)))
|
||||
|
||||
(defn is-token-requirement-met?
|
||||
[token-requirement-list]
|
||||
(and (seq token-requirement-list)
|
||||
(every?
|
||||
(fn [token]
|
||||
(get token :is-sufficient?))
|
||||
token-requirement-list)))
|
||||
|
||||
(defn are-multiple-token-requirements-met?
|
||||
[token-requirement-lists]
|
||||
(if (multiple-token-requirements? token-requirement-lists)
|
||||
(some is-token-requirement-met? token-requirement-lists)
|
||||
(is-token-requirement-met? token-requirement-lists)))
|
||||
|
||||
(defn token-requirement-list-row
|
||||
[tokens padding?]
|
||||
[tokens community-color]
|
||||
[rn/view
|
||||
{:style (style/token-row padding?)}
|
||||
(doall
|
||||
(map-indexed (fn [token-index token]
|
||||
(let [{:keys [img-src symbol amount sufficient? purchasable? loading?]} token]
|
||||
^{:key token-index}
|
||||
[rn/view {:style style/token-tag-spacing}
|
||||
[token-tag/token-tag
|
||||
{:symbol symbol
|
||||
:value amount
|
||||
:size 24
|
||||
:sufficient? sufficient?
|
||||
:purchasable purchasable?
|
||||
:loading? loading?
|
||||
:img-src img-src}]]))
|
||||
tokens))])
|
||||
{:style (merge
|
||||
(get styles :token-row)
|
||||
(get styles :token-requirement-list-spacing))}
|
||||
(map-indexed (fn [token-index token]
|
||||
(let [{:keys [token-img-src token amount is-sufficient? is-purchasable?]} token]
|
||||
^{:key token-index}
|
||||
[rn/view {:style (get styles :token-tag-spacing)}
|
||||
[token-tag/token-tag
|
||||
{:token token
|
||||
:value amount
|
||||
:size 24
|
||||
:border-color community-color
|
||||
:is-required is-sufficient?
|
||||
:is-purchasable is-purchasable?
|
||||
:token-img-src token-img-src}]]))
|
||||
tokens)])
|
||||
|
||||
(defn token-requirement-list
|
||||
[{:keys [tokens padding?]}]
|
||||
[:<>
|
||||
(if (> (count tokens) 1)
|
||||
(doall
|
||||
(map-indexed
|
||||
(fn [token-requirement-index tokens]
|
||||
^{:key token-requirement-index}
|
||||
[rn/view {:margin-bottom 12}
|
||||
(when-not (= token-requirement-index 0)
|
||||
[rn/view {:style (style/token-row-or-border)}])
|
||||
(when-not (= token-requirement-index 0)
|
||||
[props community-color]
|
||||
(let [{:keys [gate token-requirements-changed?
|
||||
required-tokens-lost?]} props
|
||||
[gate-type token-requirement-lists] gate
|
||||
multiple-token-requirements? (multiple-token-requirements? token-requirement-lists)
|
||||
is-sufficient? (are-multiple-token-requirements-met?
|
||||
token-requirement-lists)
|
||||
you-must-hold-label (if (= gate-type :join)
|
||||
(cond
|
||||
token-requirements-changed? :t/you-must-now-hold
|
||||
required-tokens-lost? :t/you-must-always-hold
|
||||
:else :t/you-must-hold)
|
||||
:t/you-must-hold)
|
||||
message-label (cond
|
||||
(= gate-type :join)
|
||||
(cond
|
||||
token-requirements-changed?
|
||||
:t/community-join-requirements-changed
|
||||
required-tokens-lost?
|
||||
:t/community-join-requirements-tokens-lost
|
||||
:else (if is-sufficient?
|
||||
:t/community-join-requirements-met
|
||||
:t/community-join-requirements-not-met))
|
||||
(= gate-type :read)
|
||||
(if is-sufficient?
|
||||
:t/community-channel-read-requirements-met
|
||||
:t/community-channel-read-requirements-not-met)
|
||||
(= gate-type :write)
|
||||
(if is-sufficient?
|
||||
:t/community-channel-write-requirements-met
|
||||
:t/community-channel-write-requirements-not-met))]
|
||||
[rn/view
|
||||
[rn/view {:style (get styles :token-requirement-text-spacing)}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:number-of-lines 1}
|
||||
(i18n/label
|
||||
message-label)]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
(i18n/label
|
||||
you-must-hold-label)]]
|
||||
|
||||
(if multiple-token-requirements?
|
||||
(map-indexed
|
||||
(fn [token-requirement-index tokens]
|
||||
^{:key token-requirement-index}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :token-row-container)
|
||||
(when-not (= token-requirement-index 0)
|
||||
(get styles :token-row-container-no-shift)))}
|
||||
(when-not (= token-requirement-index 0)
|
||||
[text/text
|
||||
{:style (get styles :token-row-or-text)
|
||||
:size :paragraph-2} "or"])
|
||||
[token-requirement-list-row tokens community-color]])
|
||||
token-requirement-lists)
|
||||
[rn/view {:style (get styles :token-row-container)}
|
||||
[token-requirement-list-row token-requirement-lists community-color]])]))
|
||||
|
||||
(defn is-community-locked?
|
||||
[community]
|
||||
(not (are-multiple-token-requirements-met? (get-in community [:gates :join]))))
|
||||
|
||||
(defn is-channel-locked?
|
||||
[channel]
|
||||
(not (are-multiple-token-requirements-met?
|
||||
(or (get-in channel [:gates :read])
|
||||
(get-in channel [:gates :write])))))
|
||||
|
||||
(defn token-gating
|
||||
"[token-gating opts]
|
||||
opts
|
||||
{
|
||||
:community {
|
||||
:name string
|
||||
:community-avatar-img-src string
|
||||
:community-color string
|
||||
:community-text-color string
|
||||
:token-requirements-changed? boolean
|
||||
:required-tokens-lost? boolean
|
||||
}
|
||||
:channel {
|
||||
:name string
|
||||
:emoji string
|
||||
:emoji-background-color :string
|
||||
:on-enter-channel callback
|
||||
:membership-request-denied? boolean
|
||||
}
|
||||
}"
|
||||
[_ _]
|
||||
(fn [{:keys [community channel]}]
|
||||
(let [type (if (some? community) :community :channel)
|
||||
{:keys [name
|
||||
emoji
|
||||
emoji-background-color
|
||||
on-enter-channel
|
||||
community-avatar-img-src
|
||||
community-color
|
||||
community-text-color
|
||||
membership-request-denied?
|
||||
token-requirements-changed?
|
||||
required-tokens-lost?
|
||||
gates]}
|
||||
(if (= type :community) community channel)
|
||||
locked? (if
|
||||
(= type :community)
|
||||
(is-community-locked? community)
|
||||
(is-channel-locked? channel))]
|
||||
|
||||
[rn/view
|
||||
{:style (merge (get styles :container)
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-90)})}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :header-container)
|
||||
(if
|
||||
(= type :community)
|
||||
(get styles :header-spacing-community)
|
||||
(get styles :header-spacing-channel)))}
|
||||
|
||||
[rn/view {:style (get styles :header-avatar)}
|
||||
(if (= type :community)
|
||||
[fast-image/fast-image
|
||||
{:source community-avatar-img-src
|
||||
:style (get styles :header-community-avatar-image)}]
|
||||
|
||||
[channel-avatar/channel-avatar
|
||||
{:big? true
|
||||
:locked? locked?
|
||||
:emoji emoji
|
||||
:emoji-background-color emoji-background-color}])]
|
||||
|
||||
[rn/view {:style (get styles :header-title-container)}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:size :heading-1
|
||||
:style (get styles :header-text)} (if (= type :community) name (str "# " name))]
|
||||
|
||||
(when (= type :community)
|
||||
[icon/icon
|
||||
(if locked?
|
||||
:main-icons2/locked
|
||||
:main-icons2/unlocked)
|
||||
{:container-style (get styles :header-title-lock)
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)}])]
|
||||
|
||||
[button/button
|
||||
{:type :outline
|
||||
:size 32
|
||||
:icon true
|
||||
:style (get styles :header-info-button)} :main-icons2/info]]
|
||||
|
||||
(map-indexed (fn [gate-index gate]
|
||||
^{:key gate-index}
|
||||
[:<>
|
||||
(when-not (= gate-index 0)
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :divider)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-80)})}])
|
||||
[token-requirement-list
|
||||
{:gate gate
|
||||
:token-requirements-changed? token-requirements-changed?
|
||||
:required-tokens-lost? required-tokens-lost?} community-color]])
|
||||
gates)
|
||||
|
||||
(when (= type :channel)
|
||||
(if membership-request-denied?
|
||||
[information-box/information-box
|
||||
{:type :error
|
||||
:icon :main-icons2/untrustworthy
|
||||
:no-icon-color? true
|
||||
:style (get styles :membership-request-denied)}
|
||||
(i18n/label
|
||||
:t/membership-request-denied)]
|
||||
|
||||
[:<>
|
||||
[button/button
|
||||
{:type :community
|
||||
:community-color community-color
|
||||
:community-text-color community-text-color
|
||||
:style (get styles :enter-button)
|
||||
:disabled locked?
|
||||
:on-press on-enter-channel}
|
||||
(str "# "
|
||||
(i18n/label
|
||||
:t/enter-channel))]
|
||||
[text/text
|
||||
{:style (style/token-row-or-text padding?)
|
||||
:size :label} (string/lower-case (i18n/label :t/or))])
|
||||
[token-requirement-list-row tokens padding?]])
|
||||
tokens))
|
||||
[token-requirement-list-row (first tokens) padding?])])
|
||||
{:size :paragraph-2
|
||||
:style (merge
|
||||
(get styles :info-text)
|
||||
{:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)})}
|
||||
(i18n/label
|
||||
:t/community-enter-channel-info)]]))])))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(ns quo2.components.drawers.action-drawers.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn divider
|
||||
[]
|
||||
(def divider
|
||||
{:border-top-width 1
|
||||
:border-top-color (colors/theme-colors colors/neutral-10 colors/neutral-90)
|
||||
:border-top-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-90)
|
||||
:margin-top 8
|
||||
:margin-bottom 7
|
||||
:align-items :center
|
||||
|
||||
@@ -8,13 +8,12 @@
|
||||
(defn- get-icon-color
|
||||
[danger? override-theme]
|
||||
(if danger?
|
||||
colors/danger-60
|
||||
colors/danger-50
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 override-theme)))
|
||||
|
||||
(defn divider
|
||||
[]
|
||||
(def divider
|
||||
[rn/view
|
||||
{:style (style/divider)
|
||||
{:style style/divider
|
||||
:accessible true
|
||||
:accessibility-label :divider}])
|
||||
|
||||
@@ -31,8 +30,7 @@
|
||||
:as action-props}]
|
||||
(when action-props
|
||||
[:<> {:key label}
|
||||
(when add-divider?
|
||||
[divider])
|
||||
(when add-divider? divider)
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label accessibility-label
|
||||
:style (style/container sub-label)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{:label (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 override-theme)
|
||||
:icon (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 override-theme)
|
||||
:button-border (colors/theme-colors colors/neutral-80-opa-30 colors/white-opa-10 override-theme)
|
||||
:password-icon (colors/theme-colors colors/neutral-100 colors/white-opa-70 override-theme)
|
||||
:password-icon (colors/theme-colors colors/neutral-100 colors/white override-theme)
|
||||
:clear-icon (colors/theme-colors colors/neutral-80-opa-30 colors/white-opa-10 override-theme)
|
||||
:cursor (colors/theme-colors (colors/custom-color :blue 50)
|
||||
colors/white
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
[quo2.components.inputs.input.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.theme :as theme]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- label-&-counter
|
||||
[{:keys [label current-chars char-limit variant-colors]}]
|
||||
@@ -101,7 +100,6 @@
|
||||
(cond-> {:style (style/input colors-by-status small? @multiple-lines?)
|
||||
:accessibility-label :input
|
||||
:placeholder-text-color (:placeholder colors-by-status)
|
||||
:keyboard-appearance (theme/theme-value :light :dark override-theme)
|
||||
:cursor-color (:cursor variant-colors)
|
||||
:editable (not disabled?)
|
||||
:on-focus (fn []
|
||||
@@ -142,7 +140,7 @@
|
||||
(assoc props
|
||||
:accessibility-label :password-input
|
||||
:auto-capitalize :none
|
||||
:auto-complete :password
|
||||
:auto-complete :password-new
|
||||
:secure-text-entry (not @password-shown?)
|
||||
:right-icon {:style-fn style/password-icon
|
||||
:icon-name (if @password-shown? :i/hide :i/reveal)
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.inputs.recovery-phrase.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.theme :as theme]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def ^:private custom-props
|
||||
[:customization-color :override-theme :blur? :cursor-color :multiline :on-focus :on-blur
|
||||
@@ -43,7 +42,6 @@
|
||||
:style (style/input)
|
||||
:placeholder-text-color (style/placeholder-color @state override-theme blur?)
|
||||
:cursor-color (style/cursor-color customization-color override-theme)
|
||||
:keyboard-appearance (theme/theme-value :light :dark override-theme)
|
||||
:multiline true
|
||||
:on-focus (fn []
|
||||
(set-focused)
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.inputs.search-input.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def ^:private tag-separator [rn/view {:style style/tag-separator}])
|
||||
|
||||
@@ -69,7 +68,6 @@
|
||||
:placeholder-text-color (style/placeholder-color @state blur? override-theme)
|
||||
:editable (not disabled?)
|
||||
:on-key-press #(handle-backspace % @scroll-view-ref)
|
||||
:keyboard-appearance (colors/theme-colors :light :dark override-theme)
|
||||
:on-change-text (fn [new-text]
|
||||
(when on-change-text
|
||||
(on-change-text new-text))
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
[quo2.components.inputs.title-input.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[reagent.core :as reagent]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- pad-0
|
||||
[value]
|
||||
@@ -39,7 +38,6 @@
|
||||
:style (style/title-text disabled? blur? override-theme)})
|
||||
:default-value default-value
|
||||
:accessibility-label :profile-title-input
|
||||
:keyboard-appearance (theme/theme-value :light :dark override-theme)
|
||||
:on-focus #(swap! focused? (fn [] true))
|
||||
:on-blur #(swap! focused? (fn [] false))
|
||||
:input-mode :text
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns quo2.components.keycard.component-spec
|
||||
(:require [quo2.components.keycard.view :as keycard]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "keycard component"
|
||||
(h/test "Render of keycard component when: holder-name prop is not set"
|
||||
(h/render [keycard/keycard])
|
||||
(h/is-truthy (h/get-by-translation-text :empty-keycard)))
|
||||
(h/test "Render of keycard component when: holder-name prop is set"
|
||||
(h/render [keycard/keycard {:holder-name "Alisha"}])
|
||||
(h/is-truthy (h/get-by-translation-text :user-keycard))))
|
||||
@@ -1,42 +0,0 @@
|
||||
(ns quo2.components.keycard.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def keycard-height 210)
|
||||
(def keycard-chip-height 28)
|
||||
|
||||
(defn card-container
|
||||
[locked?]
|
||||
{:overflow :hidden
|
||||
:height keycard-height
|
||||
:align-items :flex-start
|
||||
:justify-content :space-between
|
||||
:border-width 1
|
||||
:border-color (if locked?
|
||||
colors/white-opa-5
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-80))
|
||||
:border-style :solid
|
||||
:border-radius 16
|
||||
:padding 16
|
||||
:background-color (if locked?
|
||||
(colors/theme-colors colors/danger colors/danger-opa-40)
|
||||
(colors/theme-colors colors/neutral-5 colors/neutral-90))})
|
||||
|
||||
(defn keycard-logo
|
||||
[locked?]
|
||||
{:tint-color (if locked? colors/white (colors/theme-colors colors/neutral-100 colors/white))})
|
||||
|
||||
(defn keycard-watermark
|
||||
[locked?]
|
||||
{:position :absolute
|
||||
:tint-color (if locked? colors/white-opa-5 (colors/theme-colors colors/neutral-100 colors/white))
|
||||
:align-self :center
|
||||
:height 280.48
|
||||
:transform [{:rotate "-30deg"} {:translateY -30}]
|
||||
:opacity (when-not locked? 0.02)
|
||||
:z-index 1})
|
||||
|
||||
(def keycard-chip
|
||||
{:height keycard-chip-height
|
||||
:position :absolute
|
||||
:right 16
|
||||
:top (/ (- keycard-height 28) 2)})
|
||||
@@ -1,38 +0,0 @@
|
||||
(ns quo2.components.keycard.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.keycard.style :as style]
|
||||
[quo2.components.tags.tag :as tag]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.resources :as resources]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn keycard
|
||||
"This component based on the following properties:
|
||||
- :holder-name - Can be owner's name. Default is Empty
|
||||
- :locked? - Boolean to specify whether the keycard is locked or not
|
||||
"
|
||||
[{:keys [holder-name locked?]}]
|
||||
(let [label (if (boolean holder-name)
|
||||
(i18n/label :t/user-keycard {:name holder-name})
|
||||
(i18n/label :t/empty-keycard))]
|
||||
[rn/view {:style (style/card-container locked?)}
|
||||
[rn/image
|
||||
{:source (resources/get-image :keycard-logo)
|
||||
:style (style/keycard-logo locked?)}]
|
||||
[rn/image
|
||||
{:source (resources/get-image
|
||||
(if (or locked? (colors/dark?)) :keycard-chip-dark :keycard-chip-light))
|
||||
:style style/keycard-chip}]
|
||||
[rn/image
|
||||
{:source (resources/get-image :keycard-watermark)
|
||||
:style (style/keycard-watermark locked?)}]
|
||||
[tag/tag
|
||||
{:size 32
|
||||
:type (when locked? :icon)
|
||||
:label label
|
||||
:labelled? true
|
||||
:blurred? true
|
||||
:resource (when locked? :i/locked)
|
||||
:accessibility-label :holder-name
|
||||
:icon-color colors/white-70-blur
|
||||
:override-theme (when locked? :dark)}]]))
|
||||
@@ -6,7 +6,6 @@
|
||||
{:title "Some title"
|
||||
:description "Some description"
|
||||
:link "status.im"
|
||||
:logo "data:image/png,logo-x"
|
||||
:thumbnail "data:image/png,whatever"})
|
||||
|
||||
(h/describe "Links - Link Preview"
|
||||
@@ -20,17 +19,12 @@
|
||||
(h/is-truthy (h/query-by-text (:title props)))
|
||||
(h/is-truthy (h/query-by-text (:description props)))
|
||||
(h/is-truthy (h/query-by-text (:link props)))
|
||||
(h/is-truthy (h/query-by-label-text :logo))
|
||||
(h/is-truthy (h/query-by-label-text :thumbnail)))
|
||||
|
||||
(h/test "does not render thumbnail if prop is not present"
|
||||
(h/render [view/view (dissoc props :thumbnail)])
|
||||
(h/is-null (h/query-by-label-text :thumbnail)))
|
||||
|
||||
(h/test "does not render logo if prop is not present"
|
||||
(h/render [view/view (dissoc props :logo)])
|
||||
(h/is-null (h/query-by-label-text :logo)))
|
||||
|
||||
(h/test "shows button to enable preview when preview is disabled"
|
||||
(h/render [view/view
|
||||
(assoc props
|
||||
|
||||
@@ -54,9 +54,7 @@
|
||||
[logo]
|
||||
[rn/image
|
||||
{:accessibility-label :logo
|
||||
:source (if (string? logo)
|
||||
{:uri logo}
|
||||
logo)
|
||||
:source logo
|
||||
:style style/logo}])
|
||||
|
||||
(defn view
|
||||
@@ -70,11 +68,9 @@
|
||||
(if enabled?
|
||||
[:<>
|
||||
[rn/view {:style style/header-container}
|
||||
(when logo
|
||||
[logo-comp logo])
|
||||
[logo-comp logo]
|
||||
[title-comp title]]
|
||||
(when description
|
||||
[description-comp description])
|
||||
[description-comp description]
|
||||
[link-comp link]
|
||||
(when thumbnail
|
||||
[thumbnail-comp thumbnail thumbnail-size])]
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
(h/test "default render"
|
||||
(h/render [view/view])
|
||||
(h/is-truthy (h/query-by-label-text :title))
|
||||
(h/is-truthy (h/query-by-label-text :logo))
|
||||
(h/is-truthy (h/query-by-label-text :button-clear-preview))
|
||||
(h/is-null (h/query-by-label-text :logo))
|
||||
(h/is-null (h/query-by-label-text :url-preview-loading)))
|
||||
|
||||
(h/test "renders logo when prop is present"
|
||||
(h/render [view/view {:logo "data:image/png,logo"}])
|
||||
(h/is-truthy (h/query-by-label-text :logo)))
|
||||
|
||||
(h/test "on-clear event"
|
||||
(let [on-clear (h/mock-fn)]
|
||||
(h/render [view/view {:on-clear on-clear}])
|
||||
|
||||
@@ -6,13 +6,11 @@
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- logo-comp
|
||||
(defn- logo-component
|
||||
[{:keys [logo]}]
|
||||
[rn/image
|
||||
{:accessibility-label :logo
|
||||
:source (if (string? logo)
|
||||
{:uri logo}
|
||||
logo)
|
||||
:source logo
|
||||
:style style/logo}])
|
||||
|
||||
(defn- content
|
||||
@@ -59,7 +57,6 @@
|
||||
[rn/view
|
||||
{:accessibility-label :url-preview
|
||||
:style (merge (style/container) container-style)}
|
||||
(when logo
|
||||
[logo-comp {:logo logo}])
|
||||
[logo-component {:logo logo}]
|
||||
[content {:title title :body body}]
|
||||
[clear-button {:on-press on-clear}]]))
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
(ns quo2.components.links.url-preview-list.view
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[quo2.components.links.url-preview-list.style :as style]
|
||||
[quo2.components.links.url-preview.view :as url-preview]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- use-scroll-to-last-item
|
||||
[flat-list-ref item-count item-width]
|
||||
@@ -43,33 +44,39 @@
|
||||
:on-clear on-clear
|
||||
:container-style (merge container-style {:width width})}])
|
||||
|
||||
(defn- calculate-width
|
||||
[preview-width horizontal-spacing ^js e]
|
||||
(reset! preview-width
|
||||
(- (oops/oget e "nativeEvent.layout.width")
|
||||
(* 2 horizontal-spacing))))
|
||||
|
||||
(defn- f-view
|
||||
[]
|
||||
(let [flat-list-ref (atom nil)]
|
||||
(let [preview-width (reagent/atom 0)
|
||||
flat-list-ref (atom nil)]
|
||||
(fn [{:keys [data key-fn horizontal-spacing on-clear loading-message
|
||||
container-style container-style-item
|
||||
preview-width]}]
|
||||
(use-scroll-to-last-item flat-list-ref (count data) preview-width)
|
||||
container-style container-style-item]}]
|
||||
(use-scroll-to-last-item flat-list-ref (count data) @preview-width)
|
||||
;; We need to use a wrapping view expanded to 100% instead of "flex 1",
|
||||
;; otherwise `on-layout` will be triggered multiple times as the flat list
|
||||
;; renders its children.
|
||||
[rn/view
|
||||
{:style container-style
|
||||
{:style (merge container-style {:width "100%"})
|
||||
:accessibility-label :url-preview-list}
|
||||
[gesture/flat-list
|
||||
[rn/flat-list
|
||||
{:ref #(reset! flat-list-ref %)
|
||||
:keyboard-should-persist-taps :always
|
||||
:key-fn key-fn
|
||||
:on-layout #(calculate-width preview-width horizontal-spacing %)
|
||||
:horizontal true
|
||||
:deceleration-rate :fast
|
||||
:on-scroll-to-index-failed identity
|
||||
:content-container-style {:padding-horizontal horizontal-spacing}
|
||||
:separator [separator]
|
||||
:snap-to-interval (+ preview-width style/url-preview-gap)
|
||||
:snap-to-interval (+ @preview-width style/url-preview-gap)
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:render-fn item-component
|
||||
:render-data {:width preview-width
|
||||
:render-data {:width @preview-width
|
||||
:on-clear on-clear
|
||||
:loading-message loading-message
|
||||
:container-style container-style-item}}]])))
|
||||
|
||||
@@ -57,8 +57,7 @@
|
||||
:override-theme :dark
|
||||
:size :medium
|
||||
:status-indicator? false
|
||||
:customization-color customization-color
|
||||
:static? true}]
|
||||
:customization-color customization-color}]
|
||||
[rn/view {:flex-direction :row}
|
||||
(when show-logged-in?
|
||||
[tag/tag
|
||||
|
||||
@@ -26,10 +26,9 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(-> (h/expect event)
|
||||
(.toHaveBeenCalledTimes 1))))
|
||||
|
||||
@@ -44,18 +43,16 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200}})
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> (h/expect event)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
@@ -72,33 +69,29 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200}})
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 80
|
||||
:locationY 80
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 80
|
||||
:locationY 80
|
||||
:timestamp 200}})
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1))
|
||||
@@ -119,26 +112,23 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-move
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 80
|
||||
:locationY -30
|
||||
:pageX 80
|
||||
:pageY -30
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 80
|
||||
:locationY -30
|
||||
:pageX 80
|
||||
:pageY -30}})
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 40
|
||||
:locationY 80
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 40
|
||||
:locationY 80
|
||||
:timestamp 200}})
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1))
|
||||
@@ -156,25 +146,22 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 200}})
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 40
|
||||
:locationY 80
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 40
|
||||
:locationY 80
|
||||
:timestamp 200}})
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
@@ -191,26 +178,23 @@
|
||||
(h/fire-event
|
||||
:on-start-should-set-responder
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX 70
|
||||
:locationY 70
|
||||
:timestamp 0}})
|
||||
(h/advance-timers-by-time 500)
|
||||
(h/fire-event
|
||||
:on-responder-move
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX -30
|
||||
:locationY 80
|
||||
:pageX -30
|
||||
:pageY 80
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX -30
|
||||
:locationY 80
|
||||
:pageX -30
|
||||
:pageY 80}})
|
||||
(h/fire-event
|
||||
:on-responder-release
|
||||
(h/get-by-test-id "record-audio")
|
||||
{:nativeEvent {:locationX -10
|
||||
:locationY 70
|
||||
:timestamp 200
|
||||
:identifier 0}})
|
||||
{:nativeEvent {:locationX -10
|
||||
:locationY 70
|
||||
:timestamp 200}})
|
||||
(h/advance-timers-by-time 250)
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1))))))
|
||||
|
||||