Referrals add screen with join public-chat

Update strings

Check if transaction has receipt on login

Notification on accept

Add large icon

Unify notifications for referral

Fix duplicate path for acquisition

Fix accept notification and visibility

Small fixes

Do not show notifications when not rewardable

Add home item

Show referral on lets go button

Fix list item on home

Hide messages on accept

Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-12-07 15:10:42 +03:00
parent 7f22912f1e
commit 2571e44de0
No known key found for this signature in database
GPG Key ID: C9A094959935A952
22 changed files with 406 additions and 111 deletions

View File

@ -92,7 +92,7 @@
(defn- wrap-render-fn [f] (defn- wrap-render-fn [f]
(fn [data] (fn [data]
(reagent/as-element (f (.-item ^js data) (.-index ^js data) (.-separators ^js data))))) (reagent/as-element [f (.-item ^js data) (.-index ^js data) (.-separators ^js data)])))
(defn- wrap-key-fn [f] (defn- wrap-key-fn [f]
(fn [data index] (fn [data index]

View File

@ -4,6 +4,7 @@
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.acquisition.gateway :as gateway] [status-im.acquisition.gateway :as gateway]
[status-im.acquisition.claim :as claim] [status-im.acquisition.claim :as claim]
[status-im.acquisition.notifications :as notifications]
[status-im.acquisition.persistance :as persistence])) [status-im.acquisition.persistance :as persistence]))
(fx/defn start-acquisition (fx/defn start-acquisition
@ -15,15 +16,20 @@
(fx/defn advertiser-decide (fx/defn advertiser-decide
{:events [::decision]} {:events [::decision]}
[{:keys [db] :as cofx} decision] [{:keys [db] :as cofx} decision]
(let [referral (get-in db [:acquisition :referrer]) (let [referral (get-in db [:acquisition :referrer])
payload {:chat_key (get-in db [:multiaccount :public-key]) {:keys [rewardable]} (get-in db [:acquisition :metadata])
:address (ethereum/default-address db) payload {:chat_key (get-in db [:multiaccount :public-key])
:invite_code referral}] :address (ethereum/default-address db)
:invite_code referral}]
(fx/merge cofx (fx/merge cofx
(if (= decision :accept) (if (= decision :accept)
(gateway/handle-acquisition {:message payload (fn [cofx]
:method "PATCH" (fx/merge cofx
:url [:clicks referral] (when rewardable
:on-success [::claim/success-starter-pack-claim]}) (notifications/accept))
(gateway/handle-acquisition {:message payload
:method "PATCH"
:url [:clicks referral]
:on-success [::claim/success-starter-pack-claim]})))
{::persistence/set-referrer-state :declined}) {::persistence/set-referrer-state :declined})
(popover/hide-popover)))) (popover/hide-popover))))

View File

@ -4,35 +4,63 @@
[status-im.acquisition.claim :as claim] [status-im.acquisition.claim :as claim]
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.acquisition.persistance :as persistence] [status-im.acquisition.persistance :as persistence]
[status-im.acquisition.notifications :as notifications]
[status-im.acquisition.gateway :as gateway] [status-im.acquisition.gateway :as gateway]
[status-im.chat.models :as chat])) [status-im.chat.models :as chat]
[status-im.navigation :as navigation]
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]))
(def public-chat "public-chat")
(fx/defn start-acquisition (fx/defn start-acquisition
[{:keys [db]} {:keys [key id] :as referrer} public] [{:keys [db]} {:keys [key id] :as referrer} public]
{:db (assoc-in db [:acquisition :chat-referrer (or key id)] referrer) {:db (assoc-in db [:acquisition :chat-referrer (or key id)] referrer)
::persistence/chat-initialized? (fn [state] ::persistence/chat-initialized? (fn [state]
(when-not (= "initialized" state) (when-not (= "initialized" state)
(re-frame/dispatch [::start-chat referrer public])))}) (if public
(re-frame/dispatch [::start-public-chat referrer public])
(re-frame/dispatch [::start-chat referrer public]))))})
(fx/defn start-chat (fx/defn start-chat
{:events [::start-chat]} {:events [::start-chat]}
[cofx {:keys [key id]} public] [cofx {:keys [key id]} public]
(fx/merge cofx (fx/merge cofx
{::persistence/chat-initalized! true} {::persistence/chat-initalized! true}
(if public (chat/start-chat key)))
(chat/start-public-chat id nil)
(chat/start-chat key)))) (fx/defn start-public-chat
{:events [::start-public-chat]}
[cofx referrer chat-name]
(fx/merge cofx
{::persistence/chat-initalized! true}
(navigation/navigate-to :tabs {:screen :chat-stack
:params {:screen :referral-enclav}})))
(fx/defn join-public-chat
[cofx chat-name]
(chat/start-public-chat cofx chat-name nil))
(fx/defn accept-pack (fx/defn accept-pack
{:events [::accept-pack]} {:events [::accept-pack]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [referral (get-in db [:acquisition :referrer]) (let [referral (get-in db [:acquisition :referrer])
payload {:chat_key (get-in db [:multiaccount :public-key]) {:keys [type id rewardable]} (get-in db [:acquisition :metadata])
:address (ethereum/default-address db) payload {:chat_key (get-in db [:multiaccount :public-key])
:invite_code referral}] :address (ethereum/default-address db)
:invite_code referral}]
(fx/merge cofx (fx/merge cofx
{:db (update db :acquisition dissoc :chat-referrer)} (when rewardable
(notifications/accept))
(when (= type public-chat)
(join-public-chat id))
(gateway/handle-acquisition {:message payload (gateway/handle-acquisition {:message payload
:method "PATCH" :method "PATCH"
:url [:clicks referral] :url [:clicks referral]
:on-success [::claim/success-starter-pack-claim]})))) :on-success [::claim/success-starter-pack-claim]}))))
(fx/defn decline
{:events [::decline]}
[cofx]
(fx/merge cofx
{::persistence/set-referrer-state :declined}
(bottom-sheet/hide-bottom-sheet)))

