Show update pin megaphone after AEP without pin registration.

This commit is contained in:
Cody Henthorne
2025-03-03 10:33:13 -05:00
committed by Greyson Parrelli
parent 507d67ee61
commit 0fdcc1c027
4 changed files with 72 additions and 1 deletions

View File

@@ -81,6 +81,7 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
private const val KEY_ACI = "account.aci"
private const val KEY_PNI = "account.pni"
private const val KEY_IS_REGISTERED = "account.is_registered"
private const val KEY_ACCOUNT_REGISTERED_AT = "account.registered_at"
private const val KEY_HAS_LINKED_DEVICES = "account.has_linked_devices"
@@ -417,8 +418,20 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
if (previous && !registered) {
clearLocalCredentials()
}
if (!previous && registered) {
registeredAtTimestamp = System.currentTimeMillis()
} else if (!registered) {
registeredAtTimestamp = -1
}
}
/**
* Milliseconds since epoch when account was registered or a negative value if not known.
*/
var registeredAtTimestamp: Long by longValue(KEY_ACCOUNT_REGISTERED_AT, -1)
private set
/**
* Function for testing backup/restore
*/

View File

@@ -110,6 +110,7 @@ public final class Megaphones {
private static Map<Event, MegaphoneSchedule> buildDisplayOrder(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
return new LinkedHashMap<>() {{
put(Event.PINS_FOR_ALL, new PinsForAllSchedule());
put(Event.UPDATE_PIN_AFTER_AEP_REGISTRATION, new UpdatePinAfterAepRegistrationSchedule());
put(Event.CLIENT_DEPRECATED, SignalStore.misc().isClientDeprecated() ? ALWAYS : NEVER);
put(Event.NEW_LINKED_DEVICE, shouldShowNewLinkedDeviceMegaphone() ? ALWAYS: NEVER);
put(Event.NOTIFICATIONS, shouldShowNotificationsMegaphone(context) ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(30)) : NEVER);
@@ -170,6 +171,8 @@ public final class Megaphones {
return buildPnpLaunchMegaphone();
case NEW_LINKED_DEVICE:
return buildNewLinkedDeviceMegaphone(context);
case UPDATE_PIN_AFTER_AEP_REGISTRATION:
return buildUpdatePinAfterAepRegistrationMegaphone();
default:
throw new IllegalArgumentException("Event not handled!");
}
@@ -436,6 +439,19 @@ public final class Megaphones {
.build();
}
public static @NonNull Megaphone buildUpdatePinAfterAepRegistrationMegaphone() {
return new Megaphone.Builder(Event.UPDATE_PIN_AFTER_AEP_REGISTRATION, Megaphone.Style.BASIC)
.setImage(R.drawable.kbs_pin_megaphone)
.setTitle(R.string.UpdatePinMegaphone__update_signal_pin)
.setBody(R.string.UpdatePinMegaphone__message)
.setActionButton(R.string.UpdatePinMegaphone__update_pin, (megaphone, listener) -> {
Intent intent = CreateSvrPinActivity.getIntentForPinCreate(AppDependencies.getApplication());
listener.onMegaphoneNavigationRequested(intent, CreateSvrPinActivity.REQUEST_NEW_PIN);
})
.build();
}
private static boolean shouldShowOnboardingMegaphone(@NonNull Context context) {
return SignalStore.onboarding().hasOnboarding(context);
}
@@ -551,7 +567,8 @@ public final class Megaphones {
SET_UP_YOUR_USERNAME("set_up_your_username"),
PNP_LAUNCH("pnp_launch"),
GRANT_FULL_SCREEN_INTENT("grant_full_screen_intent"),
NEW_LINKED_DEVICE("new_linked_device");
NEW_LINKED_DEVICE("new_linked_device"),
UPDATE_PIN_AFTER_AEP_REGISTRATION("update_pin_after_registration");
private final String key;

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.megaphone
import org.thoughtcrime.securesms.keyvalue.SignalStore
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
/**
* Schedule for showing an update pin megaphone after re-registering with AEP in a flow that doesn't provide the pin.
*
* That is at this point only manual AEP entry without remote backup restore.
*/
class UpdatePinAfterAepRegistrationSchedule : MegaphoneSchedule {
override fun shouldDisplay(seenCount: Int, lastSeen: Long, firstVisible: Long, currentTime: Long): Boolean {
return !SignalStore.svr.hasPin() &&
!SignalStore.svr.hasOptedOut() &&
SignalStore.registration.isRegistrationComplete &&
(!SignalStore.backup.isMediaRestoreInProgress || hasBeenLongEnough())
}
/**
* Should show if it's been more than 3 days regardless of restore progress.
*/
private fun hasBeenLongEnough(): Boolean {
val registeredAt = SignalStore.account.registeredAtTimestamp.milliseconds
val now = System.currentTimeMillis().milliseconds
return registeredAt.isNegative() || registeredAt > now || (registeredAt + 3.days) < now
}
}