Compare commits
5 Commits
f1dac2a096
...
3eaa30d7aa
Author | SHA1 | Date |
---|---|---|
Hans-Christoph Steiner | 3eaa30d7aa | |
Mateusz Armatys | 317c12fdd4 | |
Neil Marietta | 64c3b4de6f | |
Neil Marietta | 2c4b8e9aba | |
Hans-Christoph Steiner | b04c52a486 |
|
@ -2,6 +2,10 @@ public class hilt_aggregated_deps/_me_proton_core_auth_presentation_MissingScope
|
|||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_alert_CancelCreateAccountDialog_GeneratedInjector {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_alert_confirmpass_ConfirmPasswordDialog_GeneratedInjector {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
@ -94,6 +98,14 @@ public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_Ad
|
|||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_CancelCreateAccountDialogViewModel_HiltModules_BindsModule {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_CancelCreateAccountDialogViewModel_HiltModules_KeyModule {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_ChooseAddressViewModel_HiltModules_BindsModule {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
@ -342,6 +354,29 @@ public final class me/proton/core/auth/presentation/alert/AlertUtilsKt {
|
|||
public static synthetic fun showPasswordEnterDialog$default (Landroidx/fragment/app/FragmentManager;ZZZILjava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/alert/CancelCreateAccountDialog : androidx/fragment/app/DialogFragment {
|
||||
public fun <init> ()V
|
||||
public fun onCreateDialog (Landroid/os/Bundle;)Landroid/app/Dialog;
|
||||
public final fun show (Landroidx/fragment/app/FragmentManager;Lkotlin/jvm/functions/Function0;)V
|
||||
}
|
||||
|
||||
public abstract interface class me/proton/core/auth/presentation/alert/CancelCreateAccountDialog_GeneratedInjector {
|
||||
public abstract fun injectCancelCreateAccountDialog (Lme/proton/core/auth/presentation/alert/CancelCreateAccountDialog;)V
|
||||
}
|
||||
|
||||
public abstract class me/proton/core/auth/presentation/alert/Hilt_CancelCreateAccountDialog : androidx/fragment/app/DialogFragment, dagger/hilt/internal/GeneratedComponentManagerHolder {
|
||||
public final fun componentManager ()Ldagger/hilt/android/internal/managers/FragmentComponentManager;
|
||||
public synthetic fun componentManager ()Ldagger/hilt/internal/GeneratedComponentManager;
|
||||
protected fun createComponentManager ()Ldagger/hilt/android/internal/managers/FragmentComponentManager;
|
||||
public final fun generatedComponent ()Ljava/lang/Object;
|
||||
public fun getContext ()Landroid/content/Context;
|
||||
public fun getDefaultViewModelProviderFactory ()Landroidx/lifecycle/ViewModelProvider$Factory;
|
||||
protected fun inject ()V
|
||||
public fun onAttach (Landroid/app/Activity;)V
|
||||
public fun onAttach (Landroid/content/Context;)V
|
||||
public fun onGetLayoutInflater (Landroid/os/Bundle;)Landroid/view/LayoutInflater;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/alert/PasswordAnd2FADialog : androidx/fragment/app/DialogFragment {
|
||||
public static final field BUNDLE_KEY_PASS_2FA_DATA Ljava/lang/String;
|
||||
public static final field Companion Lme/proton/core/auth/presentation/alert/PasswordAnd2FADialog$Companion;
|
||||
|
@ -554,6 +589,16 @@ public final class me/proton/core/auth/presentation/databinding/ContentHelpItemO
|
|||
public static fun inflate (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Z)Lme/proton/core/auth/presentation/databinding/ContentHelpItemOtherIssuesBinding;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/databinding/DialogCancelCreationBinding : androidx/viewbinding/ViewBinding {
|
||||
public final field cancelButton Lme/proton/core/presentation/ui/view/ProtonButton;
|
||||
public final field continueButton Lme/proton/core/presentation/ui/view/ProtonButton;
|
||||
public static fun bind (Landroid/view/View;)Lme/proton/core/auth/presentation/databinding/DialogCancelCreationBinding;
|
||||
public synthetic fun getRoot ()Landroid/view/View;
|
||||
public fun getRoot ()Landroidx/constraintlayout/widget/ConstraintLayout;
|
||||
public static fun inflate (Landroid/view/LayoutInflater;)Lme/proton/core/auth/presentation/databinding/DialogCancelCreationBinding;
|
||||
public static fun inflate (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Z)Lme/proton/core/auth/presentation/databinding/DialogCancelCreationBinding;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/databinding/DialogConfirmPasswordBinding : androidx/viewbinding/ViewBinding {
|
||||
public final field cancelButton Lme/proton/core/presentation/ui/view/ProtonButton;
|
||||
public final field enterButton Lme/proton/core/presentation/ui/view/ProtonProgressButton;
|
||||
|
@ -2140,6 +2185,38 @@ public final class me/proton/core/auth/presentation/viewmodel/AddAccountViewMode
|
|||
public static fun provide ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel : me/proton/core/presentation/viewmodel/ProtonViewModel {
|
||||
public fun <init> (Lme/proton/core/accountmanager/domain/AccountWorkflowHandler;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/util/kotlin/CoroutineScopeProvider;)V
|
||||
public final fun cancelCreation ()Lkotlinx/coroutines/Job;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_Factory : dagger/internal/Factory {
|
||||
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
|
||||
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_Factory;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public fun get ()Lme/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel;
|
||||
public static fun newInstance (Lme/proton/core/accountmanager/domain/AccountWorkflowHandler;Lme/proton/core/accountmanager/domain/AccountManager;Lme/proton/core/util/kotlin/CoroutineScopeProvider;)Lme/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_HiltModules {
|
||||
}
|
||||
|
||||
public abstract class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_HiltModules$BindsModule {
|
||||
public abstract fun binds (Lme/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel;)Landroidx/lifecycle/ViewModel;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_HiltModules$KeyModule {
|
||||
public static fun provide ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_HiltModules_KeyModule_ProvideFactory : dagger/internal/Factory {
|
||||
public fun <init> ()V
|
||||
public static fun create ()Lme/proton/core/auth/presentation/viewmodel/CancelCreateAccountDialogViewModel_HiltModules_KeyModule_ProvideFactory;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public fun get ()Ljava/lang/String;
|
||||
public static fun provide ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class me/proton/core/auth/presentation/viewmodel/ChooseAddressViewModel : me/proton/core/presentation/viewmodel/ProtonViewModel, me/proton/core/observability/domain/ObservabilityContext {
|
||||
public fun <init> (Lme/proton/core/accountmanager/domain/AccountWorkflowHandler;Lme/proton/core/auth/domain/usecase/AccountAvailability;Lme/proton/core/observability/domain/ObservabilityManager;Lme/proton/core/auth/domain/usecase/PostLoginAccountSetup;Lme/proton/core/usersettings/domain/usecase/SetupUsername;)V
|
||||
public fun enqueueObservability (Lme/proton/core/observability/domain/metrics/ObservabilityData;)V
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.auth.presentation.alert
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import me.proton.core.auth.presentation.R
|
||||
import me.proton.core.auth.presentation.databinding.DialogCancelCreationBinding
|
||||
import me.proton.core.auth.presentation.viewmodel.CancelCreateAccountDialogViewModel
|
||||
import me.proton.core.presentation.utils.onClick
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CancelCreateAccountDialog : DialogFragment() {
|
||||
|
||||
private val viewModel by viewModels<CancelCreateAccountDialogViewModel>()
|
||||
|
||||
private var onCreationCancelled: (() -> Unit)? = null
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
super.onCreateDialog(savedInstanceState)
|
||||
val binding = DialogCancelCreationBinding.inflate(LayoutInflater.from(requireContext()))
|
||||
// Buttons are in a custom View to avoid dismissing dialog on click (cancel scope).
|
||||
binding.continueButton.onClick {
|
||||
dismiss()
|
||||
}
|
||||
binding.cancelButton.onClick {
|
||||
viewModel.cancelCreation().invokeOnCompletion {
|
||||
dismiss()
|
||||
onCreationCancelled?.invoke()
|
||||
}
|
||||
}
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.auth_signup_create_account_dialog_title)
|
||||
.setMessage(R.string.auth_signup_create_account_dialog_text)
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
}
|
||||
|
||||
fun show(fragmentManager: FragmentManager, onCreationCancelled: () -> Unit) {
|
||||
this.onCreationCancelled = onCreationCancelled
|
||||
show(fragmentManager, null)
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.onEach
|
|||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.account.domain.entity.AccountType
|
||||
import me.proton.core.auth.presentation.R
|
||||
import me.proton.core.auth.presentation.alert.CancelCreateAccountDialog
|
||||
import me.proton.core.auth.presentation.databinding.FragmentSignupChooseExternalEmailBinding
|
||||
import me.proton.core.auth.presentation.entity.signup.SubscriptionDetails
|
||||
import me.proton.core.auth.presentation.ui.onLongState
|
||||
|
@ -96,7 +97,10 @@ class ChooseExternalEmailFragment : SignupFragment(R.layout.fragment_signup_choo
|
|||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
} else {
|
||||
showError(getString(R.string.auth_signup_error_create_to_continue))
|
||||
CancelCreateAccountDialog().show(parentFragmentManager) {
|
||||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +108,7 @@ class ChooseExternalEmailFragment : SignupFragment(R.layout.fragment_signup_choo
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.apply {
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, cancellable)
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, true)
|
||||
toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||
|
||||
emailInput.text = email
|
||||
|
|
|
@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.onEach
|
|||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.account.domain.entity.AccountType
|
||||
import me.proton.core.auth.presentation.R
|
||||
import me.proton.core.auth.presentation.alert.CancelCreateAccountDialog
|
||||
import me.proton.core.auth.presentation.databinding.FragmentSignupChooseInternalEmailBinding
|
||||
import me.proton.core.auth.presentation.ui.onLongState
|
||||
import me.proton.core.auth.presentation.viewmodel.signup.ChooseInternalEmailViewModel
|
||||
|
@ -90,7 +91,10 @@ class ChooseInternalEmailFragment : SignupFragment(R.layout.fragment_signup_choo
|
|||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
} else {
|
||||
showError(getString(R.string.auth_signup_error_create_to_continue))
|
||||
CancelCreateAccountDialog().show(parentFragmentManager) {
|
||||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +102,7 @@ class ChooseInternalEmailFragment : SignupFragment(R.layout.fragment_signup_choo
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.apply {
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, cancellable)
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, true)
|
||||
toolbar.setNavigationOnClickListener { requireActivity().onBackPressedDispatcher.onBackPressed() }
|
||||
|
||||
usernameInput.apply {
|
||||
|
|
|
@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.onEach
|
|||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.account.domain.entity.AccountType
|
||||
import me.proton.core.auth.presentation.R
|
||||
import me.proton.core.auth.presentation.alert.CancelCreateAccountDialog
|
||||
import me.proton.core.auth.presentation.databinding.FragmentSignupChooseUsernameBinding
|
||||
import me.proton.core.auth.presentation.ui.onLongState
|
||||
import me.proton.core.auth.presentation.viewmodel.signup.ChooseUsernameViewModel
|
||||
|
@ -63,7 +64,10 @@ class ChooseUsernameFragment : SignupFragment(R.layout.fragment_signup_choose_us
|
|||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
} else {
|
||||
showError(getString(R.string.auth_signup_error_create_to_continue))
|
||||
CancelCreateAccountDialog().show(parentFragmentManager) {
|
||||
signupViewModel.onFinish()
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +75,7 @@ class ChooseUsernameFragment : SignupFragment(R.layout.fragment_signup_choose_us
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.apply {
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, cancellable)
|
||||
toolbar.setNavigationIcon(R.drawable.ic_proton_close, true)
|
||||
toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||
|
||||
usernameInput.apply {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.auth.presentation.viewmodel
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.accountmanager.domain.AccountManager
|
||||
import me.proton.core.accountmanager.domain.AccountWorkflowHandler
|
||||
import me.proton.core.presentation.viewmodel.ProtonViewModel
|
||||
import me.proton.core.util.kotlin.CoroutineScopeProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class CancelCreateAccountDialogViewModel @Inject constructor(
|
||||
private val accountWorkflowHandler: AccountWorkflowHandler,
|
||||
private val accountManager: AccountManager,
|
||||
private val scopeProvider: CoroutineScopeProvider
|
||||
) : ProtonViewModel() {
|
||||
|
||||
fun cancelCreation() = scopeProvider.GlobalDefaultSupervisedScope.launch {
|
||||
accountManager.getPrimaryUserId().firstOrNull()?.let {
|
||||
accountWorkflowHandler.handleCreateAccountFailed(it)
|
||||
accountManager.disableAccount(it, keepSession = true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (c) 2024 Proton AG
|
||||
~ This file is part of Proton AG and ProtonCore.
|
||||
~
|
||||
~ ProtonCore is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ ProtonCore is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/default_margin">
|
||||
|
||||
<me.proton.core.presentation.ui.view.ProtonButton
|
||||
android:id="@+id/continueButton"
|
||||
style="@style/ProtonButton.Borderless.Text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/auth_signup_create_account_dialog_action_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<me.proton.core.presentation.ui.view.ProtonButton
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/ProtonButton.Borderless.Text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/auth_signup_create_account_dialog_action_cancel"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/continueButton"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -132,6 +132,11 @@
|
|||
<string name="auth_signup_set_recovery">Set recovery method</string>
|
||||
<string name="auth_signup_no_connectivity">No connectivity to display Terms and Conditions.</string>
|
||||
<string name="auth_signup_error_create_to_continue">Please create an account to continue</string>
|
||||
<string name="auth_signup_error_create_to_continue_action_learn_more">Learn more</string>
|
||||
<string name="auth_signup_create_account_dialog_title">Activate your subscription</string>
|
||||
<string name="auth_signup_create_account_dialog_text">Your Google Pay payment was successfully processed. To activate your subscription, please create your Proton account.</string>
|
||||
<string name="auth_signup_create_account_dialog_action_cancel">Cancel</string>
|
||||
<string name="auth_signup_create_account_dialog_action_continue">Continue</string>
|
||||
<string name="auth_signup_error_username_blank">Username must not be blank.</string>
|
||||
<string name="auth_signup_error_passwords_do_not_match">Passwords do not match.</string>
|
||||
<string name="auth_signup_validation_password_length">Password should be at least 8 characters long.</string>
|
||||
|
|
|
@ -175,11 +175,14 @@ public final class me/proton/core/network/domain/ApiResultKt {
|
|||
public static final fun hasProtonErrorCode (Lme/proton/core/network/domain/ApiException;I)Z
|
||||
public static final fun isForceUpdate (Lme/proton/core/network/domain/ApiException;)Z
|
||||
public static final fun isForceUpdate (Lme/proton/core/network/domain/ApiResult;)Z
|
||||
public static final fun isHttpError (Lme/proton/core/network/domain/ApiException;I)Z
|
||||
public static final fun isHttpError (Lme/proton/core/network/domain/ApiResult;I)Z
|
||||
public static final fun isPotentialBlocking (Ljava/lang/Throwable;)Z
|
||||
public static final fun isRetryable (Lme/proton/core/network/domain/ApiException;)Z
|
||||
public static final fun isRetryable (Lme/proton/core/network/domain/ApiResult;)Z
|
||||
public static final fun isUnauthorized (Lme/proton/core/network/domain/ApiException;)Z
|
||||
public static final fun isUnauthorized (Lme/proton/core/network/domain/ApiResult;)Z
|
||||
public static final fun isUnprocessable (Lme/proton/core/network/domain/ApiException;)Z
|
||||
public static final fun onError (Lme/proton/core/network/domain/ApiResult;Lkotlin/jvm/functions/Function1;)Lme/proton/core/network/domain/ApiResult;
|
||||
public static final fun onParseError (Lme/proton/core/network/domain/ApiResult;Lkotlin/jvm/functions/Function1;)Lme/proton/core/network/domain/ApiResult;
|
||||
public static final fun onParseErrorLog (Lme/proton/core/network/domain/ApiResult;Ljava/lang/String;)Lme/proton/core/network/domain/ApiResult;
|
||||
|
|
|
@ -167,19 +167,34 @@ fun ApiException.hasProtonErrorCode(code: Int): Boolean =
|
|||
(error as? ApiResult.Error.Http)?.proton?.code == code
|
||||
|
||||
/**
|
||||
* Return true if [ApiException.error] is an unauthorized error (401).
|
||||
* Return true if [ApiException.error] is a http error equals [code].
|
||||
*
|
||||
* @see ApiResult.isUnauthorized
|
||||
* @see ApiResult.isHttpError
|
||||
*/
|
||||
fun ApiException.isUnauthorized(): Boolean = error.isUnauthorized()
|
||||
fun ApiException.isHttpError(code: Int): Boolean = error.isHttpError(code)
|
||||
|
||||
/**
|
||||
* Return true if [ApiResult] is a http error equals [code].
|
||||
*/
|
||||
fun <T> ApiResult<T>.isHttpError(code: Int): Boolean {
|
||||
val httpError = this as? ApiResult.Error.Http
|
||||
return httpError?.httpCode == code
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if [ApiResult] is an unauthorized error (401).
|
||||
*/
|
||||
fun <T> ApiResult<T>.isUnauthorized(): Boolean {
|
||||
val httpError = this as? ApiResult.Error.Http
|
||||
return httpError?.httpCode == HttpResponseCodes.HTTP_UNAUTHORIZED
|
||||
}
|
||||
fun <T> ApiResult<T>.isUnauthorized(): Boolean = isHttpError(HttpResponseCodes.HTTP_UNAUTHORIZED)
|
||||
|
||||
/**
|
||||
* Return true if [ApiException.error] is an unauthorized error (401).
|
||||
*/
|
||||
fun ApiException.isUnauthorized(): Boolean = isHttpError(HttpResponseCodes.HTTP_UNAUTHORIZED)
|
||||
|
||||
/**
|
||||
* Return true if [ApiException.error] is an unprocessable error (422).
|
||||
*/
|
||||
fun ApiException.isUnprocessable() = isHttpError(HttpResponseCodes.HTTP_UNPROCESSABLE)
|
||||
|
||||
/**
|
||||
* Return true if [ApiException.error] is a force update error (5003/5005).
|
||||
|
|
|
@ -29,7 +29,7 @@ protonBuild {
|
|||
}
|
||||
|
||||
protonCoverage {
|
||||
branchCoveragePercentage.set(51)
|
||||
branchCoveragePercentage.set(48)
|
||||
lineCoveragePercentage.set(59)
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,13 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedInject
|
||||
import me.proton.core.network.domain.ApiException
|
||||
import me.proton.core.network.domain.isRetryable
|
||||
import me.proton.core.network.domain.isUnprocessable
|
||||
import me.proton.core.network.domain.session.SessionProvider
|
||||
import me.proton.core.observability.domain.ObservabilityContext
|
||||
import me.proton.core.observability.domain.ObservabilityManager
|
||||
import me.proton.core.payment.domain.MAX_PLAN_QUANTITY
|
||||
import me.proton.core.payment.domain.entity.PaymentTokenEntity
|
||||
import me.proton.core.payment.domain.entity.Purchase
|
||||
import me.proton.core.payment.domain.entity.PurchaseState
|
||||
import me.proton.core.payment.domain.entity.SubscriptionCycle
|
||||
import me.proton.core.payment.domain.extension.getSubscribeObservabilityData
|
||||
|
@ -78,25 +80,42 @@ internal class SubscribePurchaseWorker @AssistedInject constructor(
|
|||
subscriptionManagement = SubscriptionManagement.GOOGLE_MANAGED
|
||||
)
|
||||
}.fold(
|
||||
onSuccess = {
|
||||
purchaseRepository.upsertPurchase(purchase.copy(purchaseState = PurchaseState.Subscribed))
|
||||
Result.success()
|
||||
},
|
||||
onFailure = {
|
||||
if (it is ApiException && it.isRetryable()) {
|
||||
Result.retry()
|
||||
} else {
|
||||
CoreLogger.e(TAG, it)
|
||||
purchaseRepository.upsertPurchase(
|
||||
purchase.copy(
|
||||
purchaseFailure = it.localizedMessage,
|
||||
purchaseState = PurchaseState.Failed
|
||||
)
|
||||
)
|
||||
Result.failure()
|
||||
onSuccess = { onSuccess(purchase) },
|
||||
onFailure = { onFailure(purchase, it) }
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun onSuccess(purchase: Purchase): Result {
|
||||
purchaseRepository.upsertPurchase(purchase.copy(purchaseState = PurchaseState.Subscribed))
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private suspend fun onFailure(purchase: Purchase, error: Throwable): Result {
|
||||
return when {
|
||||
error is ApiException && error.isRetryable() -> Result.retry()
|
||||
|
||||
error is ApiException && error.isUnprocessable() -> {
|
||||
val userId = requireNotNull(sessionProvider.getUserId(purchase.sessionId))
|
||||
val plans = plansRepository.getSubscription(userId)?.plans.orEmpty()
|
||||
when {
|
||||
plans.any { it.name == purchase.planName } -> onSuccess(purchase)
|
||||
else -> onPermanentFailure(purchase, error)
|
||||
}
|
||||
}
|
||||
|
||||
else -> onPermanentFailure(purchase, error)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onPermanentFailure(purchase: Purchase, error: Throwable): Result {
|
||||
CoreLogger.e(TAG, error)
|
||||
purchaseRepository.upsertPurchase(
|
||||
purchase.copy(
|
||||
purchaseFailure = error.localizedMessage,
|
||||
purchaseState = PurchaseState.Failed
|
||||
)
|
||||
)
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -19,13 +19,11 @@ public final class me/proton/core/plan/presentation/compose/component/Composable
|
|||
public static field lambda-2 Lkotlin/jvm/functions/Function2;
|
||||
public static field lambda-3 Lkotlin/jvm/functions/Function2;
|
||||
public static field lambda-4 Lkotlin/jvm/functions/Function2;
|
||||
public static field lambda-5 Lkotlin/jvm/functions/Function2;
|
||||
public fun <init> ()V
|
||||
public final fun getLambda-1$plan_presentation_compose_release ()Lkotlin/jvm/functions/Function2;
|
||||
public final fun getLambda-2$plan_presentation_compose_release ()Lkotlin/jvm/functions/Function2;
|
||||
public final fun getLambda-3$plan_presentation_compose_release ()Lkotlin/jvm/functions/Function2;
|
||||
public final fun getLambda-4$plan_presentation_compose_release ()Lkotlin/jvm/functions/Function2;
|
||||
public final fun getLambda-5$plan_presentation_compose_release ()Lkotlin/jvm/functions/Function2;
|
||||
}
|
||||
|
||||
public final class me/proton/core/plan/presentation/compose/component/UpgradeStorageInfoKt {
|
||||
|
|
|
@ -27,7 +27,7 @@ plugins {
|
|||
publishOption.shouldBePublishedAsLib = true
|
||||
|
||||
protonCoverage {
|
||||
branchCoveragePercentage.set(50)
|
||||
branchCoveragePercentage.set(51)
|
||||
lineCoveragePercentage.set(91)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package me.proton.core.plan.presentation.compose.component
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
@ -26,8 +27,7 @@ import androidx.compose.foundation.layout.Spacer
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
|
@ -38,9 +38,7 @@ import androidx.compose.ui.res.dimensionResource
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import me.proton.core.compose.component.ProtonSolidButton
|
||||
import me.proton.core.compose.component.protonButtonColors
|
||||
import me.proton.core.compose.flow.rememberAsState
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import me.proton.core.compose.theme.ProtonColors
|
||||
import me.proton.core.compose.theme.ProtonDimens.DefaultIconSize
|
||||
import me.proton.core.compose.theme.ProtonDimens.ExtraSmallIconSize
|
||||
|
@ -52,7 +50,6 @@ import me.proton.core.domain.entity.UserId
|
|||
import me.proton.core.plan.presentation.R
|
||||
import me.proton.core.plan.presentation.compose.viewmodel.AccountStorageState
|
||||
import me.proton.core.plan.presentation.compose.viewmodel.UpgradeStorageInfoViewModel
|
||||
import me.proton.core.plan.presentation.compose.viewmodel.UpgradeStorageInfoViewModel.Companion.INITIAL_STATE
|
||||
|
||||
/** Displays information that storage is (nearly) full.
|
||||
* Only applies to users with free plan.
|
||||
|
@ -68,13 +65,13 @@ public fun UpgradeStorageInfo(
|
|||
withBottomDivider: Boolean = false,
|
||||
) {
|
||||
if (viewModel == null) return
|
||||
val state by rememberAsState(flow = viewModel.state, initial = INITIAL_STATE)
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val userId = (state as? AccountStorageState.HighStorageUsage)?.userId
|
||||
|
||||
if (state !is AccountStorageState.Hidden) {
|
||||
Column {
|
||||
if (withTopDivider) {
|
||||
Divider(color = ProtonTheme.colors.separatorNorm)
|
||||
HorizontalDivider(color = ProtonTheme.colors.separatorNorm)
|
||||
}
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = if (userId != null) {
|
||||
|
@ -86,7 +83,7 @@ public fun UpgradeStorageInfo(
|
|||
modifier = modifier
|
||||
)
|
||||
if (withBottomDivider) {
|
||||
Divider(color = ProtonTheme.colors.separatorNorm)
|
||||
HorizontalDivider(color = ProtonTheme.colors.separatorNorm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,17 +96,23 @@ public fun UpgradeStorageInfo(
|
|||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.padding(
|
||||
horizontal = dimensionResource(id = R.dimen.gap_large),
|
||||
vertical = dimensionResource(id = R.dimen.gap_medium_plus)
|
||||
),
|
||||
modifier = modifier
|
||||
.clickable(onClick = onUpgradeClicked)
|
||||
.padding(
|
||||
horizontal = dimensionResource(id = R.dimen.gap_large),
|
||||
vertical = dimensionResource(id = R.dimen.gap_medium_plus)
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
StackedIcons()
|
||||
Spacer(modifier = Modifier.width(dimensionResource(id = R.dimen.gap_medium_plus)))
|
||||
StorageInfoText(title)
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
UpgradeButton(onClick = { onUpgradeClicked() })
|
||||
StorageInfoText(title, modifier = Modifier.weight(1.0f))
|
||||
Image(
|
||||
colorFilter = ColorFilter.tint(ProtonTheme.colors.iconNorm),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(DefaultIconSize),
|
||||
painter = painterResource(id = R.drawable.ic_proton_arrow_up),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,25 +157,6 @@ private fun StorageInfoText(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UpgradeButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
ProtonSolidButton(
|
||||
colors = ButtonDefaults.protonButtonColors(
|
||||
backgroundColor = ProtonTheme.colors.interactionWeakNorm
|
||||
),
|
||||
onClick = onClick,
|
||||
modifier = modifier
|
||||
) {
|
||||
Text(
|
||||
color = ProtonTheme.colors.textNorm,
|
||||
text = stringResource(id = R.string.upgrade_storage_cta_button)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AccountStorageState.getTitle(): String = when (this) {
|
||||
is AccountStorageState.HighStorageUsage.Drive -> stringResource(
|
||||
|
@ -204,7 +188,7 @@ internal fun PreviewHighDriveUsage() {
|
|||
ProtonTheme(colors = ProtonColors.Light.sidebarColors!!) {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Drive storage: 90% full"
|
||||
title = "Drive: 90% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +199,7 @@ internal fun PreviewHighMailUsage() {
|
|||
ProtonTheme(colors = ProtonColors.Light.sidebarColors!!) {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Mail storage: 100% full"
|
||||
title = "Mail: 100% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +210,7 @@ internal fun PreviewHighMailUsageDarkTheme() {
|
|||
ProtonTheme(colors = ProtonColors.Dark.sidebarColors!!) {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Mail storage: 100% full"
|
||||
title = "Mail: 100% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class UpgradeStorageInfoTest {
|
|||
WithSidebarColors {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Drive storage: 80% full"
|
||||
title = "Drive: 80% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class UpgradeStorageInfoTest {
|
|||
WithSidebarColors(isDark = true) {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Drive storage: 80% full"
|
||||
title = "Drive: 80% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class UpgradeStorageInfoTest {
|
|||
WithSidebarColors {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Mail storage: 100% full"
|
||||
title = "Mail: 100% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class UpgradeStorageInfoTest {
|
|||
WithSidebarColors(isDark = true) {
|
||||
UpgradeStorageInfo(
|
||||
onUpgradeClicked = {},
|
||||
title = "Mail storage: 100% full"
|
||||
title = "Mail: 100% full"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0395aa0ee772298ea3e04fed3180e54d42929ec0f76f370150db2870baa3ecb1
|
||||
size 14933
|
||||
oid sha256:f2f522d12d318f85ed25baeafa6dcd746a86b4e2f406b30f9942675681d97012
|
||||
size 11211
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0395aa0ee772298ea3e04fed3180e54d42929ec0f76f370150db2870baa3ecb1
|
||||
size 14933
|
||||
oid sha256:f2f522d12d318f85ed25baeafa6dcd746a86b4e2f406b30f9942675681d97012
|
||||
size 11211
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c71c36bdd252036a576e85efc7b97d11ea427fc3e64013de29609bb9cf1d6d6
|
||||
size 14841
|
||||
oid sha256:71d35c1cdfeafaab1b69064af776670d64cc6983e9520aadb2366293965973f7
|
||||
size 11233
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c71c36bdd252036a576e85efc7b97d11ea427fc3e64013de29609bb9cf1d6d6
|
||||
size 14841
|
||||
oid sha256:71d35c1cdfeafaab1b69064af776670d64cc6983e9520aadb2366293965973f7
|
||||
size 11233
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:804e9c8ef58523c47f0ffd126f3a34d5b67763deac6705013c1ea6a1b513655c
|
||||
size 14843
|
||||
oid sha256:d49602dfec3587fa3eea68c36a21ea0bb2c65a17d9bf17aef87de3dd5eb8e453
|
||||
size 10998
|
||||
|
|
|
@ -165,9 +165,8 @@
|
|||
<!-- endregion -->
|
||||
|
||||
<!-- region Plan entitlement tags -->
|
||||
<string name="upgrade_storage_current_drive_storage">Drive storage: %d%% full</string>
|
||||
<string name="upgrade_storage_current_mail_storage">Mail storage: %d%% full</string>
|
||||
<string name="upgrade_storage_subtitle">Get more storage</string>
|
||||
<string name="upgrade_storage_cta_button">Upgrade</string>
|
||||
<string name="upgrade_storage_current_drive_storage">Drive: %d%% full</string>
|
||||
<string name="upgrade_storage_current_mail_storage">Mail: %d%% full</string>
|
||||
<string name="upgrade_storage_subtitle">Upgrade storage</string>
|
||||
<!-- endregion -->
|
||||
</resources>
|
||||
|
|
|
@ -29,17 +29,17 @@ abstract class ProtonIncludeCoreBuildPlugin : Plugin<Settings> {
|
|||
override fun apply(target: Settings) {
|
||||
// Configuration from Client.
|
||||
val config = target.createExtension() as DefaultProtonIncludeCoreBuildExtension
|
||||
// Configuration from CI.
|
||||
val isCI = System.getenv("CI").toBoolean()
|
||||
// Configuration from GitLab CI.
|
||||
val host = System.getenv("CI_SERVER_HOST")
|
||||
val token = System.getenv("CI_JOB_TOKEN")
|
||||
val hasHostToken = host != null && token != null
|
||||
val commitSha = System.getenv("CORE_COMMIT_SHA")
|
||||
val parentPath = target.rootDir.parentFile.absolutePath
|
||||
val metaProperties = File("$parentPath/${metaProperties}")
|
||||
target.gradle.settingsEvaluated {
|
||||
val protonLibsUri = when {
|
||||
config.uri.isPresent -> config.uri.get()
|
||||
isCI -> "https://gitlab-ci-token:$token@$host/proton/mobile/android/proton-libs.git"
|
||||
hasHostToken -> "https://gitlab-ci-token:$token@$host/proton/mobile/android/proton-libs.git"
|
||||
else -> "https://github.com/ProtonMail/protoncore_android.git"
|
||||
}
|
||||
// Configuration for Core.
|
||||
|
|
Loading…
Reference in New Issue