View File

@ -1,16 +1,17 @@
(ns status-im.acquisition.claim (ns status-im.acquisition.claim
(:require [status-im.i18n :as i18n] (:require [status-im.utils.fx :as fx]
[status-im.utils.fx :as fx]
[status-im.ethereum.transactions.core :as transaction] [status-im.ethereum.transactions.core :as transaction]
[status-im.notifications.core :as notifications] [status-im.acquisition.notifications :as notifications]
[status-im.acquisition.persistance :as persistence])) [status-im.acquisition.persistance :as persistence]
[status-im.ethereum.json-rpc :as json-rpc]
[re-frame.core :as re-frame]))
(fx/defn success-tx-received (fx/defn success-tx-received
{:events [::success-tx-received]} {:events [::success-tx-received]}
[_] [cofx]
{::persistence/set-referrer-state :claimed (fx/merge cofx
::notifications/local-notification {:title (i18n/label :t/starter-pack-received) (notifications/claimed)
:message (i18n/label :t/starter-pack-received-description)}}) {::persistence/set-referrer-state :claimed}))
(fx/defn add-tx-watcher (fx/defn add-tx-watcher
{:events [::add-tx-watcher]} {:events [::add-tx-watcher]}
@ -23,11 +24,21 @@
(fn [] (fn []
{:dispatch [::success-tx-received]})}))) {:dispatch [::success-tx-received]})})))
(fx/defn check-transaction-receipt
{:events [::check-transaction-receipt]}
[cofx tx]
(when tx
{::json-rpc/call [{:method "eth_getTransactionReceipt"
:params [tx]
:on-success (fn [receipt]
(if receipt
(re-frame/dispatch [::success-tx-received])
(re-frame/dispatch [::add-tx-watcher tx])))}]}))
(fx/defn success-starter-pack-claim (fx/defn success-starter-pack-claim
{:events [::success-starter-pack-claim]} {:events [::success-starter-pack-claim]}
[cofx {:keys [tx]}] [cofx {:keys [tx]}]
(fx/merge cofx (fx/merge cofx
{::persistence/set-referrer-state (if tx :accepted :claimed)} {::persistence/set-referrer-state (if tx :accepted :claimed)}
(when tx (when tx
(add-tx-watcher tx)) (add-tx-watcher tx))))
(notifications/request-permission)))

View File

