From 6858884c83bd32ccbb964ae4b6dc7c4f4cad7ebd Mon Sep 17 00:00:00 2001 From: andrey Date: Thu, 27 Apr 2023 09:53:04 +0200 Subject: [PATCH] [#15756] Token gated communities --- ci/Jenkinsfile.android | 2 +- ci/Jenkinsfile.combined | 2 +- ci/Jenkinsfile.ios | 2 +- ci/Jenkinsfile.nix-cache | 2 +- ci/Jenkinsfile.tests | 2 +- ci/tests/Jenkinsfile.e2e-nightly | 2 +- ci/tests/Jenkinsfile.e2e-prs | 2 +- ci/tests/Jenkinsfile.e2e-upgrade | 2 +- ci/tools/Jenkinsfile.fastlane-clean | 2 +- ci/tools/Jenkinsfile.playstore-meta | 2 +- ci/tools/Jenkinsfile.xcode-clean | 2 +- .../images/icons2/20x20/checktoken@2x.png | Bin 0 -> 1153 bytes .../images/icons2/20x20/checktoken@3x.png | Bin 0 -> 1645 bytes shadow-cljs.edn | 27 +- src/quo2/components/buttons/button.cljs | 33 +- src/quo2/components/community/style.cljs | 36 ++ .../components/community/token_gating.cljs | 322 ++---------------- .../components/tags/context_tag/style.cljs | 1 + .../components/tags/context_tag/view.cljs | 35 +- src/quo2/components/tags/token_tag.cljs | 87 +++-- src/quo2/core.cljs | 2 +- src/status_im/communities/core.cljs | 38 ++- .../screens/communities/requests_to_join.cljs | 77 ----- src/status_im/ui/screens/screens.cljs | 5 - .../password_authentication/events.cljs | 12 + .../common/password_authentication/view.cljs | 41 +++ src/status_im2/config.cljs | 5 + .../community_options/component_spec.cljs | 26 +- .../actions/community_options/view.cljs | 22 +- .../actions/token_gating/view.cljs | 23 ++ .../contexts/communities/overview/events.cljs | 22 ++ .../contexts/communities/overview/style.cljs | 7 + .../contexts/communities/overview/view.cljs | 238 +++++++------ .../contexts/onboarding/events.cljs | 51 +-- .../quo_preview/community/token_gating.cljs | 221 ++++-------- src/status_im2/contexts/quo_preview/main.cljs | 3 +- .../contexts/quo_preview/tags/token_tag.cljs | 16 +- src/status_im2/events.cljs | 4 +- src/status_im2/subs/communities.cljs | 34 +- src/status_im2/subs/root.cljs | 1 + status-go-version.json | 6 +- translations/en.json | 12 +- 42 files changed, 613 insertions(+), 816 deletions(-) create mode 100644 resources/images/icons2/20x20/checktoken@2x.png create mode 100644 resources/images/icons2/20x20/checktoken@3x.png create mode 100644 src/status_im2/common/password_authentication/events.cljs create mode 100644 src/status_im2/common/password_authentication/view.cljs create mode 100644 src/status_im2/contexts/communities/actions/token_gating/view.cljs create mode 100644 src/status_im2/contexts/communities/overview/events.cljs diff --git a/ci/Jenkinsfile.android b/ci/Jenkinsfile.android index 6ef8ec8bf8..5e1f25998c 100644 --- a/ci/Jenkinsfile.android +++ b/ci/Jenkinsfile.android @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' /* Options section can't access functions in objects. */ def isPRBuild = utils.isPRBuild() diff --git a/ci/Jenkinsfile.combined b/ci/Jenkinsfile.combined index 49745239c5..bc26fc73c7 100644 --- a/ci/Jenkinsfile.combined +++ b/ci/Jenkinsfile.combined @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { agent { label 'linux' } diff --git a/ci/Jenkinsfile.ios b/ci/Jenkinsfile.ios index 6382fa3547..46ca87a88e 100644 --- a/ci/Jenkinsfile.ios +++ b/ci/Jenkinsfile.ios @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' /* Options section can't access functions in objects. */ def isPRBuild = utils.isPRBuild() diff --git a/ci/Jenkinsfile.nix-cache b/ci/Jenkinsfile.nix-cache index cc727a34d1..ece4124250 100644 --- a/ci/Jenkinsfile.nix-cache +++ b/ci/Jenkinsfile.nix-cache @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { agent { label params.AGENT_LABEL } diff --git a/ci/Jenkinsfile.tests b/ci/Jenkinsfile.tests index 2519958cdb..8979bc2e40 100644 --- a/ci/Jenkinsfile.tests +++ b/ci/Jenkinsfile.tests @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' /* Options section can't access functions in objects. */ def isPRBuild = utils.isPRBuild() diff --git a/ci/tests/Jenkinsfile.e2e-nightly b/ci/tests/Jenkinsfile.e2e-nightly index 4ddb6a70e1..d0198aef50 100644 --- a/ci/tests/Jenkinsfile.e2e-nightly +++ b/ci/tests/Jenkinsfile.e2e-nightly @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { diff --git a/ci/tests/Jenkinsfile.e2e-prs b/ci/tests/Jenkinsfile.e2e-prs index 70911f4d38..96b46788b8 100644 --- a/ci/tests/Jenkinsfile.e2e-prs +++ b/ci/tests/Jenkinsfile.e2e-prs @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { diff --git a/ci/tests/Jenkinsfile.e2e-upgrade b/ci/tests/Jenkinsfile.e2e-upgrade index 02709af67b..48154b0946 100644 --- a/ci/tests/Jenkinsfile.e2e-upgrade +++ b/ci/tests/Jenkinsfile.e2e-upgrade @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { diff --git a/ci/tools/Jenkinsfile.fastlane-clean b/ci/tools/Jenkinsfile.fastlane-clean index 449d661a75..02620b5999 100644 --- a/ci/tools/Jenkinsfile.fastlane-clean +++ b/ci/tools/Jenkinsfile.fastlane-clean @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { agent { label 'macos' } diff --git a/ci/tools/Jenkinsfile.playstore-meta b/ci/tools/Jenkinsfile.playstore-meta index c53e0b592e..39dabb3527 100644 --- a/ci/tools/Jenkinsfile.playstore-meta +++ b/ci/tools/Jenkinsfile.playstore-meta @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { agent { label 'linux' } diff --git a/ci/tools/Jenkinsfile.xcode-clean b/ci/tools/Jenkinsfile.xcode-clean index 37923c3ccd..a11416be34 100644 --- a/ci/tools/Jenkinsfile.xcode-clean +++ b/ci/tools/Jenkinsfile.xcode-clean @@ -1,4 +1,4 @@ -library 'status-jenkins-lib@v1.7.5' +library 'status-jenkins-lib@v1.7.6' pipeline { agent { diff --git a/resources/images/icons2/20x20/checktoken@2x.png b/resources/images/icons2/20x20/checktoken@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..54eb0f61d2b126ec5e1a3dd8c157eafe8262dcad GIT binary patch literal 1153 zcmV-{1b+L8P)n7jQ#KSH*VotUx9vhzkOP zmHehk-Cr?n9OhI^5?W$3JPzRW*(<2Md=sx)f`~*u!JcPB|9*YoauuRv@BrjHy5m`( zSv^(1;iD!8Zr5M%XX0R_!Hw#UF(ZeP=E_C;O%_aDcLrq+}(;g2179ej(Yax)fG zP8C|7Ijx+dL@Yu>#zAC2#wg|_tj=?8(nf`X+>V`x)5t0DA>58*r)q^p9r@i!^X0;C zm0%ex3swozV$)IqYtKU@8B8wN_6|k}z5jqiN6%1X+wceZCi|`#S%w5D6%14Nl@1vw z?pJTzGes_mm(8tcd=e1tv1P+FNJ!&hl^|3Jnf>Um{(VKeAtB5Pcu@>j??MeTi+$WO z!IaeEPMDVQ#)9^eNNSvuxXb0#l?9Uoe+uXk3@IO!T66aB>?th<&8 zk}ub&`*;^%O)^$3o||GeJ#uSSEfj4|?$>VKGbJmDjC=9z`Z}5R$tox!>~l1VXf%f6 zLH~-h!+FvFph3%I0<7iLD;9iP$kCc}v~NFGk(1KTRkM`g>GbVkjcDR^0f9Xb=3?f*qS1cITgG;?zxE4&SqS>do zs`0p-y5F-)=#Z1?obr#}_lET#6_u4*1uF*(msz}Zl@$M<7BoTOZ}*AV^-L}h;`0d% zVCvA6s0$D1jp6OfozNx+LngmW!iIR|9^Zx<{0M>!KIo81n4}Y3Lx}y(>=87JV`pcb z+4Hc5Fu$E##>%nt_d2+%!IdygFgyOWcH~G`{`!z5+Ks4`s_DwFj~sHy;aA5O^OJdo TUnj$900000NkvXXu0mjff#V^q literal 0 HcmV?d00001 diff --git a/resources/images/icons2/20x20/checktoken@3x.png b/resources/images/icons2/20x20/checktoken@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f688be95219c6a8c2379dbeab87147749e6d98 GIT binary patch literal 1645 zcmV-z29o)SP)|7~f@7~^wsi$tiRUoT$~0H6E3U?H)ayI==8>m?n1NZ zbeox9@r$vW%|R%bAdZ9~kSJsmaC15Xq_FW(K3bpWw8hho_w+sO=}h$elIFC1&)5Gv z&w1YGecl%^F)=YQF)=Z@Ls*bP-0nj;w_vNV!m>9Aiz@(BSP;yirkwCDKKe|Aw!v=N zdXIZry+|P`5!~p0qmD(AzytV4oGd;IEN!$s`hn-*APmM(!7P+c`8s{AgE4s1V0+=1 z=hX=qgdu`MuA9a}-ADmez_X0i!zVq5d`Oa{1;6Be+qH&3R}euLQV6;EgbmjEWUXyQ z5;VDwRIFm{QmVx=d<}lEd`%=l!WQNW(@k_ie^5#m4r=v@2DF3(>viLdO-@vlmExX) zZOG5drr+r}cJgaDolaOS7A&tUW68e^zkdai_$ZiFCgR?@1#^I!hh55zONxu|L~RvH z?=MtDsyTS%J>|d68R^P4BV!Y0X6Nwh_%+NgEX6yu@=mW{rBZJoOM^~A(O6q7TXfG; zHHugfPNxG-haC=w1CH?b;-UiVc(54blYd}f=x6ws#TMrW?g;e^uRsU7EX=MC$!o{Vy9<(xX{y&pN7XUHKX>xzmT5pKz?pEc0Tj~S=+8ynm@TYThO$BA3i*N z1~a}njjJk&ju(@T8;e9s>QNZ-+A}6v{+{3mn-<}oA0o&C_oeexC6|V=Xt1LCU?P z1XGDscrvvcv&(Ijzrnaf#?BG65*bUV+#44u!L*aGx)6I4iqhif>}vFixCaOt zY2g3@!Yd7qj73G#Cu<*pQS8|roxxqxOjVUaeq5vkle@Hu+F0!9<=@tSvm3@q1Etti zQx)}k^j;i_*X4O3fs|kx2eV5HU8b`qI+bi7%V;GD@!*Hnu>0|-|IVK8(K^Iu==9j1m( zZE4iy-t5LL&ClI7u5Lfq6YtQYkVIEatI_=?*P-h~?V%D6-*9w)%-Is(^cY3iSWD&S z=AdFni8AKhs5Hdm>Ui(&anEb@kVL0oWwNYGYafy52$3RQWM5IbC@GeTa<+T*)TeFG z!9ZWvL}hh-F1<6=qJ0)A^ZKEG7!Imd+~+E|t=(=I*0Dw0XoN;=KfrW z&&2ApeSO~eRr{#p5+Gck<_e}%^31MVSg@UDA_`-MlYYf@uU@}_!Qs(3l}YtYCq9$- zzne@;czDPcB2N7JZn)Gu5Gh;7gP(=xSA3wFa#!9 rWG0QwJO-@RF)=YQF)=YQ`Pcay1T$A}tLAP*00000NkvXXu0mjfyy6~9 literal 0 HcmV?d00001 diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 0ed1c7bc5e..7825053262 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -53,8 +53,13 @@ ;; @testing-library/react-native. test-helpers.component]} :closure-defines - {status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN" - status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"} + {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"} :compiler-options {:output-feature-set :es5 :closure-defines {re-frame.trace/trace-enabled? true} @@ -67,8 +72,13 @@ :chunks {:fleets status-im.fleet.default-fleet/default-fleets} :release {:closure-defines - {status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN" - status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"} + {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"} :compiler-options {:output-feature-set :es6 ;;disable for android build as there ;;is an intermittent warning with deftype @@ -95,8 +105,13 @@ :ui-driven true :closure-defines - {status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN" - status-im2.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"} + {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"} :compiler-options {;; needed because we override require and it ;; messes with source-map which reports callstack diff --git a/src/quo2/components/buttons/button.cljs b/src/quo2/components/buttons/button.cljs index 6292436480..1d4b8fb4cf 100644 --- a/src/quo2/components/buttons/button.cljs +++ b/src/quo2/components/buttons/button.cljs @@ -226,9 +226,8 @@ [_ _] (let [pressed (reagent/atom false)] (fn - [{:keys [on-press disabled type size community-color community-text-color before after above - width customization-color - override-theme override-background-color + [{: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 @@ -247,18 +246,13 @@ [rn/touchable-without-feedback (merge {:test-ID test-ID :disabled disabled - :accessibility-label accessibility-label} + :accessibility-label accessibility-label + :on-press-in #(reset! pressed true) + :on-press-out #(reset! pressed nil)} (when on-press - {:on-press (fn [] - (on-press))}) + {:on-press on-press}) (when on-long-press - {:on-long-press (fn [] - (on-long-press))}) - {:on-press-in (fn [] - (reset! pressed true))} - {:on-press-out (fn [] - (reset! pressed nil))}) - + {:on-long-press on-long-press})) [rn/view {:style (merge (shape-style-container type icon size) @@ -277,11 +271,7 @@ width before after) - (when - (community-themed? type community-color) - (merge - {:background-color community-color} - (when (= state :pressed) {:opacity 0.9}))) + (when (= state :pressed) {:opacity 0.9}) inner-style)} (when above [rn/view @@ -309,12 +299,7 @@ {:size (when (#{56 24} size) :paragraph-2) :weight :medium :number-of-lines 1 - :style {:color (if - (and - (community-themed? type community-color) - (string? community-text-color)) - community-text-color - label-color)}} + :style {:color label-color}} children] diff --git a/src/quo2/components/community/style.cljs b/src/quo2/components/community/style.cljs index b438f14f24..7b7f87263b 100644 --- a/src/quo2/components/community/style.cljs +++ b/src/quo2/components/community/style.cljs @@ -112,3 +112,39 @@ {: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)}) + diff --git a/src/quo2/components/community/token_gating.cljs b/src/quo2/components/community/token_gating.cljs index 53a5f9a761..b5e886ae67 100644 --- a/src/quo2/components/community/token_gating.cljs +++ b/src/quo2/components/community/token_gating.cljs @@ -1,295 +1,45 @@ (ns quo2.components.community.token-gating - (: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] + (:require [quo2.components.markdown.text :as text] [quo2.components.tags.token-tag :as token-tag] - [quo2.foundations.colors :as colors] + [react-native.core :as rn] [utils.i18n :as i18n] - [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))) + [clojure.string :as string] + [quo2.components.community.style :as style])) (defn token-requirement-list-row - [tokens community-color] + [tokens padding?] [rn/view - {: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)]) + {: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))]) (defn token-requirement-list - [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))] + [{: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) [text/text - {: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)]]))]))) + {: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?])]) diff --git a/src/quo2/components/tags/context_tag/style.cljs b/src/quo2/components/tags/context_tag/style.cljs index 9fc98855b9..a11f5caf36 100644 --- a/src/quo2/components/tags/context_tag/style.cljs +++ b/src/quo2/components/tags/context_tag/style.cljs @@ -20,6 +20,7 @@ (def context-tag-text-container {:align-items :center + :margin-left 4 :flex-direction :row}) (def audio-tag-container diff --git a/src/quo2/components/tags/context_tag/view.cljs b/src/quo2/components/tags/context_tag/view.cljs index 1dd512e08a..4628cfc8e5 100644 --- a/src/quo2/components/tags/context_tag/view.cljs +++ b/src/quo2/components/tags/context_tag/view.cljs @@ -47,23 +47,24 @@ empty-photo? (empty? photo) avatar-size :xxs avatar-outer-size (get-in user-avatar-style/sizes [avatar-size :outer])] - [base-tag (assoc-in params [:style :padding-left] 3) - (if (and empty-photo? no-avatar-placeholder?) - [rn/view {:style {:width avatar-outer-size}}] - [user-avatar/user-avatar - {:full-name name - :profile-picture photo - :size avatar-size - :status-indicator? false}]) - [rn/view {:style style/context-tag-text-container} - [text/text text-params (str " " name)] - (when channel-name - [:<> - [icons/icon - :i/chevron-right - {:color (style/context-tag-icon-color blur?) - :size 16}] - [text/text text-params (str "# " channel-name)]])]])) + [rn/view {:flex-direction :row} + [base-tag (assoc-in params [:style :padding-left] 3) + (if (and empty-photo? no-avatar-placeholder?) + [rn/view {:style {:width avatar-outer-size}}] + [user-avatar/user-avatar + {:full-name name + :profile-picture photo + :size avatar-size + :status-indicator? false}]) + [rn/view {:style style/context-tag-text-container} + [text/text text-params (str " " name)] + (when channel-name + [:<> + [icons/icon + :i/chevron-right + {:color (style/context-tag-icon-color blur?) + :size 16}] + [text/text text-params (str "# " channel-name)]])]]])) (defn user-avatar-tag [params username photo] diff --git a/src/quo2/components/tags/token_tag.cljs b/src/quo2/components/tags/token_tag.cljs index 102a17f05f..a9541e3ef4 100644 --- a/src/quo2/components/tags/token_tag.cljs +++ b/src/quo2/components/tags/token_tag.cljs @@ -39,8 +39,9 @@ :overlay child-elements }" [_ _] - (fn [{:keys [size token-img-src token-img-style border-color overlay] - :or {size :small}} label] + (fn [{:keys [size img-src img-style border-color overlay] + :or {size :small}} + label] [rn/view {:style (when border-color {:border-color border-color @@ -49,13 +50,13 @@ [rn/view {:style (merge (tag-container size) (get themes (theme/get-theme)))} [rn/image - {:source token-img-src - :style (merge - {:height (get-value-from-size size 28 20) - :width (get-value-from-size size 28 20) - :margin-left 2 - :margin-right (get-value-from-size size 8 6)} - token-img-style)}] + {:src img-src + :style (merge + {:height (get-value-from-size size 28 20) + :width (get-value-from-size size 28 20) + :margin-left 2 + :margin-right (get-value-from-size size 8 6)} + img-style)}] [text/text {:weight :medium :number-of-lines 1 @@ -64,38 +65,58 @@ :size (get-value-from-size size :paragraph-2 :label)} label] overlay]])) +(defn loading-icon + [] + [rn/view + {:style {:align-items :center + :justify-content :center + :position :absolute + :right -8 + :top -8}} + [icons/icon :t/checktoken + {:no-color true + :size 20}]]) + +(defn icon + [size border-color sufficient?] + [rn/view + {:style (merge + icon-container-styles + {:background-color border-color + :border-color (if (= (theme/get-theme) :dark) colors/neutral-100 colors/white) + :border-width 1 + :right (get-value-from-size size -3.75 -5.75) + :bottom (get-value-from-size size (- 32 7.75 4) (- 24 7.75 2))})} + [icons/icon (if sufficient? :i/hold :i/add) + {:no-color true + :size 12}]]) + (defn token-tag "[token-tag opts] opts { - :token string + :symbol string :value string :size :small/:big :token-img-src :token-img-src :border-color :color - :is-required true/false - :is-purchasable true/false + :sufficient? true/false + :purchasable? true/false + :loading? true/false }" [_ _] - (fn [{:keys [token value size token-img-src border-color is-required is-purchasable] + (fn [{:keys [symbol value size img-src border-color purchasable? sufficient? loading?] :or - {size :small border-color (colors/custom-color-by-theme :purple 50 60)}}] - - [tag - {:size size - :token-img-src token-img-src - :border-color (when is-required border-color) - :overlay - (when (or is-required is-purchasable) - [rn/view - {:style (merge - icon-container-styles - {:background-color border-color - :border-color (if (= (theme/get-theme) :dark) colors/neutral-100 colors/white) - :border-width 1 - :right (get-value-from-size size -3.75 -5.75) - :bottom (get-value-from-size size (- 32 7.75 4) (- 24 7.75 2))})} - [icons/icon (if is-required :i/hold :i/add) - {:no-color true - :size 12}]])} - (str value " " token)])) + {size :small}}] + (let [sufficient? (when-not loading? sufficient?) + border-color (if sufficient? colors/success-50 border-color)] + [tag + {:size size + :img-src img-src + :border-color (if sufficient? colors/success-50 border-color) + :overlay + (if loading? + [loading-icon] + (when (or purchasable? sufficient?) + [icon size border-color sufficient?]))} + (str value " " symbol)]))) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index 8a71821e8c..6fbf98dfd6 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -145,8 +145,8 @@ (def community-title quo2.components.community.community-view/community-title) (def permission-tag-container quo2.components.community.community-view/permission-tag-container) (def discover-card quo2.components.community.banner.view/view) -(def token-gating quo2.components.community.token-gating/token-gating) (def community-icon quo2.components.community.icon/community-icon) +(def token-requirement-list quo2.components.community.token-gating/token-requirement-list) ;;;; COUNTER (def counter quo2.components.counter.counter/counter) diff --git a/src/status_im/communities/core.cljs b/src/status_im/communities/core.cljs index 2b6362f024..76536295be 100644 --- a/src/status_im/communities/core.cljs +++ b/src/status_im/communities/core.cljs @@ -74,13 +74,19 @@ :canJoin :can-join? :requestedToJoinAt :requested-to-join-at :isMember :is-member? - :adminSettings :admin-settings}) + :adminSettings :admin-settings + :tokenPermissions :token-permissions + :communityTokensMetadata :tokens-metadata}) (update :admin-settings set/rename-keys {:pinMessageAllMembersEnabled :pin-message-all-members-enabled?}) (update :members walk/stringify-keys) (update :chats <-chats-rpc) - (update :categories <-categories-rpc))) + (update :categories <-categories-rpc) + (assoc :token-images + (reduce (fn [acc {:keys [symbol image]}] (assoc acc symbol image)) + {} + (:communityTokensMetadata c))))) (defn- fetch-community-id-input [{:keys [db]}] @@ -174,6 +180,7 @@ (let [community-name (aget response-js "communities" 0 "name")] (rf/merge cofx (handle-response cofx response-js) + (navigation/hide-bottom-sheet) (toasts/upsert {:icon :correct :icon-color (:positive-01 @colors/theme) :text (i18n/label @@ -215,14 +222,12 @@ (rf/defn join {:events [:communities/join]} - [cofx community-id] + [_ community-id] {:json-rpc/call [{:method "wakuext_joinCommunity" :params [community-id] :js-response true :on-success #(re-frame/dispatch [::joined %]) - :on-error #(do - (log/error "failed to join community" community-id %) - (re-frame/dispatch [::failed-to-join %]))}]}) + :on-error #(log/error "failed to join community" community-id %)}]}) (rf/defn request-to-join {:events [:communities/request-to-join]} @@ -231,9 +236,24 @@ :params [{:communityId community-id}] :js-response true :on-success #(re-frame/dispatch [:communities/requested-to-join %]) - :on-error (fn [] - (log/error "failed to request to join community" community-id) - (re-frame/dispatch [::failed-to-request-to-join]))}]}) + :on-error #(log/error "failed to request to join community" community-id)}]}) + +(rf/defn requested-to-join-with-password-error + {:events [:communities/requested-to-join-with-password-error]} + [{:keys [db]} error] + {:db (assoc-in db [:password-authentication :error] error)}) + +(rf/defn request-to-join-with-password + {:events [:communities/request-to-join-with-password]} + [_ community-id password] + {:json-rpc/call [{:method "wakuext_requestToJoinCommunity" + :params [{:communityId community-id :password password}] + :js-response true + :on-success #(re-frame/dispatch [:communities/requested-to-join %]) + :on-error (fn [error] + (log/error "failed to request to join community" community-id error) + (re-frame/dispatch [:communities/requested-to-join-with-password-error + error]))}]}) (rf/defn get-user-requests-to-join {:events [:communities/get-user-requests-to-join]} diff --git a/src/status_im/ui/screens/communities/requests_to_join.cljs b/src/status_im/ui/screens/communities/requests_to_join.cljs index 43b15bb416..e69de29bb2 100644 --- a/src/status_im/ui/screens/communities/requests_to_join.cljs +++ b/src/status_im/ui/screens/communities/requests_to_join.cljs @@ -1,77 +0,0 @@ -(ns status-im.ui.screens.communities.requests-to-join - (:require [quo.components.animated.pressable :as animation] - [quo.core :as quo] - [quo.design-system.colors :as colors] - [quo.react-native :as rn] - [re-frame.core :as re-frame] - [reagent.core :as reagent] - [status-im.communities.core :as communities] - [utils.i18n :as i18n] - [status-im.multiaccounts.core :as multiaccounts] - [status-im.ui.components.chat-icon.screen :as chat-icon] - [status-im.ui.components.icons.icons :as icons] - [status-im.ui.components.react :as react] - [status-im.ui.components.topbar :as topbar] - [utils.re-frame :as rf])) - -(defn request-actions - [community-id request-id] - [react/view {:flex-direction :row} - [animation/pressable - {:on-press #(re-frame/dispatch [:communities.ui/accept-request-to-join-pressed community-id - request-id])} - [icons/icon :main-icons/checkmark-circle - {:width 35 - :height 35 - :color colors/green}]] - [animation/pressable - {:on-press #(re-frame/dispatch [:communities.ui/decline-request-to-join-pressed community-id - request-id])} - [icons/icon :main-icons/cancel - {:width 35 - :height 35 - :container-style {:margin-left 16} - :color colors/red}]]]) - -(defn render-request - [{:keys [id public-key]} _ _ - {:keys [community-id - can-manage-users?]}] - (let [member (or (rf/sub [:contacts/contact-by-identity public-key]) - {:public-key public-key})] - [quo/list-item - {:title (multiaccounts/displayed-name member) - :accessibility-label :member-item - :accessory-style (when can-manage-users? - {:flex-basis 120}) - :accessory (when can-manage-users? - [request-actions community-id id]) - :icon [chat-icon/contact-icon-contacts-tab member] - :on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}])) - -(defn requests-to-join - [] - (let [{:keys [community-id]} (rf/sub [:get-screen-params])] - (fn [] - (let [requests (rf/sub [:communities/requests-to-join-for-community - community-id]) - {:keys [can-manage-users?]} (rf/sub [:communities/community community-id])] - [:<> - [topbar/topbar - {:title (i18n/label :t/community-requests-to-join-title) - :subtitle (str (count requests))}] - [rn/flat-list - {:data requests - :render-data {:community-id community-id - :can-manage-users? can-manage-users?} - :key-fn :id - :render-fn render-request}]])))) - -(defn requests-to-join-container - [] - (reagent/create-class - {:display-name "community-requests-to-join-view" - :component-did-mount (fn [] - (communities/fetch-requests-to-join! (get (rf/sub [:get-screen-params]) - :community-id))) - :reagent-render requests-to-join})) diff --git a/src/status_im/ui/screens/screens.cljs b/src/status_im/ui/screens/screens.cljs index b0f7590916..d9e59ddfbb 100644 --- a/src/status_im/ui/screens/screens.cljs +++ b/src/status_im/ui/screens/screens.cljs @@ -26,7 +26,6 @@ [status-im.ui.screens.communities.membership :as membership] [status-im.ui.screens.communities.profile :as community.profile] [status-im.ui.screens.communities.reorder-categories :as reorder-categories] - [status-im.ui.screens.communities.requests-to-join :as requests-to-join] [status-im.ui.screens.communities.select-category :as select-category] [status-im.ui.screens.contacts-list.views :as contacts-list] [status-im.ui.screens.currency-settings.views :as currency-settings] @@ -229,10 +228,6 @@ ;;TODO custom subtitle :options {:insets {:top? true}} :component members/members-container} - {:name :community-requests-to-join - ;;TODO custom subtitle - :options {:insets {:top? true}} - :component requests-to-join/requests-to-join-container} {:name :create-community-channel :options {:topBar {:title {:text (i18n/label :t/create-channel-title)}} :insets {:bottom? true diff --git a/src/status_im2/common/password_authentication/events.cljs b/src/status_im2/common/password_authentication/events.cljs new file mode 100644 index 0000000000..cc13d6743c --- /dev/null +++ b/src/status_im2/common/password_authentication/events.cljs @@ -0,0 +1,12 @@ +(ns status-im2.common.password-authentication.events + (:require [utils.re-frame :as rf] + [status-im2.navigation.events :as navigation])) + +(rf/defn close + {:events [:password-authentication/show]} + [{:keys [db]} content button] + (rf/merge {:db (assoc db + :password-authentication + {:error nil + :button button})} + (navigation/show-bottom-sheet content))) diff --git a/src/status_im2/common/password_authentication/view.cljs b/src/status_im2/common/password_authentication/view.cljs new file mode 100644 index 0000000000..a9922ac962 --- /dev/null +++ b/src/status_im2/common/password_authentication/view.cljs @@ -0,0 +1,41 @@ +(ns status-im2.common.password-authentication.view + (:require [react-native.core :as rn] + [quo2.core :as quo] + [utils.re-frame :as rf] + [status-im.multiaccounts.core :as multiaccounts] + [utils.i18n :as i18n] + [status-im.ethereum.core :as ethereum] + [reagent.core :as reagent])) + +(defn view + [] + (let [entered-password (reagent/atom "")] + (fn [] + (let [account (rf/sub [:profile/multiaccount]) + {:keys [error button]} (rf/sub [:password-authentication])] + [rn/view {:padding-horizontal 20} + [quo/text {:size :heading-1 :weight :semi-bold} + (i18n/label :t/enter-password)] + [quo/user-avatar-tag + {:size :small + :style {:margin-top 8 :margin-bottom 20}} + (multiaccounts/displayed-name account) + (multiaccounts/displayed-photo account)] + [quo/input + {:type :password + :label (i18n/label :t/profile-password) + :placeholder (i18n/label :t/type-your-password) + :error? (when (not-empty error) error) + :auto-focus true + :on-change-text #(reset! entered-password %)}] + (when (not-empty error) + [quo/info-message + {:type :error + :size :default + :icon :i/info + :style {:margin-top 8}} + (i18n/label :t/oops-wrong-password)]) + [quo/button + {:style {:margin-bottom 12 :margin-top 40} + :on-press #((:on-press button) (ethereum/sha3 @entered-password))} + (:label button)]])))) diff --git a/src/status_im2/config.cljs b/src/status_im2/config.cljs index 5ee9c3aedb..c4b8c4d6b8 100644 --- a/src/status_im2/config.cljs +++ b/src/status_im2/config.cljs @@ -8,7 +8,12 @@ (defn enabled? [v] (= "1" v)) +(goog-define INFURA_TOKEN "") (goog-define POKT_TOKEN "3ef2018191814b7e1009b8d9") +(goog-define ALCHEMY_ARBITRUM_GOERLI_TOKEN "") +(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "") +(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "") +(goog-define ALCHEMY_ARBITRUM_MAINNET_TOKEN "") (goog-define OPENSEA_API_KEY "") (def mainnet-rpc-url (str "https://eth-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN)) diff --git a/src/status_im2/contexts/communities/actions/community_options/component_spec.cljs b/src/status_im2/contexts/communities/actions/community_options/component_spec.cljs index 8640277f01..222a4cf21b 100644 --- a/src/status_im2/contexts/communities/actions/community_options/component_spec.cljs +++ b/src/status_im2/contexts/communities/actions/community_options/component_spec.cljs @@ -37,8 +37,8 @@ (h/test "joined options - Token Gated" (setup-subs {:communities/my-pending-request-to-join nil - :communities/community {:joined true - :token-gated? true}}) + :communities/community {:joined true + :token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) @@ -86,8 +86,8 @@ (h/test "admin options - Token Gated" (setup-subs {:communities/my-pending-request-to-join nil - :communities/community {:admin true - :token-gated? true}}) + :communities/community {:admin true + :token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) @@ -127,7 +127,7 @@ (h/test "request sent options - Token Gated" (setup-subs {:communities/my-pending-request-to-join "mock-id" - :communities/community {:token-gated? true}}) + :communities/community {:token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) @@ -157,8 +157,8 @@ (h/test "banned options - Token Gated" (setup-subs {:communities/my-pending-request-to-join nil - :communities/community {:banList 100 - :token-gated? true}}) + :communities/community {:banList 100 + :token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) @@ -171,8 +171,8 @@ (h/test "banned options - Token Gated" (setup-subs {:communities/my-pending-request-to-join nil - :communities/community {:banList 100 - :token-gated? true}}) + :communities/community {:banList 100 + :token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) @@ -185,11 +185,9 @@ (h/test "joined and muted community" (setup-subs {:communities/my-pending-request-to-join nil - :communities/community {:joined true - :muted true - :token-gated? true}}) + :communities/community {:joined true + :muted true + :token-permissions []}}) (h/render [options/community-options-bottom-sheet {:id "test"}]) (-> (h/expect (h/get-by-translation-text :unmute-community)) (.toBeTruthy)))) - - diff --git a/src/status_im2/contexts/communities/actions/community_options/view.cljs b/src/status_im2/contexts/communities/actions/community_options/view.cljs index 3d2b350e22..5b0f813b4d 100644 --- a/src/status_im2/contexts/communities/actions/community_options/view.cljs +++ b/src/status_im2/contexts/communities/actions/community_options/view.cljs @@ -3,7 +3,8 @@ [utils.re-frame :as rf] [quo2.core :as quo] [status-im2.contexts.communities.actions.see-rules.view :as see-rules] - [status-im2.contexts.communities.actions.leave.view :as leave-menu])) + [status-im2.contexts.communities.actions.leave.view :as leave-menu] + [status-im2.contexts.communities.actions.token-gating.view :as token-gating])) (defn hide-sheet-and-dispatch [event] @@ -29,10 +30,11 @@ (defn view-token-gating [id] - {:icon :i/bullet-list - :right-icon :i/token + {:icon :i/token + :right-icon :i/chevron-right :accessibility-label :view-token-gating - :on-press #(js/alert (str "implement action" id)) + :on-press #(rf/dispatch [:show-bottom-sheet + {:content (fn [] [token-gating/token-requirements id])}]) :label (i18n/label :t/view-token-gating)}) (defn mark-as-read @@ -152,15 +154,15 @@ (defn get-context-drawers [{:keys [id]}] - (let [{:keys [token-gated? admin joined + (let [{:keys [token-permissions admin joined muted banList]} (rf/sub [:communities/community id]) request-id (rf/sub [:communities/my-pending-request-to-join id])] (cond - admin (owner-options id token-gated? muted) - joined (joined-options id token-gated? muted) - request-id (join-request-sent-options id token-gated? request-id) - banList (banned-options id token-gated?) - :else (not-joined-options id token-gated?)))) + admin (owner-options id token-permissions muted) + joined (joined-options id token-permissions muted) + request-id (join-request-sent-options id token-permissions request-id) + banList (banned-options id token-permissions) + :else (not-joined-options id token-permissions)))) (defn community-options-bottom-sheet [id] diff --git a/src/status_im2/contexts/communities/actions/token_gating/view.cljs b/src/status_im2/contexts/communities/actions/token_gating/view.cljs new file mode 100644 index 0000000000..d5a930a958 --- /dev/null +++ b/src/status_im2/contexts/communities/actions/token_gating/view.cljs @@ -0,0 +1,23 @@ +(ns status-im2.contexts.communities.actions.token-gating.view + (:require [quo2.core :as quo] + [utils.i18n :as i18n] + [utils.re-frame :as rf] + [react-native.core :as rn])) + +(defn token-requirements + [id] + (rf/dispatch [:communities/check-permissions-to-join-community id]) + (fn [] + (let [{:keys [can-request-access? + number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])] + [rn/view {:style {:padding-horizontal 12}} + [quo/text {:weight :medium} + (if can-request-access? + (i18n/label :t/you-eligible-to-join) + (i18n/label :t/you-not-eligible-to-join))] + [quo/text {:style {:padding-bottom 18} :size :paragraph-2} + (if can-request-access? + (i18n/label :t/you-hold-number-of-hold-tokens-of-these + {:number-of-hold-tokens number-of-hold-tokens}) + (i18n/label :t/you-must-hold))] + [quo/token-requirement-list {:tokens tokens}]]))) diff --git a/src/status_im2/contexts/communities/overview/events.cljs b/src/status_im2/contexts/communities/overview/events.cljs new file mode 100644 index 0000000000..fb6db9d34f --- /dev/null +++ b/src/status_im2/contexts/communities/overview/events.cljs @@ -0,0 +1,22 @@ +(ns status-im2.contexts.communities.overview.events + (:require [utils.re-frame :as rf] + [taoensso.timbre :as log])) + +(rf/defn check-permissions-to-join-community-success + {:events [:communities/check-permissions-to-join-community-success]} + [{:keys [db]} community-id result] + {:db (-> db + (assoc-in [:communities community-id :checking-permissions?] false) + (assoc-in [:communities community-id :token-permissions-check] result))}) + +(rf/defn check-permissions-to-join-community + {:events [:communities/check-permissions-to-join-community]} + [{:keys [db]} community-id] + {:db (-> db + (assoc-in [:communities community-id :checking-permissions?] true) + (assoc-in [:communities community-id :can-request-access?] false)) + :json-rpc/call [{:method "wakuext_checkPermissionsToJoinCommunity" + :params [{:communityId community-id}] + :on-success #(rf/dispatch [:communities/check-permissions-to-join-community-success + community-id %]) + :on-error #(log/error "failed to request to join community" community-id %)}]}) diff --git a/src/status_im2/contexts/communities/overview/style.cljs b/src/status_im2/contexts/communities/overview/style.cljs index bbae2341e7..2bbb1f73e7 100644 --- a/src/status_im2/contexts/communities/overview/style.cljs +++ b/src/status_im2/contexts/communities/overview/style.cljs @@ -32,3 +32,10 @@ :left 0 :right 0 :bottom 0}) + +(defn token-gated-container + [] + {:border-radius 16 + :border-color (colors/theme-colors colors/neutral-20 colors/neutral-80) + :border-width 1 + :padding-top 10}) diff --git a/src/status_im2/contexts/communities/overview/view.cljs b/src/status_im2/contexts/communities/overview/view.cljs index a35a873abd..f13484d8a2 100644 --- a/src/status_im2/contexts/communities/overview/view.cljs +++ b/src/status_im2/contexts/communities/overview/view.cljs @@ -13,47 +13,23 @@ [status-im2.contexts.communities.actions.community-options.view :as options] [quo2.components.navigation.floating-shell-button :as floating-shell-button] [status-im2.contexts.communities.overview.utils :as utils] + [status-im2.common.password-authentication.view :as password-authentication] [utils.re-frame :as rf])) (defn preview-user-list [user-list] - [rn/view style/preview-user - [quo/preview-list - {:type :user - :list-size (count user-list) - :size 24} - user-list] - [quo/text - {:accessibility-label :communities-screen-title - :style {:margin-left 8} - :size :label} - (utils/join-existing-users-string user-list)]]) - -(defn channel-token-gating-details - [name token-gating emoji channel-color] - [rn/view {:height 350 :margin-top 20} - [quo/token-gating - {:channel {:name name - :community-color channel-color - :emoji emoji - :emoji-background-color channel-color - :on-enter-channel (fn [] - (js/alert - "Entered channel" - "Wuhuu!! You successfully entered the channel :)")) - :gates token-gating}}]]) - -(defn open-channel-token-gating-details - [name token-gating emoji channel-color] - (rf/dispatch - [:show-bottom-sheet - {:content - (fn [] - [channel-token-gating-details name token-gating emoji channel-color])}])) - -(defn layout-y - [event] - (oops/oget event "nativeEvent.layout.y")) + (when (seq user-list) + [rn/view style/preview-user + [quo/preview-list + {:type :user + :list-size (count user-list) + :size 24} + user-list] + [quo/text + {:accessibility-label :communities-screen-title + :style {:margin-left 8} + :size :label} + (utils/join-existing-users-string user-list)]])) (defn add-category-height [categories-heights category height] @@ -65,17 +41,18 @@ [community-id category-id collapsed?] (rf/dispatch [:communities/toggle-collapsed-category community-id category-id (not collapsed?)])) +(defn layout-y + [event] + (oops/oget event "nativeEvent.layout.y")) + (defn channel-list-component - [{:keys [on-category-layout - community-id - on-first-channel-height-changed]} + [{:keys [on-category-layout community-id on-first-channel-height-changed]} channels-list] [rn/view - {:on-layout #(on-first-channel-height-changed (+ (if platform/ios? - 0 - 38) - (int (Math/ceil (layout-y %)))) - (into #{} (map (comp :name second) channels-list))) + {:on-layout #(on-first-channel-height-changed + (+ (if platform/ios? 0 38) + (int (Math/ceil (layout-y %)))) + (into #{} (map (comp :name second) channels-list))) :style {:margin-top 20 :flex 1}} (map (fn [[category-id {:keys [chats name collapsed?]}]] @@ -123,10 +100,68 @@ constants/community-on-request-access :request-access :unknown-access)) +(defn join-gated-community + [id] + (rf/dispatch [:password-authentication/show + {:content (fn [] [password-authentication/view])} + {:label (i18n/label :t/join-open-community) + :on-press #(rf/dispatch [:communities/request-to-join-with-password id %])}])) + +(defn info-button + [] + [rn/touchable-without-feedback + {:on-press + #(rf/dispatch + [:show-bottom-sheet + {:content + (fn [] + [quo/documentation-drawers + {:title (i18n/label :t/token-gated-communities) + :show-button? true + :button-label (i18n/label :t/read-more) + :button-icon :info} + [quo/text (i18n/label :t/token-gated-communities-info)]])}])} + [rn/view + [quo/icon :i/info {:no-color true}]]]) + +(defn token-gates + [{:keys [id]}] + (rf/dispatch [:communities/check-permissions-to-join-community id]) + (fn [{:keys [id community-color]}] + (let [{:keys [can-request-access? + number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])] + [rn/view {:style (style/token-gated-container)} + [rn/view + {:style {:padding-horizontal 12 + :flex-direction :row + :align-items :center + :justify-content :space-between + :flex 1}} + [quo/text {:weight :medium} + (if can-request-access? + (i18n/label :t/you-eligible-to-join) + (i18n/label :t/you-not-eligible-to-join))] + [info-button]] + [quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2} + (if can-request-access? + (i18n/label :t/you-hold-number-of-hold-tokens-of-these + {:number-of-hold-tokens number-of-hold-tokens}) + (i18n/label :t/you-must-hold))] + [quo/token-requirement-list + {:tokens tokens + :padding? true}] + [quo/button + {:on-press #(join-gated-community id) + :accessibility-label :join-community-button + :override-background-color community-color + :style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12} + :disabled (not can-request-access?) + :before (if can-request-access? :i/unlocked :i/locked)} + (i18n/label :t/join-open-community)]]))) + (defn join-community - [{:keys [joined can-join? - community-color permissions] - :as community} pending?] + [{:keys [joined can-join? community-color permissions token-permissions] :as community} + pending?] (let [access-type (get-access-type (:access permissions)) unknown-access? (= access-type :unknown-access) invite-only? (= access-type :invite-only) @@ -134,15 +169,16 @@ node-offline? (and can-join? (not joined) pending?)] [:<> (when-not (or joined pending? invite-only? unknown-access?) - [quo/button - {:on-press #(rf/dispatch [:open-modal :community-requests-to-join community]) - :accessibility-label :show-request-to-join-screen-button - :override-background-color community-color - :style style/join-button - :before :i/communities} - (request-to-join-text is-open?)]) + (if token-permissions + [token-gates community] + [quo/button + {:on-press #(rf/dispatch [:open-modal :community-requests-to-join community]) + :accessibility-label :show-request-to-join-screen-button + :override-background-color community-color + :before :i/communities} + (request-to-join-text is-open?)])) - (when (and (not (or joined pending?)) (not (or is-open? node-offline?))) + (when (and (not (or joined pending? token-permissions)) (not (or is-open? node-offline?))) [quo/text {:size :paragraph-2 :style style/review-notice} @@ -155,38 +191,24 @@ :style {:margin-top 12}} (i18n/label :t/request-processed-after-node-online)])])) -(defn get-tag - [joined] - [quo/status-tag - {:status {:type (if joined :positive :pending)} - :label (if joined - (i18n/label :t/joined) - (i18n/label :t/pending))}]) - -(defn community-token-gating-details - [name thumbnail-image tokens] - [rn/view {:height 200 :margin-top 20} - [quo/token-gating - {:community {:name name - :community-color colors/primary-50 - :community-avatar-img-src thumbnail-image - :gates tokens}}]]) +(defn status-tag + [pending? joined] + (when (or pending? joined) + [rn/view {:position :absolute :top 12 :right 12} + [quo/status-tag + {:status {:type (if joined :positive :pending)} + :label (if joined + (i18n/label :t/joined) + (i18n/label :t/pending))}]])) (defn add-on-press-handler - [community-id {:keys [name emoji id locked? token-gating] :or {locked? false} :as chat}] + [community-id {:keys [id locked?] :or {locked? false} :as chat}] (merge chat - (if (and locked? token-gating) - {:on-press #(open-channel-token-gating-details - name - token-gating - emoji - (colors/custom-color :pink 50))} - - (when (and (not locked?) id) - {:on-press (fn [] - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:chat/navigate-to-chat (str community-id id)]))})))) + (when (and (not locked?) id) + {:on-press (fn [] + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch [:chat/navigate-to-chat (str community-id id)]))}))) (defn add-on-press-handler-to-chats [community-id chats] @@ -206,7 +228,8 @@ :number-of-lines 1 :ellipsize-mode :tail :weight :semi-bold - :size :heading-1} + :size :heading-1 + :style {:margin-top 56}} name]) (defn community-description @@ -221,49 +244,20 @@ description]) (defn community-content - [{:keys [name description locked joined images - status tokens tags id] + [{:keys [name description joined tags id] :as community} pending? - {:keys [on-category-layout - on-first-channel-height-changed]}] - (let [thumbnail-image (:thumbnail images) - chats-by-category (rf/sub [:communities/categorized-channels id]) - users (rf/sub [:communities/users id])] - [rn/view + {:keys [on-category-layout on-first-channel-height-changed]}] + (let [chats-by-category (rf/sub [:communities/categorized-channels id])] + [:<> [rn/view {:padding-horizontal 20} - (when (and (not joined) - (not pending?) - (= status :gated)) - [rn/view - {:position :absolute - :top 8 - :right 8} - [quo/permission-tag-container - {:locked locked - :status status - :tokens tokens - :on-press #(rf/dispatch - [:show-bottom-sheet - {:content - (fn [] - [community-token-gating-details - name - thumbnail-image - tokens])}])}]]) - (when (or pending? joined) - [rn/view - {:position :absolute - :top 12 - :right 12} - [get-tag joined]]) - [rn/view {:margin-top 56} - [community-header name]] + [status-tag pending? joined] + [community-header name] [community-description description] - [quo/community-stats-column :card-view] + ;; [quo/community-stats-column :card-view] not implemented [rn/view {:margin-top 12}] [quo/community-tags tags] - [preview-user-list users] + ;;[preview-user-list users] not implemented [join-community community pending?]] [channel-list-component {:on-category-layout on-category-layout diff --git a/src/status_im2/contexts/onboarding/events.cljs b/src/status_im2/contexts/onboarding/events.cljs index a4b15a918e..da38f97fda 100644 --- a/src/status_im2/contexts/onboarding/events.cljs +++ b/src/status_im2/contexts/onboarding/events.cljs @@ -79,29 +79,38 @@ effect (if seed-phrase :multiaccount/restore-account-and-login :multiaccount/create-account-and-login) - request {:displayName display-name - :password (ethereum/sha3 (security/safe-unmask-data password)) - :mnemonic (when seed-phrase - (security/safe-unmask-data seed-phrase)) - :imagePath (strip-file-prefix image-path) - :customizationColor color - :backupDisabledDataDir (native-module/backup-disabled-data-dir) - :rootKeystoreDir (native-module/keystore-dir) + request {:displayName display-name + :password (ethereum/sha3 (security/safe-unmask-data + password)) + :mnemonic (when seed-phrase + (security/safe-unmask-data seed-phrase)) + :imagePath (strip-file-prefix image-path) + :customizationColor color + :backupDisabledDataDir (native-module/backup-disabled-data-dir) + :rootKeystoreDir (native-module/keystore-dir) ;; Temporary fix until https://github.com/status-im/status-go/issues/3024 is ;; resolved - :wakuV2Nameserver "1.1.1.1" - :logLevel (when log-enabled? config/log-level) - :logEnabled log-enabled? - :logFilePath (native-module/log-file-directory) - :openseaAPIKey config/opensea-api-key - :verifyTransactionURL config/verify-transaction-url - :verifyENSURL config/verify-ens-url - :verifyENSContractAddress config/verify-ens-contract-address - :verifyTransactionChainID config/verify-transaction-chain-id - :upstreamConfig config/default-network-rpc-url - :networkId config/default-network-id - :currentNetwork config/default-network - :previewPrivacy config/blank-preview?}] + :wakuV2Nameserver "1.1.1.1" + :logLevel (when log-enabled? config/log-level) + :logEnabled log-enabled? + :logFilePath (native-module/log-file-directory) + :openseaAPIKey config/opensea-api-key + :verifyTransactionURL config/verify-transaction-url + :verifyENSURL config/verify-ens-url + :verifyENSContractAddress config/verify-ens-contract-address + :verifyTransactionChainID config/verify-transaction-chain-id + :upstreamConfig config/default-network-rpc-url + :networkId config/default-network-id + :poktToken config/POKT_TOKEN + :infuraToken config/INFURA_TOKEN + + :alchemyOptimismMainnetToken config/ALCHEMY_OPTIMISM_MAINNET_TOKEN + :alchemyOptimismGoerliToken config/ALCHEMY_OPTIMISM_GOERLI_TOKEN + :alchemyArbitrumMainnetToken config/ALCHEMY_ARBITRUM_MAINNET_TOKEN + :alchemyArbitrumGoerliToken config/ALCHEMY_ARBITRUM_GOERLI_TOKEN + + :currentNetwork config/default-network + :previewPrivacy config/blank-preview?}] {effect request :dispatch [:navigate-to :generating-keys] :db (-> db diff --git a/src/status_im2/contexts/quo_preview/community/token_gating.cljs b/src/status_im2/contexts/quo_preview/community/token_gating.cljs index 5b35e01b08..6e6cde3d7f 100644 --- a/src/status_im2/contexts/quo_preview/community/token_gating.cljs +++ b/src/status_im2/contexts/quo_preview/community/token_gating.cljs @@ -1,171 +1,90 @@ (ns status-im2.contexts.quo-preview.community.token-gating - (:require [quo.previews.preview :as preview] - [quo.react-native :as rn] - [quo2.components.community.token-gating :as quo2] - [quo2.foundations.colors :as colors] - [reagent.core :as reagent] - [status-im2.common.resources :as resources])) - -(def styles - {:container-sandbox {:flex 1 - :padding-vertical 20 - :border-top-left-radius 20 - :border-top-right-radius 20}}) + (:require [reagent.core :as reagent] + [status-im2.common.resources :as resources] + [react-native.core :as rn] + [status-im2.contexts.quo-preview.preview :as preview] + [quo2.core :as quo])) (def descriptor - [{:label "Type:" - :key :type - :type :select - :options [{:key :community - :value "Community"} - {:key :channel - :value "Channel"}]} - {:label "Tokens sufficient:" - :key :is-sufficient? + [{:label "Tokens sufficient" + :key :sufficient? :type :boolean} - {:label "Many tokens:" + {:label "Many tokens ?" :key :many-tokens? :type :boolean} - {:label "Membership request denied:" - :key :membership-request-denied? + {:label "Loading ?" + :key :loading? + :type :boolean} + {:label "Сondition ?" + :key :condition? + :type :boolean} + {:label "Padding ?" + :key :padding? :type :boolean}]) (defn join-gate-options-base - [is-sufficient? many-tokens?] + [sufficient? many-tokens? loading?] (into - [{:token "KNC" - :token-img-src (resources/get-token :knc) - :amount 200 - :is-sufficient? true} - {:token "MANA" - :token-img-src (resources/get-token :mana) - :amount 10 - :is-sufficient? is-sufficient? - :is-purchasable? true} - {:token "RARE" - :token-img-src (resources/get-token :rare) - :amount 10 - :is-sufficient? is-sufficient?}] + [{:symbol "KNC" + :img-src (resources/get-token :knc) + :amount 200 + :sufficient? true + :loading? loading?} + {:symbol "MANA" + :img-src (resources/get-token :mana) + :amount 10 + :sufficient? sufficient? + :purchasable? true + :loading? loading?} + {:symbol "RARE" + :img-src (resources/get-token :rare) + :amount 10 + :sufficient? sufficient? + :loading? loading?}] (when many-tokens? - [{:token "FXC" - :token-img-src (resources/get-token :fxc) - :amount 20 - :is-sufficient? true} - {:token "SNT" - :token-img-src (resources/get-token :snt) - :amount 10000 - :is-sufficient? is-sufficient?}]))) - -(defn write-gate-options-base - [is-sufficient?] - [{:token "KNC" - :token-img-src (resources/get-token :knc) - :amount 200 - :is-sufficient? true} - {:token "DAI" - :token-img-src (resources/get-token :dai) - :amount 20 - :is-purchasable? true - :is-sufficient? is-sufficient?} - {:token "ETH" - :token-img-src (resources/get-token :eth) - :amount 0.5 - :is-sufficient? is-sufficient?}]) + [{:symbol "FXC" + :img-src (resources/get-token :fxc) + :amount 20 + :sufficient? true + :loading? loading?} + {:symbol "SNT" + :img-src (resources/get-token :snt) + :amount 10000 + :sufficient? sufficient? + :loading? loading?}]))) (defn get-mocked-props [props] - (let [{:keys [type is-sufficient? many-tokens? membership-request-denied?]} props] - (if (= type :community) - {:community {:name "Ethereum" - :community-color "#14044d" - :community-avatar-img-src (resources/get-token :eth) - :gates {:join (if - many-tokens? - [(join-gate-options-base is-sufficient? - many-tokens?) - [{:token "FXC" - :token-img-src (resources/get-token :fxc) - :amount 20 - :is-sufficient? true} - {:token "USDT" - :token-img-src (resources/get-token :usdt) - :amount 20 - :is-sufficient? false}]] - (join-gate-options-base is-sufficient? - many-tokens?))}}} - {:channel {:name "onboarding" - :community-color (colors/custom-color :pink 50) - :community-text-color colors/white - :emoji "🍑" - :emoji-background-color "#F38888" - :on-enter-channel #(js/alert - "Entered channel - Wuhuu!! You successfully entered the channel :)") - :membership-request-denied? membership-request-denied? - :gates {:read (into [{:token "KNC" - :token-img-src (resources/get-token :knc) - :amount 200 - :is-sufficient? true} - {:token "MANA" - :token-img-src (resources/get-token :mana) - :amount 10 - :is-sufficient? is-sufficient? - :is-purchasable? true} - {:token "RARE" - :token-img-src (resources/get-token :rare) - :amount 10 - :is-sufficient? is-sufficient?}] - (when many-tokens? - [{:token "FXC" - :token-img-src (resources/get-token :fxc) - :amount 20 - :is-sufficient? true} - {:token "SNT" - :token-img-src (resources/get-token :snt) - :amount 10000 - :is-sufficient? is-sufficient?}])) - :write (if - many-tokens? - [(write-gate-options-base is-sufficient?) - [{:token "FXC" - :token-img-src (resources/get-token :fxc) - :amount 20 - :is-sufficient? true} - {:token "MANA" - :token-img-src (resources/get-token :mana) - :amount 10 - :is-sufficient? is-sufficient?} - {:token "USDT" - :token-img-src (resources/get-token :usdt) - :amount 20 - :is-sufficient? false}]] - (write-gate-options-base is-sufficient?))}}}))) + (let [{:keys [sufficient? condition? many-tokens? padding? loading?]} props] + {:tokens + (if condition? + [(join-gate-options-base sufficient? + many-tokens? + loading?) + [{:symbol "FXC" + :img-src (resources/get-token :fxc) + :amount 20 + :sufficient? true} + {:symbol "USDT" + :img-src (resources/get-token :usdt) + :amount 20 + :sufficient? false}]] + [(join-gate-options-base sufficient? + many-tokens? + loading?)]) + :padding? padding?})) (def state - (reagent/atom {:type :channel - :is-sufficient? false - :many-tokens? false - :membership-request-denied? false})) + (reagent/atom {:sufficient? false + :many-tokens? false + :condition? false + :padding? false})) (defn preview-token-gating [] (let [preview-props (get-mocked-props @state)] - [rn/view - {:style {:background-color (colors/theme-colors - colors/neutral-10 - colors/neutral-80) - :flex 1}} - [rn/view {:style {:flex 1}} - [rn/view - {:style {:position :absolute - :left 0 - :right 0 - :top 0}} - [preview/customizer state descriptor]]] - [rn/view {:height (if (= (:type @state) :community) 280 495) :margin-top 20} - [rn/view - {:style (merge - (get styles :container-sandbox) - {:background-color (colors/theme-colors - colors/white - colors/neutral-90)})} - [quo2/token-gating preview-props]]]])) + [rn/view {:flex 1} + [rn/scroll-view {:style {:flex 1}} + [preview/customizer state descriptor]] + [rn/view {:padding-horizontal 20 :padding-vertical 20} + [quo/token-requirement-list preview-props]]])) diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index 0e171e6299..957f17c3b7 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -150,7 +150,8 @@ :options {:topBar {:visible true}} :component discover-card/preview-discoverd-card} {:name :token-gating - :options {:topBar {:visible true}} + :options {:insets {:bottom? true} + :topBar {:visible true}} :component token-gating/preview-token-gating}] :counter [{:name :counter :options {:topBar {:visible true}} diff --git a/src/status_im2/contexts/quo_preview/tags/token_tag.cljs b/src/status_im2/contexts/quo_preview/tags/token_tag.cljs index dce6eeb641..586b3b11ce 100644 --- a/src/status_im2/contexts/quo_preview/tags/token_tag.cljs +++ b/src/status_im2/contexts/quo_preview/tags/token_tag.cljs @@ -27,19 +27,11 @@ :value "1000"} {:key 10000 :value "10000"}]} - - {:label "Community Color:" - :key :border-color - :type :select - :options [{:key "#00a191" - :value "green"} - {:key "red" - :value "red"}]} - {:label "Is Required:" - :key :is-required + {:label "Is Sufficient:" + :key :sufficient? :type :boolean} {:label "Is Purchasable:" - :key :is-purchasable + :key :purchasable? :type :boolean} {:label "Token:" :key :token @@ -54,7 +46,7 @@ (defn cool-preview [] - (let [state (reagent/atom {:size :big :value 10 :token "ETH" :is-required true :is-purchasable false})] + (let [state (reagent/atom {:size :big :value 10 :token "ETH" :sufficient? false :purchasable? false})] (fn [] [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} [rn/view {:padding-bottom 150} diff --git a/src/status_im2/events.cljs b/src/status_im2/events.cljs index 41d9b07eae..42e3b62fca 100644 --- a/src/status_im2/events.cljs +++ b/src/status_im2/events.cljs @@ -16,7 +16,9 @@ [utils.datetime :as datetime] status-im2.contexts.share.events status-im2.contexts.syncing.events - status-im2.contexts.chat.events)) + status-im2.contexts.chat.events + status-im2.common.password-authentication.events + status-im2.contexts.communities.overview.events)) (re-frame/reg-cofx :now diff --git a/src/status_im2/subs/communities.cljs b/src/status_im2/subs/communities.cljs index b8e076f4e9..54a0db8181 100644 --- a/src/status_im2/subs/communities.cljs +++ b/src/status_im2/subs/communities.cljs @@ -262,17 +262,33 @@ categories-and-chats))) -(re-frame/reg-sub - :communities/users - :<- [:communities] - (fn [_ [_ _]] - [{:full-name "Alicia K"} - {:full-name "Marcus C"} - {:full-name "MNO PQR"} - {:full-name "STU VWX"}])) - (re-frame/reg-sub :communities/collapsed-categories-for-community :<- [:communities/collapsed-categories] (fn [collapsed-categories [_ community-id]] (get collapsed-categories community-id))) + +(re-frame/reg-sub + :community/token-gated-overview + (fn [[_ community-id]] + [(re-frame/subscribe [:communities/community community-id])]) + (fn [[{:keys [token-permissions-check token-permissions checking-permissions? token-images]}] _] + {:can-request-access? (:satisfied token-permissions-check) + :number-of-hold-tokens (reduce + (fn [acc [_ {:keys [criteria]}]] + (reduce #(+ %1 (if %2 1 0)) acc criteria)) + 0 + (:permissions token-permissions-check)) + :tokens (map (fn [[perm-key {:keys [token_criteria]}]] + (let [check-criteria (get-in token-permissions-check + [:permissions perm-key :criteria])] + (map + (fn [{:keys [symbol amount]} sufficient?] + {:symbol symbol + :sufficient? (when (seq check-criteria) sufficient?) + :loading? checking-permissions? + :amount amount + :img-src (get token-images symbol)}) + token_criteria + (or check-criteria token_criteria)))) + token-permissions)})) diff --git a/src/status_im2/subs/root.cljs b/src/status_im2/subs/root.cljs index 46d720fc24..9db6b05e0d 100644 --- a/src/status_im2/subs/root.cljs +++ b/src/status_im2/subs/root.cljs @@ -74,6 +74,7 @@ (reg-root-key-sub :waku/v2-peer-stats :peer-stats) (reg-root-key-sub :visibility-status-updates :visibility-status-updates) (reg-root-key-sub :shell/switcher-cards :shell/switcher-cards) +(reg-root-key-sub :password-authentication :password-authentication) ;;NOTE this one is not related to ethereum network ;; it is about cellular network/ wifi network diff --git a/status-go-version.json b/status-go-version.json index 304a366944..69f1588361 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -3,7 +3,7 @@ "_comment": "Instead use: scripts/update-status-go.sh ", "owner": "status-im", "repo": "status-go", - "version": "v0.151.12", - "commit-sha1": "6fa8c113821509d744b81d90dc21c1e79c575577", - "src-sha256": "02mmhy4z6gd9xlqjhw4i4j48gd85pijyyga48if9dd3zasqkp3y1" + "version": "v0.151.14", + "commit-sha1": "959e3703891286853574f4974e87bd53e079e72d", + "src-sha256": "11l9p1psl331b4vaw1694z09z9rlaps5w1cildmdgnx2pnkgcr7q" } diff --git a/translations/en.json b/translations/en.json index 24e7524589..4b16c3d76d 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1447,7 +1447,7 @@ "view-details": "View Details", "view-signing": "View signing phrase", "view-superrare": "View in SuperRare", - "view-token-gating": "View token gating", + "view-token-gating": "View token requirements", "vote-to-feature": "Vote to feature this community", "waiting-for-wifi": "No Wi-fi, message syncing disabled.", "waiting-for-wifi-change": "Settings", @@ -2168,5 +2168,11 @@ "sync-devices-error-sub-title":"Make sure both devices are powered on and connected to the internet.", "sync-devices-complete-title": "Device sync complete!", "sync-devices-complete-sub-title": "Your devices are now in sync", - "sync-with": "Synced with" -} \ No newline at end of file + "sync-with": "Synced with", + "you-eligible-to-join": "You’re eligible to join", + "you-not-eligible-to-join": "You’re not eligible to join", + "you-hold-number-of-hold-tokens-of-these": "You hold {{number-of-hold-tokens}} of these:", + "token-gated-communities": "Token gated communities", + "read-more": "Read more", + "token-gated-communities-info": "Here will be something relevant about this topic. This will help the user get more context and therefore have a better understanding of it." +}