Delete the reminders system.

This commit is contained in:
Nicholas Tinsley
2024-08-19 13:45:53 -04:00
committed by mtang-signal
parent 4002dea05d
commit 9a24455085
37 changed files with 73 additions and 1277 deletions

View File

@@ -1,15 +0,0 @@
package org.thoughtcrime.securesms.components.reminder
import org.thoughtcrime.securesms.R
class BubbleOptOutReminder : Reminder(R.string.BubbleOptOutTooltip__description) {
init {
addAction(Action(R.string.BubbleOptOutTooltip__turn_off, R.id.reminder_action_bubble_turn_off))
addAction(Action(R.string.BubbleOptOutTooltip__not_now, R.id.reminder_action_bubble_not_now))
}
override fun isDismissable(): Boolean {
return false
}
}

View File

@@ -1,42 +0,0 @@
package org.thoughtcrime.securesms.components.reminder
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.keyvalue.SignalStore
import kotlin.time.Duration.Companion.days
/**
* Reminder shown when CDS is in a permanent error state, preventing us from doing a sync.
*/
class CdsPermanentErrorReminder : Reminder(R.string.reminder_cds_permanent_error_body) {
init {
addAction(
Action(
R.string.reminder_cds_permanent_error_learn_more,
R.id.reminder_action_cds_permanent_error_learn_more
)
)
}
override fun isDismissable(): Boolean {
return false
}
override fun getImportance(): Importance {
return Importance.ERROR
}
companion object {
/**
* Even if we're not truly "permanently blocked", if the time until we're unblocked is long enough, we'd rather show the permanent error message than
* telling the user to wait for 3 months or something.
*/
val PERMANENT_TIME_CUTOFF = 30.days.inWholeMilliseconds
@JvmStatic
fun isEligible(): Boolean {
val timeUntilUnblock = SignalStore.misc.cdsBlockedUtil - System.currentTimeMillis()
return SignalStore.misc.isCdsBlocked && timeUntilUnblock >= PERMANENT_TIME_CUTOFF
}
}
}

View File

@@ -1,35 +0,0 @@
package org.thoughtcrime.securesms.components.reminder
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.keyvalue.SignalStore
/**
* Reminder shown when CDS is rate-limited, preventing us from temporarily doing a refresh.
*/
class CdsTemporaryErrorReminder : Reminder(R.string.reminder_cds_warning_body) {
init {
addAction(
Action(
R.string.reminder_cds_warning_learn_more,
R.id.reminder_action_cds_temporary_error_learn_more
)
)
}
override fun isDismissable(): Boolean {
return false
}
override fun getImportance(): Importance {
return Importance.ERROR
}
companion object {
@JvmStatic
fun isEligible(): Boolean {
val timeUntilUnblock = SignalStore.misc.cdsBlockedUtil - System.currentTimeMillis()
return SignalStore.misc.isCdsBlocked && timeUntilUnblock < CdsPermanentErrorReminder.PERMANENT_TIME_CUTOFF
}
}
}

View File

