From 0fdcc1c027d7141d341130aa62e8b223a52b4aa9 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Mon, 3 Mar 2025 10:33:13 -0500 Subject: [PATCH] Show update pin megaphone after AEP without pin registration. --- .../securesms/keyvalue/AccountValues.kt | 13 +++++++ .../securesms/megaphone/Megaphones.java | 19 ++++++++++- .../UpdatePinAfterAepRegistrationSchedule.kt | 34 +++++++++++++++++++ app/src/main/res/values/strings.xml | 7 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/megaphone/UpdatePinAfterAepRegistrationSchedule.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt index 72ba52955c..aff52b39de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt @@ -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 */ diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java index 42141c3228..edad53d121 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java @@ -110,6 +110,7 @@ public final class Megaphones { private static Map buildDisplayOrder(@NonNull Context context, @NonNull Map 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; diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/UpdatePinAfterAepRegistrationSchedule.kt b/app/src/main/java/org/thoughtcrime/securesms/megaphone/UpdatePinAfterAepRegistrationSchedule.kt new file mode 100644 index 0000000000..67d894e025 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/UpdatePinAfterAepRegistrationSchedule.kt @@ -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 + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2292e9ba3..b3e0ecd4e0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4460,6 +4460,13 @@ PINs keep information that’s stored with Signal encrypted. Create PIN + + Update Signal PIN + + Update your Signal PIN to complete account registration. + + Update PIN + Incoming Signal voice call