mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-24 19:00:26 +01:00
Use megaphones for PIN reminders.
This commit is contained in:
@@ -20,8 +20,8 @@ public class BasicMegaphoneView extends FrameLayout {
|
||||
private Button actionButton;
|
||||
private Button snoozeButton;
|
||||
|
||||
private Megaphone megaphone;
|
||||
private MegaphoneListener megaphoneListener;
|
||||
private Megaphone megaphone;
|
||||
private MegaphoneActionController megaphoneListener;
|
||||
|
||||
public BasicMegaphoneView(@NonNull Context context) {
|
||||
super(context);
|
||||
@@ -52,7 +52,7 @@ public class BasicMegaphoneView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public void present(@NonNull Megaphone megaphone, @NonNull MegaphoneListener megaphoneListener) {
|
||||
public void present(@NonNull Megaphone megaphone, @NonNull MegaphoneActionController megaphoneListener) {
|
||||
this.megaphone = megaphone;
|
||||
this.megaphoneListener = megaphoneListener;
|
||||
|
||||
@@ -92,7 +92,7 @@ public class BasicMegaphoneView extends FrameLayout {
|
||||
if (megaphone.canSnooze()) {
|
||||
snoozeButton.setVisibility(VISIBLE);
|
||||
snoozeButton.setOnClickListener(v -> {
|
||||
megaphoneListener.onMegaphoneSnooze(megaphone);
|
||||
megaphoneListener.onMegaphoneSnooze(megaphone.getEvent());
|
||||
|
||||
if (megaphone.getSnoozeListener() != null) {
|
||||
megaphone.getSnoozeListener().onEvent(megaphone, megaphoneListener);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class Megaphone {
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NonNull Builder setButtonText(@StringRes int buttonTextRes, @NonNull EventListener listener) {
|
||||
public @NonNull Builder setActionButton(@StringRes int buttonTextRes, @NonNull EventListener listener) {
|
||||
this.buttonTextRes = buttonTextRes;
|
||||
this.buttonListener = listener;
|
||||
return this;
|
||||
@@ -160,6 +160,6 @@ public class Megaphone {
|
||||
}
|
||||
|
||||
public interface EventListener {
|
||||
void onEvent(@NonNull Megaphone megaphone, @NonNull MegaphoneListener listener);
|
||||
void onEvent(@NonNull Megaphone megaphone, @NonNull MegaphoneActionController listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.thoughtcrime.securesms.megaphone;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
public interface MegaphoneListener {
|
||||
public interface MegaphoneActionController {
|
||||
/**
|
||||
* When a megaphone wants to navigate to a specific intent.
|
||||
*/
|
||||
@@ -21,13 +22,18 @@ public interface MegaphoneListener {
|
||||
*/
|
||||
void onMegaphoneToastRequested(@NonNull String string);
|
||||
|
||||
/**
|
||||
* When a megaphone needs a raw activity reference. Favor more specific methods when possible.
|
||||
*/
|
||||
@NonNull Activity getMegaphoneActivity();
|
||||
|
||||
/**
|
||||
* When a megaphone has been snoozed via "remind me later" or a similar option.
|
||||
*/
|
||||
void onMegaphoneSnooze(@NonNull Megaphone megaphone);
|
||||
void onMegaphoneSnooze(@NonNull Megaphones.Event event);
|
||||
|
||||
/**
|
||||
* Called when a megaphone completed its goal.
|
||||
*/
|
||||
void onMegaphoneCompleted(@NonNull Megaphone megaphone);
|
||||
void onMegaphoneCompleted(@NonNull Megaphones.Event event);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public class MegaphoneViewBuilder {
|
||||
|
||||
public static @Nullable View build(@NonNull Context context,
|
||||
@NonNull Megaphone megaphone,
|
||||
@NonNull MegaphoneListener listener)
|
||||
@NonNull MegaphoneActionController listener)
|
||||
{
|
||||
switch (megaphone.getStyle()) {
|
||||
case BASIC:
|
||||
@@ -28,7 +28,7 @@ public class MegaphoneViewBuilder {
|
||||
|
||||
private static @NonNull View buildBasicMegaphone(@NonNull Context context,
|
||||
@NonNull Megaphone megaphone,
|
||||
@NonNull MegaphoneListener listener)
|
||||
@NonNull MegaphoneActionController listener)
|
||||
{
|
||||
BasicMegaphoneView view = new BasicMegaphoneView(context);
|
||||
view.present(megaphone, listener);
|
||||
@@ -37,7 +37,7 @@ public class MegaphoneViewBuilder {
|
||||
|
||||
private static @NonNull View buildReactionsMegaphone(@NonNull Context context,
|
||||
@NonNull Megaphone megaphone,
|
||||
@NonNull MegaphoneListener listener)
|
||||
@NonNull MegaphoneActionController listener)
|
||||
{
|
||||
ReactionsMegaphoneView view = new ReactionsMegaphoneView(context);
|
||||
view.present(megaphone, listener);
|
||||
|
||||
@@ -12,6 +12,11 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.model.MegaphoneRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockReminders;
|
||||
import org.thoughtcrime.securesms.lock.SignalPinReminderDialog;
|
||||
import org.thoughtcrime.securesms.lock.SignalPinReminders;
|
||||
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
|
||||
import org.thoughtcrime.securesms.lock.v2.KbsMigrationActivity;
|
||||
import org.thoughtcrime.securesms.lock.v2.PinUtil;
|
||||
@@ -76,6 +81,7 @@ public final class Megaphones {
|
||||
return new LinkedHashMap<Event, MegaphoneSchedule>() {{
|
||||
put(Event.REACTIONS, new ForeverSchedule(true));
|
||||
put(Event.PINS_FOR_ALL, new PinsForAllSchedule());
|
||||
put(Event.PIN_REMINDER, new PinReminderSchedule());
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -84,7 +90,9 @@ public final class Megaphones {
|
||||
case REACTIONS:
|
||||
return buildReactionsMegaphone();
|
||||
case PINS_FOR_ALL:
|
||||
return buildPinsForAllMegaphone(context, record);
|
||||
return buildPinsForAllMegaphone(record);
|
||||
case PIN_REMINDER:
|
||||
return buildPinReminderMegaphone(context);
|
||||
default:
|
||||
throw new IllegalArgumentException("Event not handled!");
|
||||
}
|
||||
@@ -96,7 +104,7 @@ public final class Megaphones {
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull Megaphone buildPinsForAllMegaphone(@NonNull Context context, @NonNull MegaphoneRecord record) {
|
||||
private static @NonNull Megaphone buildPinsForAllMegaphone(@NonNull MegaphoneRecord record) {
|
||||
if (PinsForAllSchedule.shouldDisplayFullScreen(record.getFirstVisible(), System.currentTimeMillis())) {
|
||||
return new Megaphone.Builder(Event.PINS_FOR_ALL, Megaphone.Style.FULLSCREEN)
|
||||
.setMandatory(true)
|
||||
@@ -125,7 +133,7 @@ public final class Megaphones {
|
||||
private static @NonNull Megaphone buildPinsForAllMegaphoneForUserWithPin(@NonNull Megaphone.Builder builder) {
|
||||
return builder.setTitle(R.string.KbsMegaphone__introducing_pins)
|
||||
.setBody(R.string.KbsMegaphone__your_registration_lock_is_now_called_a_pin)
|
||||
.setButtonText(R.string.KbsMegaphone__update_pin, (megaphone, listener) -> {
|
||||
.setActionButton(R.string.KbsMegaphone__update_pin, (megaphone, listener) -> {
|
||||
Intent intent = CreateKbsPinActivity.getIntentForPinChangeFromSettings(ApplicationDependencies.getApplication());
|
||||
|
||||
listener.onMegaphoneNavigationRequested(intent, CreateKbsPinActivity.REQUEST_NEW_PIN);
|
||||
@@ -136,7 +144,7 @@ public final class Megaphones {
|
||||
private static @NonNull Megaphone buildPinsForAllMegaphoneForUserWithoutPin(@NonNull Megaphone.Builder builder) {
|
||||
return builder.setTitle(R.string.KbsMegaphone__create_a_pin)
|
||||
.setBody(R.string.KbsMegaphone__pins_add_another_layer_of_security_to_your_signal_account)
|
||||
.setButtonText(R.string.KbsMegaphone__create_pin, (megaphone, listener) -> {
|
||||
.setActionButton(R.string.KbsMegaphone__create_pin, (megaphone, listener) -> {
|
||||
Intent intent = CreateKbsPinActivity.getIntentForPinCreate(ApplicationDependencies.getApplication());
|
||||
|
||||
listener.onMegaphoneNavigationRequested(intent, CreateKbsPinActivity.REQUEST_NEW_PIN);
|
||||
@@ -144,9 +152,40 @@ public final class Megaphones {
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull Megaphone buildPinReminderMegaphone(@NonNull Context context) {
|
||||
return new Megaphone.Builder(Event.PIN_REMINDER, Megaphone.Style.BASIC)
|
||||
.setTitle(R.string.Megaphones_verify_your_signal_pin)
|
||||
.setBody(R.string.Megaphones_well_occasionally_ask_you_to_verify_your_pin)
|
||||
.setImage(R.drawable.kbs_pin_megaphone)
|
||||
.setActionButton(R.string.Megaphones_verify_pin, (megaphone, controller) -> {
|
||||
SignalPinReminderDialog.show(controller.getMegaphoneActivity(), controller::onMegaphoneNavigationRequested, new SignalPinReminderDialog.Callback() {
|
||||
@Override
|
||||
public void onReminderDismissed(boolean includedFailure) {
|
||||
if (includedFailure) {
|
||||
SignalStore.pinValues().onEntryFailure();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReminderCompleted(boolean includedFailure) {
|
||||
if (includedFailure) {
|
||||
SignalStore.pinValues().onEntryFailure();
|
||||
} else {
|
||||
SignalStore.pinValues().onEntrySuccess();
|
||||
}
|
||||
|
||||
controller.onMegaphoneSnooze(Event.PIN_REMINDER);
|
||||
controller.onMegaphoneToastRequested(context.getString(SignalPinReminders.getReminderString(SignalStore.pinValues().getCurrentInterval())));
|
||||
}
|
||||
});
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public enum Event {
|
||||
REACTIONS("reactions"),
|
||||
PINS_FOR_ALL("pins_for_all");
|
||||
PINS_FOR_ALL("pins_for_all"),
|
||||
PIN_REMINDER("pin_reminder");
|
||||
|
||||
private final String key;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.thoughtcrime.securesms.megaphone;
|
||||
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
|
||||
final class PinReminderSchedule implements MegaphoneSchedule {
|
||||
|
||||
@Override
|
||||
public boolean shouldDisplay(int seenCount, long lastSeen, long firstVisible, long currentTime) {
|
||||
if (!SignalStore.kbsValues().isV2RegistrationLockEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FeatureFlags.pinsForAll()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long lastSuccessTime = SignalStore.pinValues().getLastSuccessfulEntryTime();
|
||||
long interval = SignalStore.pinValues().getCurrentInterval();
|
||||
|
||||
return currentTime - lastSuccessTime >= interval;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user