@@ -1,41 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.PowerManagerCompat;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@SuppressLint("BatteryLife")
public class DozeReminder extends Reminder {
@RequiresApi(api = 23)
public DozeReminder(@NonNull final Context context) {
super(R.string.DozeReminder_optimize_for_missing_play_services, R.string.DozeReminder_this_device_does_not_support_play_services_tap_to_disable_system_battery);
setOkListener(v -> {
TextSecurePreferences.setPromptedOptimizeDoze(context, true);
PowerManagerCompat.requestIgnoreBatteryOptimizations(context);
});
setDismissListener(v -> TextSecurePreferences.setPromptedOptimizeDoze(context, true));
}
public static boolean isEligible(Context context) {
return !SignalStore.account().isFcmEnabled() &&
!TextSecurePreferences.hasPromptedOptimizeDoze(context) &&
Build.VERSION.SDK_INT >= 23 &&
!((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName());
}
}

View File

@@ -1,23 +0,0 @@
package org.thoughtcrime.securesms.components.reminder
import android.content.Context
import android.view.View
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.PlayStoreUtil
/**
* Banner to update app to the latest version because of enclave failure
*/
class EnclaveFailureReminder(context: Context) : Reminder(R.string.EnclaveFailureReminder_update_signal) {
init {
addAction(Action(R.string.ExpiredBuildReminder_update_now, R.id.reminder_action_update_now))
okListener = View.OnClickListener { PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(context) }
}
override fun isDismissable(): Boolean = false
override fun getImportance(): Importance {
return Importance.TERMINAL
}
}

View File

@@ -1,34 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
/**
* Showed when a build has fully expired (either via the compile-time constant, or remote
* deprecation).
*/
public class ExpiredBuildReminder extends Reminder {
public ExpiredBuildReminder(final Context context) {
super(R.string.ExpiredBuildReminder_this_version_of_signal_has_expired);
addAction(new Action(R.string.ExpiredBuildReminder_update_now, R.id.reminder_action_update_now));
}
@Override
public boolean isDismissable() {
return false;
}
@Override
public @NonNull Importance getImportance() {
return Importance.TERMINAL;
}
public static boolean isEligible() {
return SignalStore.misc().isClientDeprecated();
}
}

View File

@@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.RecipientId;
import java.util.List;
/**
* Shows a reminder to add anyone that might have been missed in GV1->GV2 migration.
*/
public class GroupsV1MigrationSuggestionsReminder extends Reminder {
private final int suggestionsSize;
public GroupsV1MigrationSuggestionsReminder(@NonNull List<RecipientId> suggestions) {
this.suggestionsSize = suggestions.size();
addAction(new AddMembersAction(suggestionsSize));
addAction(new Action(R.string.GroupsV1MigrationSuggestionsReminder_no_thanks, R.id.reminder_action_gv1_suggestion_no_thanks));
}
@Override
public @NonNull CharSequence getText(@NonNull Context context) {
return context.getResources().getQuantityString(R.plurals.GroupsV1MigrationSuggestionsReminder_members_couldnt_be_added_to_the_new_group, suggestionsSize, suggestionsSize);
}
@Override
public boolean isDismissable() {
return false;
}
private static class AddMembersAction extends Action {
private final int suggestionsSize;
public AddMembersAction(int suggestionsSize) {
super(NO_RESOURCE, R.id.reminder_action_gv1_suggestion_add_members);
this.suggestionsSize = suggestionsSize;
}
@Override
public CharSequence getTitle(@NonNull Context context) {
return context.getResources().getQuantityString(R.plurals.GroupsV1MigrationSuggestionsReminder_add_members, suggestionsSize);
}
}
}

View File

@@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.PlayStoreUtil;
import org.thoughtcrime.securesms.util.Util;
import java.util.concurrent.TimeUnit;
/**
* Reminder that is shown when a build is getting close to expiry (either because of the
* compile-time constant, or remote deprecation).
*/
public class OutdatedBuildReminder extends Reminder {
public OutdatedBuildReminder(final Context context) {
setOkListener(v -> PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(context));
addAction(new Action(R.string.OutdatedBuildReminder_update_now, R.id.reminder_action_update_now));
}
@Override
public @NonNull CharSequence getText(@NonNull Context context) {
int days = getDaysUntilExpiry();
if (days == 0) {
return context.getString(R.string.OutdatedBuildReminder_your_version_of_signal_will_expire_today);
} else {
return context.getResources().getQuantityString(R.plurals.OutdatedBuildReminder_your_version_of_signal_will_expire_in_n_days, days, days);
}
}
@Override
public boolean isDismissable() {
return false;
}
public static boolean isEligible() {
return getDaysUntilExpiry() <= 10;
}
private static int getDaysUntilExpiry() {
return (int) TimeUnit.MILLISECONDS.toDays(Util.getTimeUntilBuildExpiry(SignalStore.misc().getEstimatedServerTime()));
}
}

View File

@@ -1,36 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
/**
* Shown to admins when there are pending group join requests.
*/
public final class PendingGroupJoinRequestsReminder extends Reminder {
private final int count;
public PendingGroupJoinRequestsReminder(int count) {
this.count = count;
addAction(new Action(R.string.PendingGroupJoinRequestsReminder_view, R.id.reminder_action_review_join_requests));
}
@Override
public @NonNull CharSequence getText(@NonNull Context context) {
return context.getResources().getQuantityString(R.plurals.PendingGroupJoinRequestsReminder_d_pending_member_requests, count, count);
}
@Override
public boolean isDismissable() {
return true;
}
@Override
public @NonNull Importance getImportance() {
return Importance.NORMAL;
}
}

View File

@@ -1,119 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import android.view.View.OnClickListener;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import org.whispersystems.signalservice.api.util.Preconditions;
import java.util.LinkedList;
import java.util.List;
public abstract class Reminder {
public static final int NO_RESOURCE = -1;
private int title;
private int text;
private OnClickListener okListener;
private OnClickListener dismissListener;
private final List<Action> actions = new LinkedList<>();
/**
* For a reminder that wishes to generate it's own strings by overwriting
* {@link #getText(Context)} and {@link #getTitle(Context)}
*/
public Reminder() {
this(NO_RESOURCE, NO_RESOURCE);
}
public Reminder(@StringRes int textRes) {
this(NO_RESOURCE, textRes);
}
public Reminder(@StringRes int titleRes, @StringRes int textRes) {
this.title = titleRes;
this.text = textRes;
}
public @Nullable CharSequence getTitle(@NonNull Context context) {
if (title == NO_RESOURCE) {
return null;
}
return context.getString(title);
}
public @NonNull CharSequence getText(@NonNull Context context) {
Preconditions.checkArgument(text != NO_RESOURCE);
return context.getString(text);
}
public OnClickListener getOkListener() {
return okListener;
}
public OnClickListener getDismissListener() {
return dismissListener;
}
public void setOkListener(OnClickListener okListener) {
this.okListener = okListener;
}
public void setDismissListener(OnClickListener dismissListener) {
this.dismissListener = dismissListener;
}
public boolean isDismissable() {
return true;
}
public @NonNull Importance getImportance() {
return Importance.NORMAL;
}
protected void addAction(@NonNull Action action) {
actions.add(action);
}
public List<Action> getActions() {
return actions;
}
public int getProgress() {
return -1;
}
public enum Importance {
NORMAL, ERROR, TERMINAL
}
public static class Action {
private final int title;
private final int actionId;
public Action(@IdRes int actionId) {
this(NO_RESOURCE, actionId);
}
public Action(@StringRes int title, @IdRes int actionId) {
this.title = title;
this.actionId = actionId;
}
public CharSequence getTitle(@NonNull Context context) {
Preconditions.checkArgument(title != NO_RESOURCE);
return context.getText(title);
}
public int getActionId() {
return actionId;
}
}
}

View File

@@ -1,68 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.R;
import java.util.Collections;
import java.util.List;
final class ReminderActionsAdapter extends RecyclerView.Adapter<ReminderActionsAdapter.ActionViewHolder> {
private final Reminder.Importance importance;
private final List<Reminder.Action> actions;
private final ReminderView.OnActionClickListener actionClickListener;
ReminderActionsAdapter(Reminder.Importance importance, List<Reminder.Action> actions, ReminderView.OnActionClickListener actionClickListener) {
this.importance = importance;
this.actions = Collections.unmodifiableList(actions);
this.actionClickListener = actionClickListener;
}
@NonNull
@Override
public ActionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
TextView button = ((TextView) LayoutInflater.from(context).inflate(R.layout.reminder_action_button, parent, false));
if (importance == Reminder.Importance.NORMAL) {
button.setTextColor(ContextCompat.getColor(context, R.color.signal_colorPrimary));
} else if (importance == Reminder.Importance.ERROR || importance == Reminder.Importance.TERMINAL) {
button.setTextColor(ContextCompat.getColor(context, R.color.signal_light_colorOnSurface));
}
return new ActionViewHolder(button);
}
@Override
public void onBindViewHolder(@NonNull ActionViewHolder holder, int position) {
final Reminder.Action action = actions.get(position);
((Button) holder.itemView).setText(action.getTitle(holder.itemView.getContext()));
holder.itemView.setOnClickListener(v -> {
if (holder.getAdapterPosition() == RecyclerView.NO_POSITION) return;
actionClickListener.onActionClick(action.getActionId());
});
}
@Override
public int getItemCount() {
return actions.size();
}
final class ActionViewHolder extends RecyclerView.ViewHolder {
ActionViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}

View File

@@ -1,183 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.Space;
import android.widget.TextView;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.card.MaterialCardView;
import org.signal.core.util.DimensionUnit;
import org.thoughtcrime.securesms.R;
import java.util.List;
/**
* View to display actionable reminders to the user
*/
public final class ReminderView extends FrameLayout {
private ProgressBar progressBar;
private TextView progressText;
private MaterialCardView container;
private ImageButton closeButton;
private TextView title;
private TextView text;
private OnDismissListener dismissListener;
private Space space;
private RecyclerView actionsRecycler;
private OnActionClickListener actionClickListener;
private OnHideListener onHideListener;
public ReminderView(Context context) {
super(context);
initialize();
}
public ReminderView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public ReminderView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
private void initialize() {
LayoutInflater.from(getContext()).inflate(R.layout.reminder_header, this, true);
progressBar = findViewById(R.id.reminder_progress);
progressText = findViewById(R.id.reminder_progress_text);
container = findViewById(R.id.container);
closeButton = findViewById(R.id.cancel);
title = findViewById(R.id.reminder_title);
text = findViewById(R.id.reminder_text);
space = findViewById(R.id.reminder_space);
actionsRecycler = findViewById(R.id.reminder_actions);
}
public void showReminder(final Reminder reminder) {
if (!TextUtils.isEmpty(reminder.getTitle(getContext()))) {
title.setText(reminder.getTitle(getContext()));
title.setVisibility(VISIBLE);
space.setVisibility(GONE);
} else {
title.setText("");
title.setVisibility(GONE);
space.setVisibility(VISIBLE);
text.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface));
}
if (!reminder.isDismissable()) {
space.setVisibility(GONE);
}
text.setText(reminder.getText(getContext()));
switch (reminder.getImportance()) {
case NORMAL:
title.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface));
text.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurfaceVariant));
break;
case ERROR:
case TERMINAL:
container.setStrokeWidth(0);
container.setCardBackgroundColor(ContextCompat.getColor(getContext(), R.color.reminder_background));
title.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_light_colorOnSurface));
text.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_light_colorOnSurface));
break;
default:
throw new IllegalStateException();
}
if (reminder.getOkListener() != null) {
setOnClickListener(reminder.getOkListener());
}
closeButton.setVisibility(reminder.isDismissable() ? View.VISIBLE : View.GONE);
closeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hide();
if (reminder.getDismissListener() != null) reminder.getDismissListener().onClick(v);
if (dismissListener != null) dismissListener.onDismiss();
}
});
if (reminder.getImportance() == Reminder.Importance.NORMAL) {
closeButton.setColorFilter(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurfaceVariant));
}
int progress = reminder.getProgress();
if (progress != -1) {
progressBar.setProgress(progress);
progressBar.setVisibility(VISIBLE);
progressText.setText(getContext().getString(R.string.reminder_header_progress, progress));
progressText.setVisibility(VISIBLE);
} else {
progressBar.setVisibility(GONE);
progressText.setVisibility(GONE);
}
List<Reminder.Action> actions = reminder.getActions();
if (actions.isEmpty()) {
text.setPadding(0, 0, 0, ((int) DimensionUnit.DP.toPixels(16f)));
actionsRecycler.setVisibility(GONE);
} else {
text.setPadding(0, 0, 0, 0);
actionsRecycler.setVisibility(VISIBLE);
actionsRecycler.setAdapter(new ReminderActionsAdapter(reminder.getImportance(), actions, this::handleActionClicked));
}
container.setVisibility(View.VISIBLE);
}
private void handleActionClicked(@IdRes int actionId) {
if (actionClickListener != null) actionClickListener.onActionClick(actionId);
}
public void setOnDismissListener(OnDismissListener dismissListener) {
this.dismissListener = dismissListener;
}
public void setOnActionClickListener(@Nullable OnActionClickListener actionClickListener) {
this.actionClickListener = actionClickListener;
}
public void setOnHideListener(@Nullable OnHideListener onHideListener) {
this.onHideListener = onHideListener;
}
public void requestDismiss() {
closeButton.performClick();
}
public void hide() {
if (onHideListener != null && onHideListener.onHide()) {
return;
}
container.setVisibility(View.GONE);
}
public interface OnDismissListener {
void onDismiss();
}
public interface OnActionClickListener {
void onActionClick(@IdRes int actionId);
}
public interface OnHideListener {
boolean onHide();
}
}

