Update prioritization of donation error bottom sheets.

This commit is contained in:
Alex Hart
2022-04-08 13:07:19 -03:00
committed by Cody Henthorne
parent fc55be0916
commit b65d62e065
7 changed files with 40 additions and 16 deletions

View File

@@ -168,6 +168,7 @@ class SubscribeViewModel(
SignalStore.donationsValues().clearLevelOperations()
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
MultiDeviceSubscriptionSyncRequestJob.enqueue()
}
} else {
@@ -185,6 +186,7 @@ class SubscribeViewModel(
SignalStore.donationsValues().clearLevelOperations()
SignalStore.donationsValues().markUserManuallyCancelled()
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
refreshActiveSubscription()
MultiDeviceSubscriptionSyncRequestJob.enqueue()
donationPaymentRepository.scheduleSyncForAccountRecordChange()

View File

@@ -342,21 +342,32 @@ public class ConversationListFragment extends MainFragment implements ActionMode
Badge expiredBadge = SignalStore.donationsValues().getExpiredBadge();
String subscriptionCancellationReason = SignalStore.donationsValues().getUnexpectedSubscriptionCancelationReason();
UnexpectedSubscriptionCancellation unexpectedSubscriptionCancellation = UnexpectedSubscriptionCancellation.fromStatus(subscriptionCancellationReason);
boolean isDisplayingSubscriptionFailure = false;
long subscriptionFailureTimestamp = SignalStore.donationsValues().getUnexpectedSubscriptionCancelationTimestamp();
long subscriptionFailureWatermark = SignalStore.donationsValues().getUnexpectedSubscriptionCancelationWatermark();
boolean isWatermarkPriorToTimestamp = subscriptionFailureWatermark < subscriptionFailureTimestamp;
if (expiredBadge != null) {
if (unexpectedSubscriptionCancellation != null &&
!SignalStore.donationsValues().isUserManuallyCancelled() &&
SignalStore.donationsValues().showCantProcessDialog() &&
isWatermarkPriorToTimestamp) {
Log.w(TAG, "Displaying bottom sheet for unexpected cancellation: " + unexpectedSubscriptionCancellation, true);
new CantProcessSubscriptionPaymentBottomSheetDialogFragment().show(getChildFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationWatermark(subscriptionFailureTimestamp);
isDisplayingSubscriptionFailure = true;
} else if (unexpectedSubscriptionCancellation != null && SignalStore.donationsValues().isUserManuallyCancelled()) {
Log.w(TAG, "Unexpected cancellation detected but not displaying dialog because user manually cancelled their subscription: " + unexpectedSubscriptionCancellation, true);
} else if (unexpectedSubscriptionCancellation != null && !SignalStore.donationsValues().showCantProcessDialog()) {
Log.w(TAG, "Unexpected cancellation detected but not displaying dialog because user has silenced it.", true);
}
if (expiredBadge != null && !isDisplayingSubscriptionFailure) {
SignalStore.donationsValues().setExpiredBadge(null);
if (expiredBadge.isBoost() || !SignalStore.donationsValues().isUserManuallyCancelled()) {
Log.w(TAG, "Displaying bottom sheet for an expired badge", true);
ExpiredBadgeBottomSheetDialogFragment.show(expiredBadge, unexpectedSubscriptionCancellation, getParentFragmentManager());
}
} else if (unexpectedSubscriptionCancellation != null && !SignalStore.donationsValues().isUserManuallyCancelled() && SignalStore.donationsValues().showCantProcessDialog()) {
Log.w(TAG, "Displaying bottom sheet for unexpected cancellation: " + unexpectedSubscriptionCancellation, true);
new CantProcessSubscriptionPaymentBottomSheetDialogFragment().show(getChildFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
} else if (unexpectedSubscriptionCancellation != null && SignalStore.donationsValues().isUserManuallyCancelled()) {
Log.w(TAG, "Unexpected cancellation detected but not displaying dialog because user manually cancelled their subscription: " + unexpectedSubscriptionCancellation, true);
} else if (unexpectedSubscriptionCancellation != null && !SignalStore.donationsValues().showCantProcessDialog()) {
Log.w(TAG, "Unexpected cancellation detected but not displaying dialog because user has silenced it.", true);
}
}

View File

@@ -11,7 +11,6 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredential;
import org.thoughtcrime.securesms.badges.BadgeRepository;
import org.thoughtcrime.securesms.badges.Badges;
import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.UnexpectedSubscriptionCancellation;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
@@ -269,7 +268,6 @@ public class RefreshOwnProfileJob extends BaseJob {
ActiveSubscription activeSubscription = response.getResult().get();
if (activeSubscription.isFailedPayment()) {
Log.d(TAG, "Unexpected expiry due to payment failure.", true);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(activeSubscription.getActiveSubscription().getStatus());
isDueToPaymentFailure = true;
}
}
@@ -277,7 +275,6 @@ public class RefreshOwnProfileJob extends BaseJob {
if (!isDueToPaymentFailure) {
Log.d(TAG, "Unexpected expiry due to inactivity.", true);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(UnexpectedSubscriptionCancellation.INACTIVE.getStatus());
}
MultiDeviceSubscriptionSyncRequestJob.enqueue();

View File

@@ -91,7 +91,14 @@ public class SubscriptionKeepAliveJob extends BaseJob {
ActiveSubscription activeSubscription = activeSubscriptionResponse.getResult().get();
if (activeSubscription.getActiveSubscription() == null) {
Log.i(TAG, "User does not have an active subscription. Exiting.", true);
Log.i(TAG, "User does not have a subscription. Exiting.", true);
return;
}
if (activeSubscription.isFailedPayment()) {
Log.i(TAG, "User has a subscription with a failed payment. Marking the payment failure. Status message: " + activeSubscription.getActiveSubscription().getStatus(), true);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(activeSubscription.getActiveSubscription().getStatus());
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(activeSubscription.getActiveSubscription().getEndOfCurrentPeriod());
return;
}

View File

@@ -144,7 +144,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
throw new RetryableException();
} else if (subscription.isFailedPayment()) {
Log.w(TAG, "Subscription payment failure in active subscription response (status = " + subscription.getStatus() + ").", true);
onPaymentFailure(subscription.getStatus());
onPaymentFailure(subscription.getStatus(), subscription.getEndOfCurrentPeriod());
throw new Exception("Subscription has a payment failure: " + subscription.getStatus());
} else if (!subscription.isActive()) {
Log.w(TAG, "Subscription is not yet active. Status: " + subscription.getStatus(), true);
@@ -234,7 +234,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
throw new Exception(response.getApplicationError().get());
case 402:
Log.w(TAG, "Subscription payment failure in credential response.", response.getApplicationError().get(), true);
onPaymentFailure(null);
onPaymentFailure(null, 0L);
throw new Exception(response.getApplicationError().get());
case 403:
Log.w(TAG, "SubscriberId password mismatch or account auth was present.", response.getApplicationError().get(), true);
@@ -253,13 +253,13 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
}
}
private void onPaymentFailure(@Nullable String status) {
private void onPaymentFailure(@Nullable String status, long timestamp) {
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
if (status == null) {
DonationError.routeDonationError(context, DonationError.genericPaymentFailure(getErrorSource()));
} else {
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(status);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(timestamp);
MultiDeviceSubscriptionSyncRequestJob.enqueue();
}
}

View File

@@ -35,6 +35,8 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
private const val SUBSCRIPTION_REDEMPTION_FAILED = "donation.subscription.redemption.failed"
private const val SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT = "donation.should.cancel.subscription.before.next.subscribe.attempt"
private const val SUBSCRIPTION_CANCELATION_REASON = "donation.subscription.cancelation.reason"
private const val SUBSCRIPTION_CANCELATION_TIMESTAMP = "donation.subscription.cancelation.timestamp"
private const val SUBSCRIPTION_CANCELATION_WATERMARK = "donation.subscription.cancelation.watermark"
private const val SHOW_CANT_PROCESS_DIALOG = "show.cant.process.dialog"
}
@@ -46,6 +48,8 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
KEY_LAST_END_OF_PERIOD_SECONDS,
SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT,
SUBSCRIPTION_CANCELATION_REASON,
SUBSCRIPTION_CANCELATION_TIMESTAMP,
SUBSCRIPTION_CANCELATION_WATERMARK,
SHOW_CANT_PROCESS_DIALOG
)
@@ -230,6 +234,8 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
}
var unexpectedSubscriptionCancelationReason: String? by stringValue(SUBSCRIPTION_CANCELATION_REASON, null)
var unexpectedSubscriptionCancelationTimestamp: Long by longValue(SUBSCRIPTION_CANCELATION_TIMESTAMP, 0L)
var unexpectedSubscriptionCancelationWatermark: Long by longValue(SUBSCRIPTION_CANCELATION_WATERMARK, 0L)
@get:JvmName("showCantProcessDialog")
var showCantProcessDialog: Boolean by booleanValue(SHOW_CANT_PROCESS_DIALOG, true)

View File

@@ -162,6 +162,7 @@ public final class StorageSyncHelper {
if (update.getNew().isSubscriptionManuallyCancelled()) {
SignalStore.donationsValues().markUserManuallyCancelled();
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(null);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(0L);
} else {
SignalStore.donationsValues().clearUserManuallyCancelled();
}