@ -5,6 +5,7 @@
[status-im.ethereum.core :as ethereum] [status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens] [status-im.ethereum.ens :as ens]
[status-im.ethereum.contracts :as contracts] [status-im.ethereum.contracts :as contracts]
[status-im.acquisition.notifications :as notifications]
[status-im.acquisition.chat :as chat] [status-im.acquisition.chat :as chat]
[status-im.acquisition.dapp :as dapp] [status-im.acquisition.dapp :as dapp]
[status-im.acquisition.claim :as claim] [status-im.acquisition.claim :as claim]
@ -58,7 +59,8 @@
[{:keys [db] :as cofx} referrer {:keys [type attributed] :as referrer-meta}] [{:keys [db] :as cofx} referrer {:keys [type attributed] :as referrer-meta}]
(when-not attributed (when-not attributed
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:acquisition :metadata] referrer-meta)} {:db (assoc-in db [:acquisition :metadata] referrer-meta)
::notifications/create-channel nil}
(cond (cond
(= type advertiser-type) (= type advertiser-type)
(advertiser/start-acquisition referrer-meta) (advertiser/start-acquisition referrer-meta)
@ -95,7 +97,7 @@
(fn [_] (fn [_]
{::persistence/check-tx-state (fn [tx] {::persistence/check-tx-state (fn [tx]
(when-not (nil? tx) (when-not (nil? tx)
(re-frame/dispatch [::claim/add-tx-watcher tx])))}))))) (re-frame/dispatch [::claim/check-transaction-receipt tx])))})))))
(re-frame/reg-fx (re-frame/reg-fx
::resolve-contract ::resolve-contract

View File

@ -0,0 +1,33 @@
(ns status-im.acquisition.notifications
(:require [re-frame.core :as re-frame]
[status-im.notifications.android :as pn-android]
[status-im.utils.fx :as fx]
[status-im.i18n :as i18n]
[status-im.notifications.core :as notifications]
[status-im.ui.components.react :as react]
[quo.platform :as platform]
[status-im.ethereum.tokens :as tokens]))
(def channel-id "status-im-referrals")
(re-frame/reg-fx
::create-channel
(fn []
(when platform/android?
(pn-android/create-channel {:channel-id channel-id
:channel-name "Status referrals push notifications"}))))
(fx/defn accept
[_]
{::notifications/local-notification
{:title (i18n/label :t/starter-pack-coming)
:message (i18n/label :t/starter-pack-coming-description)
:channel-id channel-id
:icon (:uri (react/resolve-asset-source tokens/snt-icon-source))}})
(fx/defn claimed
[_]
{::notifications/local-notification {:title (i18n/label :t/starter-pack-received)
:message (i18n/label :t/starter-pack-received-description)
:channel-id channel-id
:icon (:uri (react/resolve-asset-source tokens/snt-icon-source))}})

View File

@ -19,7 +19,8 @@
(-> ^js async-storage (-> ^js async-storage
(.setItem referrer-flow-state-key (get referrer-state decision)) (.setItem referrer-flow-state-key (get referrer-state decision))
(.then (fn [] (.then (fn []
(re-frame/dispatch [:set-in [:acquisition :flow-state] decision]))) (re-frame/dispatch [:set-in [:acquisition :flow-state]
(get referrer-state decision)])))
(.catch (fn [error] (.catch (fn [error]
(log/error "[async-storage]" error)))))) (log/error "[async-storage]" error))))))

View File

@ -269,10 +269,10 @@
(fx/defn create-only-events (fx/defn create-only-events
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [multiaccount multiaccounts :multiaccount/accounts]} db (let [{:keys [multiaccount :multiaccounts/multiaccounts :multiaccount/accounts]} db
{:keys [creating?]} (:multiaccounts/login db) {:keys [creating?]} (:multiaccounts/login db)
first-account? (and creating? first-account? (and creating?
(empty? multiaccounts))] (empty? multiaccounts))]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(dissoc :multiaccounts/login) (dissoc :multiaccounts/login)
@ -284,12 +284,11 @@
;;later on there is a check that filters have been initialized twice ;;later on there is a check that filters have been initialized twice
;;so here we set it at 1 already so that it passes the check once it has ;;so here we set it at 1 already so that it passes the check once it has
;;been initialized ;;been initialized
:filters/initialized 1)) :filters/initialized 1)
:dispatch-later [{:ms 2000 :dispatch [::initialize-wallet accounts nil nil (:recovered multiaccount)]}] (assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
:dispatch-later [{:ms 2000 :dispatch [::initialize-wallet accounts nil nil (:recovered multiaccount)]}]
:filters/load-filters [[]]} :filters/load-filters [[]]}
(finish-keycard-setup) (finish-keycard-setup)
(when first-account?
(acquisition/create))
(protocol/initialize-protocol {:mailservers [] (protocol/initialize-protocol {:mailservers []
:mailserver-ranges {} :mailserver-ranges {}
:mailserver-topics {} :mailserver-topics {}
@ -448,3 +447,13 @@
(popover/show-popover {:view :secure-with-biometric}) (popover/show-popover {:view :secure-with-biometric})
(when-not (= previous-auth-method keychain/auth-method-none) (when-not (= previous-auth-method keychain/auth-method-none)
(popover/show-popover {:view :disable-password-saving}))))))) (popover/show-popover {:view :disable-password-saving})))))))
(fx/defn welcome-lets-go
{:events [::welcome-lets-go]}
[cofx]
(let [first-account? (get-in cofx [:db :multiaccount :multiaccounts/first-account])]
(fx/merge cofx
(when first-account?
(acquisition/create))
(navigation/navigate-reset {:index 0
:routes [{:name :tabs}]}))))