View File

@@ -1,30 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class ServiceOutageReminder extends Reminder {
public ServiceOutageReminder() {
super(R.string.reminder_header_service_outage_text);
}
public static boolean isEligible(@NonNull Context context) {
return TextSecurePreferences.getServiceOutage(context);
}
@Override
public boolean isDismissable() {
return false;
}
@NonNull
@Override
public Importance getImportance() {
return Importance.ERROR;
}
}

View File

@@ -1,31 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class UnauthorizedReminder extends Reminder {
public UnauthorizedReminder() {
super(R.string.UnauthorizedReminder_this_is_likely_because_you_registered_your_phone_number_with_Signal_on_a_different_device);
addAction(new Action(R.string.UnauthorizedReminder_reregister_action, R.id.reminder_action_re_register));
}
@Override
public boolean isDismissable() {
return false;
}
@Override
public @NonNull Importance getImportance() {
return Importance.ERROR;
}
public static boolean isEligible(Context context) {
return TextSecurePreferences.isUnauthorizedReceived(context) || !SignalStore.account().isRegistered();
}
}

View File

@@ -1,51 +0,0 @@
package org.thoughtcrime.securesms.components.reminder
import android.content.Context
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.keyvalue.AccountValues.UsernameSyncState
import org.thoughtcrime.securesms.keyvalue.SignalStore
/**
* Displays a reminder message when the local username gets out of sync with
* what the server thinks our username is.
*/
class UsernameOutOfSyncReminder : Reminder(NO_RESOURCE) {
init {
val action = if (SignalStore.account.usernameSyncState == UsernameSyncState.USERNAME_AND_LINK_CORRUPTED) {
R.id.reminder_action_fix_username_and_link
} else {
R.id.reminder_action_fix_username_link
}
addAction(
Action(
R.string.UsernameOutOfSyncReminder__fix_now,
action
)
)
}
override fun getText(context: Context): CharSequence {
return if (SignalStore.account.usernameSyncState == UsernameSyncState.USERNAME_AND_LINK_CORRUPTED) {
context.getString(R.string.UsernameOutOfSyncReminder__username_and_link_corrupt)
} else {
context.getString(R.string.UsernameOutOfSyncReminder__link_corrupt)
}
}
override fun isDismissable(): Boolean {
return false
}
companion object {
@JvmStatic
fun isEligible(): Boolean {
return when (SignalStore.account.usernameSyncState) {
UsernameSyncState.USERNAME_AND_LINK_CORRUPTED -> true
UsernameSyncState.LINK_CORRUPTED -> true
UsernameSyncState.IN_SYNC -> false
}
}
}
}

