Add verify key megaphone.

This commit is contained in:
Michelle Tang
2025-07-10 13:22:30 -04:00
committed by Jeffrey Starke
parent c6afa17330
commit 359f473b59
13 changed files with 605 additions and 148 deletions

View File

@@ -19,6 +19,7 @@ import org.signal.core.util.SetUtil;
import org.signal.core.util.TranslationDetection;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.v2.ui.verify.VerifyBackupKeyActivity;
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.MegaphoneRecord;
@@ -128,6 +129,7 @@ public final class Megaphones {
put(Event.ADD_A_PROFILE_PHOTO, shouldShowAddAProfilePhotoMegaphone(context) ? ALWAYS : NEVER);
put(Event.PNP_LAUNCH, shouldShowPnpLaunchMegaphone() ? ALWAYS : NEVER);
put(Event.TURN_ON_SIGNAL_BACKUPS, shouldShowTurnOnBackupsMegaphone(context) ? ALWAYS : NEVER);
put(Event.VERIFY_BACKUP_KEY, new VerifyBackupKeyReminderSchedule());
}};
}
@@ -177,6 +179,8 @@ public final class Megaphones {
return buildUpdatePinAfterAepRegistrationMegaphone();
case TURN_ON_SIGNAL_BACKUPS:
return buildTurnOnSignalBackupsMegaphone();
case VERIFY_BACKUP_KEY:
return buildVerifyBackupKeyMegaphone();
default:
throw new IllegalArgumentException("Event not handled!");
}
@@ -474,6 +478,28 @@ public final class Megaphones {
.build();
}
public static @NonNull Megaphone buildVerifyBackupKeyMegaphone() {
Megaphone.Builder builder = new Megaphone.Builder(Event.VERIFY_BACKUP_KEY, Megaphone.Style.BASIC)
.setImage(R.drawable.image_signal_backups_key)
.setTitle(R.string.VerifyBackupKey__title)
.setBody(R.string.VerifyBackupKey__body)
.setActionButton(R.string.VerifyBackupKey__verify, (megaphone, controller) -> {
Intent intent = VerifyBackupKeyActivity.createIntent(controller.getMegaphoneActivity());
controller.onMegaphoneNavigationRequested(intent, VerifyBackupKeyActivity.REQUEST_CODE);
});
if (!SignalStore.backup().getHasSnoozedVerified()) {
builder.setSecondaryButton(R.string.VerifyBackupKey__not_now, (megaphone, controller) -> {
SignalStore.backup().setHasSnoozedVerified(true);
controller.onMegaphoneToastRequested(controller.getMegaphoneActivity().getString(R.string.VerifyBackupKey__we_will_ask_again));
controller.onMegaphoneSnooze(Event.VERIFY_BACKUP_KEY);
});
}
return builder.build();
}
private static boolean shouldShowOnboardingMegaphone(@NonNull Context context) {
return SignalStore.onboarding().hasOnboarding(context);
}
@@ -599,7 +625,8 @@ public final class Megaphones {
GRANT_FULL_SCREEN_INTENT("grant_full_screen_intent"),
NEW_LINKED_DEVICE("new_linked_device"),
UPDATE_PIN_AFTER_AEP_REGISTRATION("update_pin_after_registration"),
TURN_ON_SIGNAL_BACKUPS("turn_on_signal_backups");
TURN_ON_SIGNAL_BACKUPS("turn_on_signal_backups"),
VERIFY_BACKUP_KEY("verify_backup_key");
private final String key;

View File

@@ -0,0 +1,36 @@
package org.thoughtcrime.securesms.megaphone
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.RemoteConfig
import kotlin.time.Duration.Companion.days
/**
* Calculates if the verify key megaphone should be shown based on the following rules
* - 1 reminder within 14 days of creation, every 6 months after that
* - Allow snooze only once, for a week
* - Do not show within 1 week of showing the PIN reminder
*/
class VerifyBackupKeyReminderSchedule : MegaphoneSchedule {
override fun shouldDisplay(seenCount: Int, lastSeen: Long, firstVisible: Long, currentTime: Long): Boolean {
if (!RemoteConfig.messageBackups) {
return false
}
if (!SignalStore.backup.areBackupsEnabled) {
return false
}
val lastVerifiedTime = SignalStore.backup.lastVerifyKeyTime
val previouslySnoozed = SignalStore.backup.hasSnoozedVerified
val isFirstReminder = !SignalStore.backup.hasVerifiedBefore
val intervalTime = if (isFirstReminder) 14.days.inWholeMilliseconds else 183.days.inWholeMilliseconds
val snoozedTime = if (previouslySnoozed) 7.days.inWholeMilliseconds else 0.days.inWholeMilliseconds
val shouldShowBackupKeyReminder = System.currentTimeMillis() > (lastVerifiedTime + intervalTime + snoozedTime)
val hasShownPinReminderRecently = System.currentTimeMillis() < SignalStore.pin.lastReminderTime + 7.days.inWholeMilliseconds
return shouldShowBackupKeyReminder && !hasShownPinReminderRecently
}
}