View File

@ -6,6 +6,7 @@
["@react-native-community/push-notification-ios" :default pn-ios] ["@react-native-community/push-notification-ios" :default pn-ios]
[status-im.notifications.android :as pn-android] [status-im.notifications.android :as pn-android]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.notifications.local :as local]
[quo.platform :as platform] [quo.platform :as platform]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.ethereum.json-rpc :as json-rpc])) [status-im.ethereum.json-rpc :as json-rpc]))
@ -57,9 +58,10 @@
(re-frame/reg-fx (re-frame/reg-fx
::local-notification ::local-notification
(fn [{:keys [title message]}] (fn [props]
(log/info {:title title (if platform/ios?
:message message}))) (local/local-push-ios props)
(local/local-push-android props))))
(re-frame/reg-fx (re-frame/reg-fx
::enable ::enable

View File

@ -31,8 +31,9 @@
:userInfo (bean/->js (merge user-info :userInfo (bean/->js (merge user-info
{:notificationType "local-notification"}))})) {:notificationType "local-notification"}))}))
(defn local-push-android [{:keys [title message icon user-info]}] (defn local-push-android [{:keys [title message icon user-info channel-id]
(pn-android/present-local-notification (merge {:channelId "status-im-notifications" :or {channel-id "status-im-notifications"}}]
(pn-android/present-local-notification (merge {:channelId channel-id
:title title :title title
:message message :message message
:showBadge false} :showBadge false}

View File

@ -216,6 +216,7 @@
(reg-root-key-sub :push-notifications/servers :push-notifications/servers) (reg-root-key-sub :push-notifications/servers :push-notifications/servers)
(reg-root-key-sub :push-notifications/preferences :push-notifications/preferences) (reg-root-key-sub :push-notifications/preferences :push-notifications/preferences)
(reg-root-key-sub :acquisition :acquisition)
;;GENERAL ============================================================================================================== ;;GENERAL ==============================================================================================================
(re-frame/reg-sub (re-frame/reg-sub

View File

@ -92,31 +92,35 @@
nil))]]) nil))]])
(defn reward-messages [] (defn reward-messages []
(let [pending-invite @(re-frame/subscribe [::invite/pending-chat-invite]) (let [has-invite @(re-frame/subscribe [::invite/has-chat-invite])
loading (#{(get gateway/network-statuses :initiated) loading (#{(get gateway/network-statuses :initiated)
(get gateway/network-statuses :in-flight)} (get gateway/network-statuses :in-flight)}
@(re-frame/subscribe [::gateway/network-status])) @(re-frame/subscribe [::gateway/network-status]))
messages [{:content [{:type :text pending @(re-frame/subscribe [::invite/pending-reward])
:value "👋"}]} messages [{:content [{:type :text
{:content [{:type :author :value "👋"}]}
:value (i18n/label :t/invite-chat-name)} {:content [{:type :author
{:type :text :value (i18n/label :t/invite-chat-name)}
:value (i18n/label :t/invite-chat-intro)} {:type :text
{:type :pack} :value (i18n/label :t/invite-chat-intro)}
{:type :button {:type :pack}
:value [quo/button {:type :secondary {:type :button
:loading loading :value [quo/button {:type :secondary
:on-press #(re-frame/dispatch [::acquisition/accept-pack])} :loading loading
(i18n/label :t/invite-chat-accept)]}]} :disabled pending
{:content [{:type :text :on-press #(re-frame/dispatch [::acquisition/accept-pack])}
:value (i18n/label :t/invite-chat-rule)}]} (if pending
{:content [{:type :text (i18n/label :t/invite-chat-pending)
:value [:<> (i18n/label :t/invite-chat-accept))]}]}
(i18n/label :t/invite-privacy-policy1) " " {:content [{:type :text
[quo/text {:color :link :value (i18n/label :t/invite-chat-rule)}]}
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])} {:content [{:type :text
(i18n/label :t/invite-privacy-policy2)]]}]}]] :value [:<>
(when pending-invite (i18n/label :t/invite-privacy-policy1) " "
[quo/text {:color :link
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]}]}]]
(when has-invite
[rn/view {:style (messages-wrapper)} [rn/view {:style (messages-wrapper)}
(for [message messages] (for [message messages]
[render-message message])]))) [render-message message])])))