View File

@@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.View
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.viewModels
@@ -13,9 +12,6 @@ import androidx.navigation.fragment.findNavController
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.signal.core.util.isNotNullOrBlank
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.badges.BadgeImageView
@@ -24,10 +20,6 @@ import org.thoughtcrime.securesms.banner.banners.OutdatedBuildBanner
import org.thoughtcrime.securesms.banner.banners.UnauthorizedBanner
import org.thoughtcrime.securesms.components.AvatarImageView
import org.thoughtcrime.securesms.components.emoji.EmojiTextView
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder
import org.thoughtcrime.securesms.components.reminder.Reminder
import org.thoughtcrime.securesms.components.reminder.ReminderView
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
@@ -38,13 +30,10 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaym
import org.thoughtcrime.securesms.components.settings.app.subscription.completed.InAppPaymentsBottomSheetDelegate
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
import org.thoughtcrime.securesms.events.ReminderUpdateEvent
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.ui.RegistrationActivity
import org.thoughtcrime.securesms.util.Environment
import org.thoughtcrime.securesms.util.PlayStoreUtil
import org.thoughtcrime.securesms.util.RemoteConfig
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.ViewUtil
@@ -62,17 +51,15 @@ class AppSettingsFragment : DSLSettingsFragment(
private val viewModel: AppSettingsViewModel by viewModels()
private lateinit var reminderView: Stub<ReminderView>
private lateinit var bannerView: Stub<ComposeView>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewLifecycleOwner.lifecycle.addObserver(InAppPaymentsBottomSheetDelegate(childFragmentManager, viewLifecycleOwner))
super.onViewCreated(view, savedInstanceState)
reminderView = ViewUtil.findStubById(view, R.id.reminder_stub)
bannerView = ViewUtil.findStubById(view, R.id.banner_stub)
updateReminders()
updateBanners()
}
override fun bindAdapter(adapter: MappingAdapter) {
@@ -85,69 +72,31 @@ class AppSettingsFragment : DSLSettingsFragment(
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEvent(event: ReminderUpdateEvent?) {
updateReminders()
}
private fun updateReminders() {
if (RemoteConfig.newBannerUi) {
val bannerFlows = listOf(
OutdatedBuildBanner.createFlow(requireContext(), OutdatedBuildBanner.ExpiryStatus.EXPIRED_ONLY),
UnauthorizedBanner.createFlow(requireContext())
)
val bannerManager = BannerManager(bannerFlows)
bannerManager.setContent(bannerView.get())
} else {
if (ExpiredBuildReminder.isEligible()) {
showReminder(ExpiredBuildReminder(context))
} else if (UnauthorizedReminder.isEligible(context)) {
showReminder(UnauthorizedReminder())
} else {
hideReminders()
private fun updateBanners() {
val bannerFlows = listOf(
OutdatedBuildBanner.createFlow(requireContext(), OutdatedBuildBanner.ExpiryStatus.EXPIRED_ONLY),
UnauthorizedBanner.createFlow(requireContext())
)
val bannerManager = BannerManager(bannerFlows,
onNewBannerShownListener = {
if (bannerView.resolved()) {
bannerView.get().addOnLayoutChangeListener { _, _, top, _, bottom, _, _, _, _ ->
recyclerView?.setPadding(0, bottom - top, 0, 0)
}
recyclerView?.clipToPadding = false
}
},
onNoBannerShownListener = {
recyclerView?.clipToPadding = true
}
}
)
bannerManager.setContent(bannerView.get())
viewModel.refreshDeprecatedOrUnregistered()
}
private fun showReminder(reminder: Reminder) {
if (!reminderView.resolved()) {
reminderView.get().addOnLayoutChangeListener { _, _, top, _, bottom, _, _, _, _ ->
recyclerView?.setPadding(0, bottom - top, 0, 0)
}
recyclerView?.clipToPadding = false
}
reminderView.get().showReminder(reminder)
reminderView.get().setOnActionClickListener { reminderActionId: Int -> this.handleReminderAction(reminderActionId) }
}
private fun hideReminders() {
if (reminderView.resolved()) {
reminderView.get().hide()
recyclerView?.clipToPadding = true
}
}
private fun handleReminderAction(@IdRes reminderActionId: Int) {
when (reminderActionId) {
R.id.reminder_action_update_now -> {
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext())
}
R.id.reminder_action_re_register -> {
startActivity(RegistrationActivity.newIntentForReRegistration(requireContext()))
}
}
}
override fun onResume() {
super.onResume()
viewModel.refreshExpiredGiftBadge()
EventBus.getDefault().register(this)
}
override fun onPause() {
super.onPause()
EventBus.getDefault().unregister(this)
}
private fun getConfiguration(state: AppSettingsState): DSLConfiguration {