mirror of
https://github.com/status-im/status-react.git
synced 2025-01-09 10:42:53 +00:00
feat(onboarding): Present Terms to users upgrading from v1 or those who need to accept updated Terms (#21487)
Cherry-pick d45eb5ec20
.
Fixes https://github.com/status-im/status-mobile/issues/21113
Related status-go PR: https://github.com/status-im/status-go/pull/5977
This commit is contained in:
parent
cac96b589f
commit
e1abe5c6e2
@ -253,6 +253,11 @@ class AccountManager(private val reactContext: ReactApplicationContext) : ReactC
|
|||||||
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
|
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
private fun acceptTerms(callback: Callback) {
|
||||||
|
Log.d(TAG, "acceptTerms")
|
||||||
|
utils.executeRunnableStatusGoMethod({ Statusgo.acceptTerms() }, callback)
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
fun logout() {
|
fun logout() {
|
||||||
|
@ -204,6 +204,14 @@ RCT_EXPORT_METHOD(initializeApplication:(NSString *)request
|
|||||||
callback(@[result]);
|
callback(@[result]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(acceptTerms:(RCTResponseSenderBlock)callback) {
|
||||||
|
#if DEBUG
|
||||||
|
NSLog(@"acceptTerms() method called");
|
||||||
|
#endif
|
||||||
|
NSString *result = StatusgoAcceptTerms();
|
||||||
|
callback(@[result]);
|
||||||
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
NSLog(@"OpenAccounts() method called");
|
NSLog(@"OpenAccounts() method called");
|
||||||
|
@ -761,6 +761,26 @@ void _Logout(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _AcceptTerms(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
|
||||||
|
if (args.Length() != 0) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for AcceptTerms")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = AcceptTerms();
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
|
||||||
void _HashMessage(const FunctionCallbackInfo<Value>& args) {
|
void _HashMessage(const FunctionCallbackInfo<Value>& args) {
|
||||||
Isolate* isolate = args.GetIsolate();
|
Isolate* isolate = args.GetIsolate();
|
||||||
Local<Context> context = isolate->GetCurrentContext();
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
@ -1998,6 +2018,7 @@ void init(Local<Object> exports) {
|
|||||||
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
|
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
|
||||||
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
||||||
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
|
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
|
||||||
|
NODE_SET_METHOD(exports, "acceptTerms", _AcceptTerms);
|
||||||
NODE_SET_METHOD(exports, "fleets", _Fleets);
|
NODE_SET_METHOD(exports, "fleets", _Fleets);
|
||||||
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
||||||
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
|
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
|
||||||
|
@ -79,6 +79,12 @@
|
|||||||
(types/clj->json request)
|
(types/clj->json request)
|
||||||
#(callback (types/json->clj %))))
|
#(callback (types/json->clj %))))
|
||||||
|
|
||||||
|
(defn accept-terms
|
||||||
|
([]
|
||||||
|
(native-utils/promisify-native-module-call accept-terms))
|
||||||
|
([callback]
|
||||||
|
(.acceptTerms ^js (account-manager) callback)))
|
||||||
|
|
||||||
(defn prepare-dir-and-update-config
|
(defn prepare-dir-and-update-config
|
||||||
[key-uid config callback]
|
[key-uid config callback]
|
||||||
(log/debug "[native-module] prepare-dir-and-update-config")
|
(log/debug "[native-module] prepare-dir-and-update-config")
|
||||||
|
@ -11,17 +11,17 @@
|
|||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn view
|
(defn- show-terms-of-use
|
||||||
[]
|
[]
|
||||||
(let [[terms-accepted? set-terms-accepted?] (rn/use-state false)]
|
(rf/dispatch [:show-bottom-sheet {:content terms/terms-of-use :shell? true}]))
|
||||||
[rn/view {:style style/page-container}
|
|
||||||
[background/view false]
|
(defn- show-privacy-policy
|
||||||
[quo/bottom-actions
|
[]
|
||||||
{:container-style (style/bottom-actions-container (safe-area/get-bottom))
|
(rf/dispatch [:show-bottom-sheet {:content privacy/privacy-statement :shell? true}]))
|
||||||
:actions :two-vertical-actions
|
|
||||||
:description :top
|
(defn- terms
|
||||||
:description-top-text [rn/view
|
[terms-accepted? set-terms-accepted?]
|
||||||
{:style style/terms-privacy-container}
|
[rn/view {:style style/terms-privacy-container}
|
||||||
[rn/view
|
[rn/view
|
||||||
{:accessibility-label :terms-privacy-checkbox-container}
|
{:accessibility-label :terms-privacy-checkbox-container}
|
||||||
[quo/selectors
|
[quo/selectors
|
||||||
@ -35,9 +35,7 @@
|
|||||||
:size :paragraph-2}
|
:size :paragraph-2}
|
||||||
(str (i18n/label :t/accept-status-tos-prefix) " ")]
|
(str (i18n/label :t/accept-status-tos-prefix) " ")]
|
||||||
[quo/text
|
[quo/text
|
||||||
{:on-press #(rf/dispatch [:show-bottom-sheet
|
{:on-press show-terms-of-use
|
||||||
{:content terms/terms-of-use
|
|
||||||
:shell? true}])
|
|
||||||
:style style/highlighted-text
|
:style style/highlighted-text
|
||||||
:size :paragraph-2
|
:size :paragraph-2
|
||||||
:weight :medium}
|
:weight :medium}
|
||||||
@ -47,30 +45,59 @@
|
|||||||
:size :paragraph-2}
|
:size :paragraph-2}
|
||||||
" " (i18n/label :t/and) " "]
|
" " (i18n/label :t/and) " "]
|
||||||
[quo/text
|
[quo/text
|
||||||
{:on-press #(rf/dispatch [:show-bottom-sheet
|
{:on-press show-privacy-policy
|
||||||
{:content privacy/privacy-statement
|
|
||||||
:shell? true}])
|
|
||||||
:style style/highlighted-text
|
:style style/highlighted-text
|
||||||
:size :paragraph-2
|
:size :paragraph-2
|
||||||
:weight :medium}
|
:weight :medium}
|
||||||
(i18n/label :t/intro-privacy-policy)]]]
|
(i18n/label :t/intro-privacy-policy)]]])
|
||||||
|
|
||||||
|
(defn- explore-new-status
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:profile/explore-new-status]))
|
||||||
|
|
||||||
|
(defn- sync-or-recover-profile
|
||||||
|
[]
|
||||||
|
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
|
||||||
|
(blur-show-fn))
|
||||||
|
(rf/dispatch [:open-modal :screen/onboarding.sync-or-recover-profile]))
|
||||||
|
|
||||||
|
(defn- create-profile
|
||||||
|
[]
|
||||||
|
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
|
||||||
|
(blur-show-fn))
|
||||||
|
(rf/dispatch [:open-modal :screen/onboarding.new-to-status]))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
(let [[terms-accepted? set-terms-accepted?] (rn/use-state false)
|
||||||
|
has-profiles-and-unaccepted-terms? (rf/sub [:profile/has-profiles-and-unaccepted-terms?])]
|
||||||
|
[rn/view {:style style/page-container}
|
||||||
|
[background/view false]
|
||||||
|
[quo/bottom-actions
|
||||||
|
(cond->
|
||||||
|
{:container-style (style/bottom-actions-container (safe-area/get-bottom))
|
||||||
|
:actions :two-vertical-actions
|
||||||
|
:description :top
|
||||||
|
:description-top-text [terms terms-accepted? set-terms-accepted?]}
|
||||||
|
|
||||||
|
has-profiles-and-unaccepted-terms?
|
||||||
|
(assoc
|
||||||
|
:actions :one-action
|
||||||
|
:button-one-label (i18n/label :t/explore-the-new-status)
|
||||||
|
:button-one-props {:disabled? (not terms-accepted?)
|
||||||
|
:accessibility-label :explore-new-status
|
||||||
|
:on-press explore-new-status})
|
||||||
|
|
||||||
|
(not has-profiles-and-unaccepted-terms?)
|
||||||
|
(assoc
|
||||||
|
:actions :two-vertical-actions
|
||||||
:button-one-label (i18n/label :t/sync-or-recover-profile)
|
:button-one-label (i18n/label :t/sync-or-recover-profile)
|
||||||
:button-one-props {:type :dark-grey
|
:button-one-props {:type :dark-grey
|
||||||
:disabled? (not terms-accepted?)
|
:disabled? (not terms-accepted?)
|
||||||
:accessibility-label :already-use-status-button
|
:accessibility-label :already-use-status-button
|
||||||
:on-press (fn []
|
:on-press sync-or-recover-profile}
|
||||||
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
|
|
||||||
(blur-show-fn))
|
|
||||||
(rf/dispatch
|
|
||||||
[:open-modal
|
|
||||||
:screen/onboarding.sync-or-recover-profile]))}
|
|
||||||
:button-two-label (i18n/label :t/create-profile)
|
:button-two-label (i18n/label :t/create-profile)
|
||||||
:button-two-props {:accessibility-label :new-to-status-button
|
:button-two-props {:accessibility-label :new-to-status-button
|
||||||
:disabled? (not terms-accepted?)
|
:disabled? (not terms-accepted?)
|
||||||
:on-press
|
:on-press create-profile}))]
|
||||||
(fn []
|
|
||||||
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
|
|
||||||
(blur-show-fn))
|
|
||||||
(rf/dispatch
|
|
||||||
[:open-modal :screen/onboarding.new-to-status]))}}]
|
|
||||||
[overlay/view]]))
|
[overlay/view]]))
|
||||||
|
5
src/status_im/contexts/profile/data_store.cljs
Normal file
5
src/status_im/contexts/profile/data_store.cljs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
(ns status-im.contexts.profile.data-store)
|
||||||
|
|
||||||
|
(defn accepted-terms?
|
||||||
|
[accounts]
|
||||||
|
(some :hasAcceptedTerms accounts))
|
14
src/status_im/contexts/profile/effects.cljs
Normal file
14
src/status_im/contexts/profile/effects.cljs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(ns status-im.contexts.profile.effects
|
||||||
|
(:require
|
||||||
|
[native-module.core :as native-module]
|
||||||
|
[promesa.core :as promesa]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(rf/reg-fx :effects.profile/accept-terms
|
||||||
|
(fn [{:keys [on-success]}]
|
||||||
|
(-> (native-module/accept-terms)
|
||||||
|
(promesa/then (fn []
|
||||||
|
(rf/call-continuation on-success)))
|
||||||
|
(promesa/catch (fn [error]
|
||||||
|
(log/error "Failed to accept terms" {:error error}))))))
|
@ -4,10 +4,12 @@
|
|||||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[status-im.config :as config]
|
[status-im.config :as config]
|
||||||
|
[status-im.contexts.profile.data-store :as profile.data-store]
|
||||||
[status-im.contexts.profile.edit.accent-colour.events]
|
[status-im.contexts.profile.edit.accent-colour.events]
|
||||||
[status-im.contexts.profile.edit.bio.events]
|
[status-im.contexts.profile.edit.bio.events]
|
||||||
[status-im.contexts.profile.edit.header.events]
|
[status-im.contexts.profile.edit.header.events]
|
||||||
[status-im.contexts.profile.edit.name.events]
|
[status-im.contexts.profile.edit.name.events]
|
||||||
|
status-im.contexts.profile.effects
|
||||||
status-im.contexts.profile.login.events
|
status-im.contexts.profile.login.events
|
||||||
[status-im.contexts.profile.rpc :as profile.rpc]
|
[status-im.contexts.profile.rpc :as profile.rpc]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
@ -44,24 +46,25 @@
|
|||||||
(fn [{:keys [db]} [{:keys [accounts] {:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
(fn [{:keys [db]} [{:keys [accounts] {:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
||||||
(let [db-with-settings (assoc db
|
(let [db-with-settings (assoc db
|
||||||
:centralized-metrics/user-confirmed? userConfirmed
|
:centralized-metrics/user-confirmed? userConfirmed
|
||||||
:centralized-metrics/enabled? enabled)]
|
:centralized-metrics/enabled? enabled)
|
||||||
(if (seq accounts)
|
profiles (reduce-profiles accounts)
|
||||||
(let [profiles (reduce-profiles accounts)
|
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))
|
||||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))]
|
new-db (cond-> db-with-settings
|
||||||
{:db (if key-uid
|
(seq profiles)
|
||||||
(-> db-with-settings
|
|
||||||
(assoc :profile/profiles-overview profiles)
|
(assoc :profile/profiles-overview profiles)
|
||||||
(update :profile/login #(select-profile % key-uid)))
|
|
||||||
db-with-settings)
|
key-uid
|
||||||
:fx [[:dispatch [:update-theme-and-init-root :screen/profile.profiles]]
|
(update :profile/login #(select-profile % key-uid)))]
|
||||||
|
{:db new-db
|
||||||
|
:fx (if (profile.data-store/accepted-terms? accounts)
|
||||||
|
[[:dispatch [:update-theme-and-init-root :screen/profile.profiles]]
|
||||||
(when (and key-uid userConfirmed)
|
(when (and key-uid userConfirmed)
|
||||||
[:effects.biometric/check-if-available
|
[:effects.biometric/check-if-available
|
||||||
{:key-uid key-uid
|
{:key-uid key-uid
|
||||||
:on-success (fn [auth-method]
|
:on-success (fn [auth-method]
|
||||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
||||||
auth-method]))}])]})
|
auth-method]))}])]
|
||||||
{:db db-with-settings
|
[[:dispatch [:update-theme-and-init-root :screen/onboarding.intro]]])})))
|
||||||
:fx [[:dispatch [:update-theme-and-init-root :screen/onboarding.intro]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:profile/update-setting-from-backup
|
:profile/update-setting-from-backup
|
||||||
@ -82,3 +85,8 @@
|
|||||||
:messages-from-contacts-only
|
:messages-from-contacts-only
|
||||||
(not (get-in db [:profile/profile :messages-from-contacts-only]))
|
(not (get-in db [:profile/profile :messages-from-contacts-only]))
|
||||||
{})))
|
{})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :profile/explore-new-status
|
||||||
|
(fn []
|
||||||
|
{:fx [[:effects.profile/accept-terms
|
||||||
|
{:on-success [:navigate-to :screen/profile.profiles]}]]}))
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.common.pixel-ratio :as pixel-ratio]
|
[status-im.common.pixel-ratio :as pixel-ratio]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
|
[status-im.contexts.profile.data-store :as profile.data-store]
|
||||||
[status-im.contexts.profile.utils :as profile.utils]
|
[status-im.contexts.profile.utils :as profile.utils]
|
||||||
[utils.security.core :as security]))
|
[utils.security.core :as security]))
|
||||||
|
|
||||||
@ -17,6 +18,15 @@
|
|||||||
(fn [{:keys [customization-color]}]
|
(fn [{:keys [customization-color]}]
|
||||||
(or customization-color constants/profile-default-color)))
|
(or customization-color constants/profile-default-color)))
|
||||||
|
|
||||||
|
;; A profile can only be created without accepting terms in Status v1. In Status
|
||||||
|
;; v2, the terms may be unaccepted because we intentionally created a migration
|
||||||
|
;; resetting the flag in case the privacy policy changed.
|
||||||
|
(re-frame/reg-sub :profile/has-profiles-and-unaccepted-terms?
|
||||||
|
:<- [:profile/profiles-overview]
|
||||||
|
(fn [profiles-overview]
|
||||||
|
(and (seq profiles-overview)
|
||||||
|
(not (profile.data-store/accepted-terms? (vals profiles-overview))))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:profile/currency
|
:profile/currency
|
||||||
:<- [:profile/profile]
|
:<- [:profile/profile]
|
||||||
|
@ -70,6 +70,9 @@
|
|||||||
{:initializeApplication
|
{:initializeApplication
|
||||||
(fn [request callback]
|
(fn [request callback]
|
||||||
(callback (.initializeApplication native-status request)))
|
(callback (.initializeApplication native-status request)))
|
||||||
|
:acceptTerms
|
||||||
|
(fn [callback]
|
||||||
|
(callback (.acceptTerms native-status)))
|
||||||
:createAccountAndLogin
|
:createAccountAndLogin
|
||||||
(fn [request] (.createAccountAndLogin native-status request))
|
(fn [request] (.createAccountAndLogin native-status request))
|
||||||
:restoreAccountAndLogin
|
:restoreAccountAndLogin
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v3.3.0",
|
"version": "v3.5.0",
|
||||||
"commit-sha1": "43659f0c7e1a64102e7f8e38bd532b72714c5819",
|
"commit-sha1": "39511298cdc8f50e7659ac8079d5bc8a4763ddc7",
|
||||||
"src-sha256": "01fpviw1g22f4ni3li2wnhyz0l517jfipvnyfysckds6yi94l0hf"
|
"src-sha256": "1nn8gq9d91ix5mzndr306rq3n68rzj4drym3pfaxzaa73k4v9r07"
|
||||||
}
|
}
|
||||||
|
@ -1002,6 +1002,7 @@
|
|||||||
"expand-all": "Expand all",
|
"expand-all": "Expand all",
|
||||||
"experienced-web3": "Experienced in Web3?",
|
"experienced-web3": "Experienced in Web3?",
|
||||||
"explore-the-decentralized-web": "Explore and interact with the decentralized web",
|
"explore-the-decentralized-web": "Explore and interact with the decentralized web",
|
||||||
|
"explore-the-new-status": "Explore the new Status",
|
||||||
"export-account": "Export account",
|
"export-account": "Export account",
|
||||||
"export-key": "Export private key",
|
"export-key": "Export private key",
|
||||||
"external-link": "External link",
|
"external-link": "External link",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user