View File

@ -46,16 +46,31 @@
:on-success [::share-link]})) :on-success [::share-link]}))
(re-frame/reg-sub (re-frame/reg-sub
::pending-chat-invite ::has-chat-invite
(fn [db] :<- [:chats/current-chat-id]
(let [chat-id (get db :current-chat-id) :<- [:acquisition]
{:keys [flow-state]} (get db :acquisition) (fn [[chat-id acquisition]]
{:keys [attributed] (let [{:keys [flow-state attributed]} acquisition
:as chat-referrer} (get-in db [:acquisition :chat-referrer chat-id])] chat-referrer (get-in acquisition [:chat-referrer chat-id])]
(and chat-referrer (and chat-referrer
(not attributed) (not attributed)
(or (= flow-state (get persistence/referrer-state :accepted)) (nil? flow-state)))))
(nil? flow-state))))))
(re-frame/reg-sub
::pending-reward
:<- [:acquisition]
(fn [{:keys [flow-state]}]
(= flow-state (get persistence/referrer-state :accepted))))
(re-frame/reg-sub
::has-public-chat-invite
:<- [:acquisition]
(fn [acquisition]
(let [{:keys [metadata flow-state attributed]} acquisition
{:keys [type]} metadata]
(and (= type "public-chat")
(not attributed)
(nil? flow-state)))))
(fx/defn go-to-invite (fx/defn go-to-invite
{:events [::open-invite]} {:events [::open-invite]}

View File

@ -176,7 +176,11 @@
(defn friend-reward-item [starter-pack-amount description] (defn friend-reward-item [starter-pack-amount description]
(let [tokens (transform-tokens starter-pack-amount) (let [tokens (transform-tokens starter-pack-amount)
reward-text (cstr/join ", " (map (comp name :symbol first) tokens))] reward-text (->> tokens
(map (comp :symbol first))
(filter (comp not nil?))
(map name)
(cstr/join ", "))]
[rn/view {} [rn/view {}
[rn/view {:style styles/reward-item-title} [rn/view {:style styles/reward-item-title}
[quo/text {:weight :medium} [quo/text {:weight :medium}

View File

@ -3,8 +3,7 @@
[status-im.ui.components.chat-icon.screen :as chat-icon.screen] [status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.main :as st] [status-im.ui.screens.chat.styles.main :as st]
[re-frame.core :as re-frame]) [re-frame.core :as re-frame]))
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn- group-last-activity [{:keys [contacts public?]}] (defn- group-last-activity [{:keys [contacts public?]}]
[react/view {:flex-direction :row} [react/view {:flex-direction :row}
@ -31,27 +30,25 @@
(i18n/label :chat-is-a-contact) (i18n/label :chat-is-a-contact)
(i18n/label :chat-is-not-a-contact))]])) (i18n/label :chat-is-not-a-contact))]]))
(defview toolbar-content-view [] (defn toolbar-content-view [{:keys [group-chat
(letsubs [{:keys [group-chat invitation-admin
invitation-admin color
color chat-id
chat-id contacts
contacts chat-name
chat-name public?]}]
public?]} [react/view {:style st/toolbar-container}
[:chats/current-chat]] [react/view {:margin-right 10}
[react/view {:style st/toolbar-container} [chat-icon.screen/chat-icon-view-toolbar chat-id group-chat chat-name color]]
[react/view {:margin-right 10} [react/view {:style st/chat-name-view}
[chat-icon.screen/chat-icon-view-toolbar chat-id group-chat chat-name color]] (if group-chat
[react/view {:style st/chat-name-view} [react/text {:style st/chat-name-text
(if group-chat :number-of-lines 1
[react/text {:style st/chat-name-text :accessibility-label :chat-name-text}
:number-of-lines 1 chat-name]
:accessibility-label :chat-name-text} [one-to-one-name chat-id])
chat-name] (when-not group-chat
[one-to-one-name chat-id]) [contact-indicator chat-id])
(when-not group-chat (when (and group-chat (not invitation-admin))
[contact-indicator chat-id]) [group-last-activity {:contacts contacts
(when (and group-chat (not invitation-admin)) :public? public?}])]])
[group-last-activity {:contacts contacts
:public? public?}])]]))

View File

@ -37,7 +37,7 @@
(defn topbar [] (defn topbar []
(let [current-chat @(re-frame/subscribe [:current-chat/metadata])] (let [current-chat @(re-frame/subscribe [:current-chat/metadata])]
[topbar/topbar [topbar/topbar
{:content [toolbar-content/toolbar-content-view] {:content [toolbar-content/toolbar-content-view current-chat]
:navigation {:on-press #(re-frame/dispatch [:navigate-to :home])} :navigation {:on-press #(re-frame/dispatch [:navigate-to :home])}
:right-accessories [{:icon :main-icons/more :right-accessories [{:icon :main-icons/more
:accessibility-label :chat-menu-button :accessibility-label :chat-menu-button

View File

@ -9,6 +9,7 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.home.styles :as styles] [status-im.ui.screens.home.styles :as styles]
[status-im.ui.screens.home.views.inner-item :as inner-item] [status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.screens.referrals.home-item :as referral-item]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat] [status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
[quo.core :as quo] [quo.core :as quo]
@ -18,6 +19,7 @@
[status-im.utils.debounce :as debounce] [status-im.utils.debounce :as debounce]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[cljs-bean.core :as bean] [cljs-bean.core :as bean]
[status-im.multiaccounts.login.core :as multiaccounts.login]
[status-im.ui.components.invite.views :as invite] [status-im.ui.components.invite.views :as invite]
[status-im.ui.components.topbar :as topbar] [status-im.ui.components.topbar :as topbar]
[status-im.ui.components.plus-button :as components.plus-button]) [status-im.ui.components.plus-button :as components.plus-button])
@ -45,8 +47,7 @@
[react/i18n-text {:style styles/welcome-text-description [react/i18n-text {:style styles/welcome-text-description
:key :welcome-to-status-description}]] :key :welcome-to-status-description}]]
[react/view {:align-items :center :margin-bottom 50} [react/view {:align-items :center :margin-bottom 50}
[quo/button {:on-press #(re-frame/dispatch [:navigate-reset {:index 0 [quo/button {:on-press #(re-frame/dispatch [::multiaccounts.login/welcome-lets-go])
:routes [{:name :tabs}]}])
:accessibility-label :lets-go-button} :accessibility-label :lets-go-button}
(i18n/label :t/lets-go)]]]) (i18n/label :t/lets-go)]]])
@ -152,8 +153,9 @@
:keyboard-should-persist-taps :always :keyboard-should-persist-taps :always
:data chats :data chats
:render-fn render-fn :render-fn render-fn
:header (when (or (seq chats) @search-active? (seq search-filter)) :header [:<> (when (or (seq chats) @search-active? (seq search-filter))
[search-input-wrapper search-filter chats]) [search-input-wrapper search-filter chats])
[referral-item/list-item]]
:empty-component (when (or @search-active? (seq search-filter)) :empty-component (when (or @search-active? (seq search-filter))
[start-suggestion search-filter]) [start-suggestion search-filter])
:footer (if (and (not hide-home-tooltip?) (not @search-active?)) :footer (if (and (not hide-home-tooltip?) (not @search-active?))

View File

@ -0,0 +1,60 @@
(ns status-im.ui.screens.referrals.home-item
(:require [status-im.acquisition.chat :as acquisition.chat]
[status-im.acquisition.core :as acquisition]
[quo.core :as quo]
[status-im.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[quo.react-native :as rn]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.utils.core :as utils]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.invite.events :as invite]))
(defn icon-style []
{:color colors/black
:width 15
:height 15
:container-style {:width 15
:height 15
:margin-right 2}})
(defn referral-sheet []
[quo/list-item
{:theme :negative
:title (i18n/label :t/delete-chat)
:accessibility-label :delete-chat-button
:icon :main-icons/delete
:on-press #(re-frame/dispatch [::acquisition.chat/decline])}])
(defn list-item []
(let [{:keys [id]} @(re-frame/subscribe [::acquisition/metadata])
{:keys [chat-id
chat-name
group-chat
color]} {:chat-name (str "#" id)
:chat-id id
:color "#887af9"
:public? true
:group-chat true}]
(when @(re-frame/subscribe [::invite/has-public-chat-invite])
[quo/list-item {:icon [chat-icon.screen/chat-icon-view-chat-list
chat-id group-chat chat-name color nil false]
:title [rn/view {:flex-direction :row
:flex 1}
[rn/view {:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
[icons/icon :main-icons/tiny-public (icon-style)]
[quo/text {:weight :medium
:accessibility-label :chat-name-text
:ellipsize-mode :tail
:number-of-lines 1}
(utils/truncate-str chat-name 30)]]]
:title-accessibility-label :chat-name-text
:subtitle (i18n/label :t/invite-public-chat-home)
:on-press #(re-frame/dispatch [:navigate-to :tabs {:screen :chat-stack
:params {:screen :referral-enclav}}])
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content referral-sheet}])}])))

