From 564b9f47ee2eb31fe7f2f3eaa14629b4fa351347 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 11 Jan 2023 16:31:47 -0500 Subject: [PATCH] Add banner warning about API 19 deprecation. --- .../components/reminder/Api19Reminder.kt | 45 +++++++++++++++++++ .../reminder/ExpiredBuildReminder.java | 13 ++++-- .../components/reminder/Reminder.java | 4 +- .../ConversationParentFragment.java | 40 +++++++++++++++++ .../ConversationListFragment.java | 6 +++ app/src/main/res/values/ids.xml | 2 + app/src/main/res/values/strings.xml | 9 ++++ 7 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/reminder/Api19Reminder.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Api19Reminder.kt b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Api19Reminder.kt new file mode 100644 index 000000000..5669d2730 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Api19Reminder.kt @@ -0,0 +1,45 @@ +package org.thoughtcrime.securesms.components.reminder + +import android.content.Context +import android.os.Build +import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.util.Util +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * Shown when a user has API 19. + */ +class Api19Reminder(context: Context) : Reminder(null, context.getString(R.string.API19Reminder_banner_message, getExpireDate())) { + + init { + addAction( + Action( + context.getString(R.string.API19Reminder_learn_more), + R.id.reminder_action_api_19_learn_more + ) + ) + } + + override fun isDismissable(): Boolean { + return false + } + + override fun getImportance(): Importance { + return Importance.TERMINAL + } + + companion object { + @JvmStatic + fun isEligible(): Boolean { + return Build.VERSION.SDK_INT < 21 && !ExpiredBuildReminder.isEligible() + } + + fun getExpireDate(): String { + val formatter = SimpleDateFormat("MMMM d", Locale.getDefault()) + val expireDate = Date(System.currentTimeMillis() + Util.getTimeUntilBuildExpiry()) + return formatter.format(expireDate) + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java index b5089cf4b..4a2f13b9e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ExpiredBuildReminder.java @@ -1,11 +1,13 @@ package org.thoughtcrime.securesms.components.reminder; import android.content.Context; +import android.os.Build; import androidx.annotation.NonNull; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.keyvalue.SignalStore; +import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.PlayStoreUtil; import java.util.List; @@ -17,10 +19,15 @@ import java.util.List; public class ExpiredBuildReminder extends Reminder { public ExpiredBuildReminder(final Context context) { - super(null, context.getString(R.string.ExpiredBuildReminder_this_version_of_signal_has_expired)); + super(null, Build.VERSION.SDK_INT < 21 + ? context.getString(R.string.ExpiredBuildReminder_api_19_message) + : context.getString(R.string.ExpiredBuildReminder_this_version_of_signal_has_expired)); - setOkListener(v -> PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(context)); - addAction(new Action(context.getString(R.string.ExpiredBuildReminder_update_now), R.id.reminder_action_update_now)); + if (Build.VERSION.SDK_INT < 21) { + addAction(new Action(context.getString(R.string.API19Reminder_learn_more), R.id.reminder_action_api_19_learn_more)); + } else { + addAction(new Action(context.getString(R.string.ExpiredBuildReminder_update_now), R.id.reminder_action_update_now)); + } } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java index 4ff4a65b7..0250c5f11 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java @@ -82,11 +82,11 @@ public abstract class Reminder { this.actionId = actionId; } - CharSequence getTitle() { + public CharSequence getTitle() { return title; } - int getActionId() { + public int getActionId() { return actionId; } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java index 65f072a90..e53c023b9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -1936,6 +1936,8 @@ public class ConversationParentFragment extends Fragment InsightsLauncher.showInsightsDashboard(getChildFragmentManager()); } else if (reminderActionId == R.id.reminder_action_update_now) { PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext()); + } else if (reminderActionId == R.id.reminder_action_api_19_learn_more) { + CommunicationActions.openBrowserLink(requireContext(), "https://support.signal.org/hc/articles/5109141421850"); } else { throw new IllegalArgumentException("Unknown ID: " + reminderActionId); } @@ -2974,6 +2976,11 @@ public class ConversationParentFragment extends Fragment } private void sendMediaMessage(@NonNull MediaSendActivityResult result) { + if (ExpiredBuildReminder.isEligible()) { + showExpiredDialog(); + return; + } + long thread = this.threadId; long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds()); QuoteModel quote = result.isViewOnce() ? null : inputPanel.getQuote().orElse(null); @@ -3052,6 +3059,11 @@ public class ConversationParentFragment extends Fragment final boolean clearComposeBox, final @Nullable String metricId) { + if (ExpiredBuildReminder.isEligible()) { + showExpiredDialog(); + return new SettableFuture<>(null); + } + if (!viewModel.isDefaultSmsApplication() && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { showDefaultSmsPrompt(); return new SettableFuture<>(null); @@ -3130,6 +3142,11 @@ public class ConversationParentFragment extends Fragment private void sendTextMessage(@NonNull MessageSendType sendType, final long expiresIn, final boolean initiating, final @Nullable String metricId) throws InvalidMessageException { + if (ExpiredBuildReminder.isEligible()) { + showExpiredDialog(); + return; + } + if (!viewModel.isDefaultSmsApplication() && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { showDefaultSmsPrompt(); return; @@ -3172,6 +3189,29 @@ public class ConversationParentFragment extends Fragment .show(); } + private void showExpiredDialog() { + Reminder reminder = new ExpiredBuildReminder(requireContext()); + + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext()) + .setMessage(reminder.getText()) + .setPositiveButton(android.R.string.ok, (d, w) -> d.dismiss()); + + List actions = reminder.getActions(); + if (actions.size() == 1) { + Reminder.Action action = actions.get(0); + + builder.setNeutralButton(action.getTitle(), (d, i) -> { + if (action.getActionId() == R.id.reminder_action_update_now) { + PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext()); + } else if (action.getActionId() == R.id.reminder_action_api_19_learn_more) { + CommunicationActions.openBrowserLink(requireContext(), "https://support.signal.org/hc/articles/5109141421850"); + } + }); + } + + builder.show(); + } + private void updateToggleButtonState() { if (inputPanel.isRecordingInLockedMode()) { buttonToggle.display(sendButton); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 6c44905b9..2acc74b21 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -97,6 +97,7 @@ import org.thoughtcrime.securesms.components.menu.ActionItem; import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar; import org.thoughtcrime.securesms.components.menu.SignalContextMenu; import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton; +import org.thoughtcrime.securesms.components.reminder.Api19Reminder; import org.thoughtcrime.securesms.components.reminder.CdsPermanentErrorReminder; import org.thoughtcrime.securesms.components.reminder.CdsTemporyErrorReminder; import org.thoughtcrime.securesms.components.reminder.DozeReminder; @@ -158,6 +159,7 @@ import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel; import org.thoughtcrime.securesms.util.AppForegroundObserver; import org.thoughtcrime.securesms.util.AppStartup; import org.thoughtcrime.securesms.util.BottomSheetUtil; +import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.ConversationUtil; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.LifecycleDisposable; @@ -681,6 +683,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode CdsTemporaryErrorBottomSheet.show(getChildFragmentManager()); } else if (reminderActionId == R.id.reminder_action_cds_permanent_error_learn_more) { CdsPermanentErrorBottomSheet.show(getChildFragmentManager()); + } else if (reminderActionId == R.id.reminder_action_api_19_learn_more) { + CommunicationActions.openBrowserLink(requireContext(), "https://support.signal.org/hc/articles/5109141421850"); } } @@ -942,6 +946,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode } else if (ServiceOutageReminder.isEligible(context)) { ApplicationDependencies.getJobManager().add(new ServiceOutageDetectionJob()); return Optional.of(new ServiceOutageReminder(context)); + } else if (Api19Reminder.isEligible()) { + return Optional.of(new Api19Reminder(context)); } else if (OutdatedBuildReminder.isEligible()) { return Optional.of(new OutdatedBuildReminder(context)); } else if (PushRegistrationReminder.isEligible(context)) { diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 2b7749cdf..3cb431d1a 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -18,6 +18,8 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d391d3d8b..56b6bf35d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -653,6 +653,9 @@ This version of Signal has expired. Update now to send and receive messages. Update now + + Signal no longer works on this device. To use Signal again, update your device to a newer version of Android or switch to a newer device. + %d pending member request. @@ -5482,4 +5485,10 @@ Tip: Pull down on the chat list to filter + + Signal will no longer support your device\'s version of Android soon. To keep using Signal, update your device, or switch to a newer device by %1$s. + + + Learn more +