View File

@ -0,0 +1,109 @@
(ns status-im.ui.screens.referrals.public-chat
(:require [status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
[re-frame.core :as re-frame]
[status-im.acquisition.chat :as chat.acquisition]
[status-im.acquisition.core :as acquisition]
[status-im.ui.components.invite.events :as invite]
[status-im.i18n :as i18n]
[status-im.acquisition.gateway :as gateway]
[quo.react-native :as rn]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.screens.chat.styles.main :as chat.styles]
[status-im.ui.components.invite.chat :as invite.chat]))
(defn non-reward []
(let [loading (#{(get gateway/network-statuses :initiated)
(get gateway/network-statuses :in-flight)}
@(re-frame/subscribe [::gateway/network-status]))]
[rn/view {:border-radius 16
:padding-horizontal 12
:padding-vertical 16
:justify-content :center
:align-items :center
:border-width 1
:border-color (colors/get-color :border-01)}
[rn/view
[icons/icon :main-icons/link {:color (colors/get-color :icon-04)}]]
[rn/view {:style {:padding-vertical 10}}
[quo/text {:color :secondary
:align :center}
(i18n/label :t/invite-privacy-policy-public) " "
[quo/text {:color :link
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]]
[rn/view {:padding-horizontal 16
:padding-vertival 8
:flex-direction :row}
[quo/button {:loading loading
:on-press #(re-frame/dispatch [::chat.acquisition/accept-pack])}
(i18n/label :t/invite-chat-accept-join)]]]))
(defn reward-messages []
(let [loading (#{(get gateway/network-statuses :initiated)
(get gateway/network-statuses :in-flight)}
@(re-frame/subscribe [::gateway/network-status]))
pending @(re-frame/subscribe [::invite/pending-reward])
messages [{:content [{:type :text
:value "👋"}]}
{:content [{:type :text
:value (i18n/label :t/invite-public-chat-intro)}
{:type :pack}
{:type :button
:value [quo/button {:type :secondary
:loading loading
:disabled pending
:on-press #(re-frame/dispatch [::chat.acquisition/accept-pack])}
(if pending
(i18n/label :t/invite-chat-pending)
(i18n/label :t/invite-chat-accept-join))]}]}
{:content [{:type :text
:value [:<>
(i18n/label :t/invite-privacy-policy-public) " "
[quo/text {:color :link
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]}]}]]
[rn/view {:style (invite.chat/messages-wrapper)}
(for [message messages]
[invite.chat/render-message message])]))
(defn view []
(let [{:keys [rewardable id]} @(re-frame/subscribe [::acquisition/metadata])
{:keys [chat-id
chat-name
group-chat
color]
:as chat-info} {:chat-name (str "#" id)
:color "#887af9"
:public? true
:group-chat true}]
[:<>
[topbar/topbar
{:content [toolbar-content/toolbar-content-view chat-info]
:navigation {:on-press #(re-frame/dispatch [:navigate-to :home])}}]
[rn/scroll-view {:style {:flex 1}
:center-content true
:content-container-style {:padding 16}}
[rn/view {:style {:flex 1
:justify-content :flex-end
:align-items :center
:padding-vertical 24}}
[rn/view {:style {:padding-vertical 16}}
[chat-icon.screen/chat-intro-icon-view
chat-name chat-id group-chat
{:default-chat-icon (chat.styles/intro-header-icon 120 color)
:default-chat-icon-text chat.styles/intro-header-icon-text
:size 120}]]
[rn/view {:style {:padding-horizontal 32
:padding-bottom 32}}
[quo/text {:size :x-large
:weight :bold}
chat-name]]]
(if rewardable
[reward-messages]
[non-reward])]]))

View File

@ -3,6 +3,7 @@
[status-im.ui.screens.home.views :as home] [status-im.ui.screens.home.views :as home]
[status-im.ui.screens.chat.views :as chat] [status-im.ui.screens.chat.views :as chat]
[status-im.ui.screens.group.views :as group] [status-im.ui.screens.group.views :as group]
[status-im.ui.screens.referrals.public-chat :as referrals.public-chat]
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat] [status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
[status-im.ui.components.tabbar.styles :as tabbar.styles] [status-im.ui.components.tabbar.styles :as tabbar.styles]
[status-im.ui.screens.stickers.views :as stickers])) [status-im.ui.screens.stickers.views :as stickers]))
@ -16,6 +17,8 @@
[{:name :home [{:name :home
:style {:padding-bottom tabbar.styles/tabs-diff} :style {:padding-bottom tabbar.styles/tabs-diff}
:component home/home} :component home/home}
{:name :referral-enclav
:component referrals.public-chat/view}
{:name :chat {:name :chat
:component chat/chat} :component chat/chat}
{:name :group-chat-profile {:name :group-chat-profile

View File

@ -23,7 +23,7 @@
(and (= (:error a) (:error b)) (and (= (:error a) (:error b))
(or (and (nil? (:amount a)) (or (and (nil? (:amount a))
(nil? (:amount b))) (nil? (:amount b)))
(.eq (:amount a) (:amount b))))) (.eq ^js (:amount a) (:amount b)))))
(deftest test-parse-amount (deftest test-parse-amount
(testing "test amount parsing" (testing "test amount parsing"

View File

@ -597,10 +597,15 @@
"invite-reward-friend-description": "Your friend will receive a Starter Pack consisting of some {{reward}} to get started", "invite-reward-friend-description": "Your friend will receive a Starter Pack consisting of some {{reward}} to get started",
"invite-privacy-policy1": "By accepting you agree to the referral program", "invite-privacy-policy1": "By accepting you agree to the referral program",
"invite-privacy-policy2": "Terms and Conditions.", "invite-privacy-policy2": "Terms and Conditions.",
"invite-privacy-policy-public": "You installed Status through a referral link. By joining this chat you attribute your referrer and agree to the",
"invite-chat-name": "Friend referral", "invite-chat-name": "Friend referral",
"invite-chat-starter-pack": "Starter Pack", "invite-chat-starter-pack": "Starter Pack",
"invite-chat-intro": "You were referred by a friend to join Status. Heres some crypto to get you started! Use it to register an ENS name or buy a sticker pack", "invite-chat-intro": "You were referred by a friend to join Status. Heres some crypto to get you started! Use it to register an ENS name or buy a sticker pack",
"invite-public-chat-home": "Referral invitation",
"invite-public-chat-intro": "Heres some crypto to get you started! Use it to register an ENS name or buy a sticker pack",
"invite-chat-accept": "Accept", "invite-chat-accept": "Accept",
"invite-chat-pending": "Pending",
"invite-chat-accept-join": "Accept and Join",
"invite-chat-rule": "Accepting will also reward your friend with a crypto referral bonus", "invite-chat-rule": "Accepting will also reward your friend with a crypto referral bonus",
"redeem-now": "Redeem now", "redeem-now": "Redeem now",
"redeem-amount": "{{quantity}} bonuses available", "redeem-amount": "{{quantity}} bonuses available",
@ -615,6 +620,8 @@
"dapp-starter-pack-title": "Starter Pack", "dapp-starter-pack-title": "Starter Pack",
"dapp-starter-pack-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps", "dapp-starter-pack-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps",
"dapp-starter-pack-accept": "Accept and Open", "dapp-starter-pack-accept": "Accept and Open",
"starter-pack-coming": "Starter Pack coming your way",
"starter-pack-coming-description": "Can take a few minutes to hours",
"starter-pack-received": "Starter Pack received", "starter-pack-received": "Starter Pack received",
"starter-pack-received-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps", "starter-pack-received-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps",
"join-group-chat": "Join group", "join-group-chat": "Join group",